说说分布式系统里那些同步机制,技术细节和干货都在这儿了
- 问答
- 2025-12-27 12:07:40
- 2
分布式系统就像一个大团队在不同的地方一起完成一个巨大的项目,团队成员之间必须沟通顺畅、步调一致,否则就会乱成一锅粥,这些让团队保持同步、避免混乱的规则和方法,就是分布式系统里的同步机制,下面我们就来详细聊聊这些机制,全是技术细节和干货。
最基础的同步:分布式锁
想象一下,团队只有一台打印机,但很多人要打印,为了避免打印内容混在一起,大家约定:谁拿到了“打印许可证”(一个实物令牌),谁才能去打印,分布式锁就是这个“许可证”。
- 技术细节:
- 目的: 保证在某个时刻,只有一个节点(团队成员)能执行一段关键代码(打印操作),比如防止商品超卖(扣减库存时)。
- 实现方式: 通常需要一个所有节点都认可的“公证人”来发放锁,这个公证人就是一个独立的协调服务。
- 核心实现(以Redis为例): 节点A要操作资源X,它向Redis服务器发送一个命令:
SET lock_resource_x unique_value NX PX 30000,这个命令的意思是:如果键lock_resource_x不存在(NX),就设置它,值为一个唯一标识(比如UUID),并设置30秒后过期(PX),如果设置成功,Redis返回OK,节点A就拿到了锁,节点B再来尝试设置,会因为NX条件不满足而失败,只能等待,节点A操作完后,需要用自己的唯一标识去删除这个键来释放锁,避免误删其他节点的锁。 - 关键问题与解决方案:
- 死锁: 如果节点A拿到锁后崩溃了,没来得及释放,锁就永远被占用了,所以锁必须设置一个过期时间,这就是上面命令中
PX 30000的作用。 - 误删: 如果节点A操作超时(比如操作花了35秒),锁已经自动过期被释放了,节点B拿到了锁,这时节点A操作完成,还去执行删除操作,就会把节点B的锁删掉,所以删除前要校验锁的值是否还是自己当初设置的那个
unique_value。
- 死锁: 如果节点A拿到锁后崩溃了,没来得及释放,锁就永远被占用了,所以锁必须设置一个过期时间,这就是上面命令中
- 更可靠的实现:ZooKeeper/etcd: Redis锁虽然快,但它的锁是“租约”性质的,靠过期时间失效,ZooKeeper这类系统通过临时顺序节点能实现更精准的控制,客户端在ZooKeeper的一个目录下创建一个临时顺序节点,ZooKeeper会保证只有序号最小的节点能获得锁,如果客户端与ZooKeeper的会话断开,临时节点会自动删除,锁自然释放,避免了死锁,其他节点监听自己前一个序号节点的删除事件,一旦前一个节点释放锁,自己就能被唤醒并获得锁,这种方式更安全,但性能通常不如Redis。
更复杂的协同:分布式事务
锁解决的是“串行化”访问的问题,但分布式事务要解决的是“原子性”问题:一个业务操作涉及跨多个数据库(或服务)的修改,要么全部成功,要么全部失败,不能只成功一部分。
- 技术细节:
- 两阶段提交(2PC): 这是最经典的模型,像一个“小组投票”。
- 阶段一(准备阶段): 事务协调者(项目经理)问所有参与者(组员):“我要做某某事,你们准备好了吗?能成功吗?”每个参与者检查自己的情况,如果没问题,就回复“可以”(Yes),并锁定相关资源,进入“预备状态”;如果不行,就回复“不行”(No)。
- 阶段二(提交/回滚阶段): 协调者收集所有投票,如果所有参与者都回复“可以”,协调者就发送“正式提交”指令,大家才真正执行修改,如果有任何一个参与者回复“不行”,协调者就发送“回滚”指令,所有参与者撤销在阶段一做的准备。
- 缺点: 同步阻塞严重,在阶段一准备完成后,所有参与者的资源都处于锁定状态,直到收到第二阶段的通知,如果协调者宕机,所有参与者都会“卡住”,不知道下一步该提交还是回滚。
- TCC模式(Try-Confirm-Cancel): 2PC是数据库层面的,TCC是业务层面的,需要开发者自己实现三个方法。
- Try: 对应2PC的准备阶段,但做的是业务检查和资源预留,比如下单操作,Try阶段不是直接扣库存,而是把库存“冻结”起来(可用库存减1,冻结库存加1),同样,不是直接扣钱,而是把资金冻结。
- Confirm: 如果所有服务的Try都成功了,就进入Confirm阶段,这里是执行真正的业务操作,将Try阶段冻结的资源进行扣减,Confirm操作需要保证幂等性(重复调用效果一样),因为网络问题可能导致重复调用。
- Cancel: 如果任何一个服务的Try失败,就进入Cancel阶段,释放Try阶段冻结的资源。
- 优点: 由业务代码控制,锁粒度更细,性能更好。缺点: 对业务侵入性强,实现复杂。
- 两阶段提交(2PC): 这是最经典的模型,像一个“小组投票”。
保证多副本数据一致性的基石:共识算法
在分布式系统中,为了高可用,数据通常会存多个副本,如何让所有副本的数据保持一致,特别是在有节点故障、网络分区的情况下,就需要共识算法,最著名的就是Paxos和它的变种Raft。
- 技术细节(以易于理解的Raft为例):
- 核心思想: “民主选举”和“多数派决议”,Raft集群中每个节点有三种角色:Leader(领袖)、Follower(追随者)、Candidate(候选人)。
- 选举Leader: 系统启动或Leader宕机后,所有Follower会等待一个随机超时时间,先超时的节点变成Candidate,向其他节点发起投票请求,如果获得超过半数的投票,它就晋升为新的Leader,从此,所有客户端的写请求都必须发给Leader。
- 复制日志(数据同步): Leader接收到写请求后,将其作为一个日志条目附加到自己的日志中,然后并行地将该条目复制给所有Follower,当Leader收到超过半数的Follower的成功响应后,就认为该日志条目是“已提交”的,可以安全地应用到状态机(即执行修改内存数据的操作),然后Leader通知Follower该条目已提交,Follower也将其应用到自己的状态机。
- 干货要点: Raft通过“选主”和“多数派”机制,保证了即使在部分节点故障的情况下,集群依然能对外提供一致的数据服务,它强依赖“大多数节点是好的”这个前提,etcd、Consul等知名协调服务的核心就是Raft算法。
其他重要的同步机制
- 分布式队列(如Kafka、RocketMQ): 它本身是一种异步通信机制,但也能起到同步作用,所有服务都把操作请求发到队列里,由消费者按顺序处理,这天然地实现了流量削峰和顺序控制。
- 屏障(Barrier): 类似于运动会上的“所有运动员各就各位,听到发令枪才能一起跑”,在分布式计算中(如MapReduce),一个任务可能需要等待所有前置任务都完成后才能开始,这个等待点就是屏障。
- 时钟同步: 虽然不像锁和事务那么直接,但分布式系统中所有机器保持时间同步至关重要,它用于判断事件的先后顺序(如谁先下单)、实现租约过期、生成全局有序的ID等,通常通过NTP协议与时间服务器进行同步。
分布式系统的同步机制是一个层层递进、根据业务场景权衡选择的过程,从最简单的互斥锁,到保证原子性的事务,再到维持全局状态的共识算法,每一种机制都是为了解决在分散、不可靠的网络环境下,如何让系统表现得像一个整体一样可靠、一致这个核心难题,理解这些机制的细节和取舍,是设计和构建健壮分布式系统的关键。

本文由盈壮于2025-12-27发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/69399.html
