网站建设技能考试aspcms 手机网站
2026/1/1 21:13:46 网站建设 项目流程
网站建设技能考试,aspcms 手机网站,浏览器打开网址404,网站产品关键词导出两个系统的故事想象一下#xff1a;高峰期到了,两家大型公司正在处理每秒数百万笔请求。悲观系统采用了我们上篇文章讨论的传统方法——在做任何更改之前锁定每条记录。他们的数据库就像一座狭窄的桥,一次只能通过一辆车。安全吗?绝对的。快吗?不见得。乐观系统则采用了完全…两个系统的故事想象一下高峰期到了,两家大型公司正在处理每秒数百万笔请求。悲观系统采用了我们上篇文章讨论的传统方法——在做任何更改之前锁定每条记录。他们的数据库就像一座狭窄的桥,一次只能通过一辆车。安全吗?绝对的。快吗?不见得。乐观系统则采用了完全不同的设计思路。他们的系统像一条多车道的高速公路,相信大多数时候车辆(请求)不会相撞。即便检测到潜在冲突,也能优雅地处理。到下午 2 点,悲观系统的响应时间已经爬升到每笔请求 3 秒以上。而乐观系统仍然以 200ms 的平均响应时间稳定运行,处理的请求量是前者的 10 倍。秘诀是什么乐观锁。什么是乐观锁?乐观锁基于一个简单的前提冲突很少发生,所以不必事先锁定一切。我们不在读取数据前获取锁,而是:读取数据及其版本号处理业务逻辑仅在版本号未改变时才尝试更新如果其他人同时修改了数据则重试这就像编辑共享的 Google 文档——你不会在思考写什么的时候锁定整个文档。只有当别人在你工作时更改了同一部分,你才会收到警告。真实场景Maria 的午夜购物狂欢来看看 Maria 的故事。她是个夜猫子,喜欢在午夜流量低的时候网购……至少她是这么认为的。Maria 的乐观银行账户里有 1000 美元。在凌晨 12:00 整,她:从科技商城订购了一台 400 美元的笔记本电脑从活动中心购买了 300 美元的音乐会门票从旅行公司预订了 350 美元的机票这三笔交易在几毫秒内同时到达银行的 API。看看乐观锁如何完美解决这个问题Laravel 实现让我们一步步构建,从数据库结构开始:步骤 1带版本列的数据库设置// 迁移文件为乐观锁添加版本列Schema::table(accounts, function (Blueprint $table) {$table-integer(version)-default(0)-after(balance);$table-index([account_number, version]);});步骤 2带版本跟踪的 Account 模型?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;use App\Exceptions\OptimisticLockException;class Account extends Model{protected $fillable [account_number, balance, version];protected $casts [balance decimal:2];/*** 乐观锁仅在版本匹配时更新*/public function updateBalanceOptimistically($newBalance, $expectedVersion null){$expectedVersion $expectedVersion ?? $this-version;$updated $this-newQuery()-where(id, $this-id)-where(version, $expectedVersion)-update([balance $newBalance,version $expectedVersion 1,updated_at now()]);if (!$updated) {throw new OptimisticLockException(账户 {$this-account_number} 已被其他交易修改);}// 更新模型实例$this-balance $newBalance;$this-version $expectedVersion 1;return $this;}}步骤 3自定义异常?phpnamespace App\Exceptions;class OptimisticLockException extends \Exception{public function __construct($message 资源已被其他交易修改){parent::__construct($message);}}步骤 4带重试逻辑的交易服务?phpnamespace App\Services;use App\Models\Account;use App\Models\Transaction;use App\Exceptions\OptimisticLockException;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Log;class OptimisticTransactionService{const MAX_RETRIES 3;const RETRY_DELAY_MS 50; // 50 毫秒public function transfer(string $fromAccount, string $toAccount, float $amount, string $reference){return $this-executeWithRetry(function() use ($fromAccount, $toAccount, $amount, $reference) {return DB::transaction(function() use ($fromAccount, $toAccount, $amount, $reference) {// 获取两个账户的最新副本及当前版本$sender Account::where(account_number, $fromAccount)-first();$receiver Account::where(account_number, $toAccount)-first();if (!$sender || !$receiver) {throw new \Exception(账户不存在);}// 业务逻辑验证if ($sender-balance $amount) {throw new \Exception(余额不足);}// 计算新余额$newSenderBalance $sender-balance - $amount;$newReceiverBalance $receiver-balance $amount;// 乐观更新关键就在这里$sender-updateBalanceOptimistically($newSenderBalance);$receiver-updateBalanceOptimistically($newReceiverBalance);// 记录交易$transaction Transaction::create([from_account $fromAccount,to_account $toAccount,amount $amount,reference $reference,status completed,sender_version_used $sender-version - 1,receiver_version_used $receiver-version - 1,]);Log::info(转账完成, [transaction_id $transaction-id,from $fromAccount,to $toAccount,amount $amount]);return $transaction;});});}private function executeWithRetry(callable $operation, int $attempt 1){try {return $operation();} catch (OptimisticLockException $e) {if ($attempt self::MAX_RETRIES) {Log::error(乐观锁重试次数超限, [attempts $attempt,error $e-getMessage()]);throw new \Exception(交易繁忙,请稍后重试);}Log::info(乐观锁冲突正在重试, [attempt $attempt,next_attempt_in_ms self::RETRY_DELAY_MS * $attempt]);// 指数退避每次重试等待更长时间usleep(self::RETRY_DELAY_MS * $attempt * 1000);return $this-executeWithRetry($operation, $attempt 1);}}}步骤 5API 控制器?phpnamespace App\Http\Controllers;use App\Services\OptimisticTransactionService;use Illuminate\Http\Request;use Illuminate\Http\JsonResponse;class TransferController extends Controller{public function __construct(private OptimisticTransactionService $transactionService) {}public function transfer(Request $request): JsonResponse{$validated $request-validate([from_account required|string,to_account required|string,amount required|numeric|min:0.01,reference required|string|max:255]);try {$transaction $this-transactionService-transfer($validated[from_account],$validated[to_account],$validated[amount],$validated[reference]);return response()-json([success true,transaction_id $transaction-id,message 转账成功]);} catch (\Exception $e) {return response()-json([success false,message $e-getMessage()], 400);}}}回到 Maria 的故事整个流程如何工作当 Maria 的三笔交易同时到达系统时:交易 A笔记本电脑读取 Maria 的账户余额$1000版本5交易 B音乐会同样读取账户余额$1000版本5交易 C机票同样的操作余额$1000版本5精彩的来了交易 A 首先完成更新余额为 $600版本为 6交易 B 尝试更新版本不匹配期望 5实际 6交易 B 重试读取最新数据余额$600版本6成功完成交易 C 尝试更新又一次版本不匹配使用最新数据重试交易 C 失败余额不足余额$300需要$350结果Maria 成功购买了笔记本电脑和音乐会门票,但机票预订失败,并收到清晰的错误消息。没有资金损失,没有数据不一致,所有这些都在 500ms 内完成性能优势数字说话在实际的高并发系统中,从悲观锁切换到乐观锁往往能带来显著提升:5 倍的交易吞吐量提升60%的平均响应时间缩减90%的数据库连接超时减少零数据一致性问题秘密武器大多数交易其实并不冲突。避免不必要的锁,数据库就能腾出手来处理更多并发操作。何时使用乐观锁最佳应用场景读多写少、冲突少的场景如文章阅读计数、商品浏览量电商系统的库存扣减并发购买同一商品社交应用的点赞、收藏功能用户积分、钱包余额的更新性能至关重要的高并发系统具有良好重试机制的应用不适用于冲突频繁的场景10% 的操作重试逻辑会影响用户体验的情况需要保证立即一致性的系统网络延迟导致重试成本过高的环境实战高级技巧1. 智能版本列// 使用时间戳而不是简单整数,便于更好的调试Schema::table(accounts, function (Blueprint $table) {$table-timestamp(version)-default(DB::raw(CURRENT_TIMESTAMP(6)));});2. 冲突指标监控// 添加监控以了解冲突率class OptimisticLockMetrics{public static function recordConflict($model, $operation){Cache::increment(optimistic_conflicts:{$model}:{$operation}:.now()-format(Y-m-d-H));}}3. 优雅降级// 在高冲突期间回退到悲观锁if ($this-getConflictRate() 0.1) {return $this-pessimisticTransfer($fromAccount, $toAccount, $amount);}总结乐观锁不仅是个数据库技巧——更是一种思维方式的转变。不再一上来就锁定一切,而是采用更聪明的策略只在冲突真正发生时才去处理。在高并发的互联网世界中,每一毫秒的延迟都会影响用户体验,每一次失败的请求都可能流失用户。乐观锁为我们提供了两全其美的方案极致的性能和坚如磐石的一致性。无论你构建的是电商平台、社交应用还是支付系统,当面对高并发场景时,请记住 Maria 的故事。有时候,保持乐观不仅有益于心理健康——对应用性能同样大有裨益。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询