分布式系统 文章

分布式系统并发控制:从单机锁到分布式锁的深度解析
后端
2024-05-06 0k

分布式系统并发控制:从单机锁到分布式锁的深度解析

引言 在分布式系统开发中,并发控制是一个永恒的话题。最近在代码评审时,我看到了这样一段代码: // 复杂操作仍需 lock public void ComplexOperation() { lock (_lockObj) { if (_count > 0 && _count < 100) { _count *= 2; // 其他复杂业务逻辑... } } } 这引发了一系列深入的讨论:如果锁里面执行的是用户下单操作,A用户下单过程中执行了1秒,B用户的请求会怎样?是直接失败还是等待?我们需要手动处理这种等待吗? 本文将围绕这个问题展开,深入探讨单机锁、细粒度锁、数据库事务和Redis分布式锁的优缺点及适用场景。 第一部分:单机锁的行为分析 锁的基本行为 当我们在C#中使用lock语句时,CLR会为我们管理一个等待队列: public void PlaceOrder(Order order) { lock (_lockObj) // 所有用户下单都串行化! { // 复杂的下单逻辑,耗时1秒... ProcessOrder(order); UpdateInventory(); // 其他业务... } } 关键结论:B用户会等待A用户执行完,而不是直接失败。整个过程是自动的,不需要人工干预。 具体执行流程 A用户进入lock块,开始执行下单操作(耗时1秒) B用户的线程到达lock语句时,发现_lockObj已被锁定 B线程会阻塞并等待,直到A线程释放锁 A用户执行完毕,释放锁 B线程获得锁,开始执行自己的下单操作 单机锁的严重问题 虽然锁机制自动处理了同步,但这种设计存在严重问题: 性能瓶颈:所有用户请求串行处理 响应时间变长:B用户需要等待A用户的1秒 + 自己的1秒 = 至少2秒 系统吞吐量下降:无法充分利用多核CPU优势 第二部分:解决方案对比 🥉 方案一:细粒度锁 private readonly Dictionary<string, object> _userLocks = new(); private readonly object _dictLock = new object(); public void PlaceOrder(string userId, Order order) { object userLock; lock (_dictLock) { if (!

分布式系统 并发控制 锁机制
阅读更多