架构师之路--分布式系统设计原理与实践(03)
系列导读本篇将深入讲解分布式系统的核心原理、设计模式与最佳实践。文章目录一、分布式系统概述1.1 什么是分布式系统1.2 分布式系统挑战二、CAP 理论与 BASE 理论2.1 CAP 理论2.2 BASE 理论三、分布式一致性3.1 一致性模型3.2 共识算法四、分布式锁4.1 Redis 分布式锁4.2 ZooKeeper 分布式锁五、分布式事务5.1 两阶段提交2PC5.2 TCC 模式5.3 最终一致性方案六、分布式 ID 生成6.1 方案对比6.2 雪花算法实现总结一、分布式系统概述1.1 什么是分布式系统分布式系统是多个独立计算机的集合对用户而言如同一个整体。┌─────────────────────────────────────────────────────────────┐ │ 分布式系统特征 │ ├─────────────────────────────────────────────────────────────┤ │ ️ 多节点多台计算机协同工作 │ │ 网络通信节点间通过网络交互 │ │ 数据分布数据分散存储在多个节点 │ │ ⚡ 并发处理多个节点并行处理请求 │ │ 容错能力部分节点故障不影响整体 │ └─────────────────────────────────────────────────────────────┘1.2 分布式系统挑战挑战说明网络不可靠网络延迟、分区、丢包节点故障硬件故障、进程崩溃数据一致性多副本数据同步时钟不同步分布式时钟问题二、CAP 理论与 BASE 理论2.1 CAP 理论Consistency (一致性) /\ / \ / \ / \ /________\ Availability Partition (可用性) Tolerance (分区容错)组合说明典型系统CP一致性 分区容错ZooKeeper、HBaseAP可用性 分区容错Cassandra、DynamoDBCA一致性 可用性单机数据库2.2 BASE 理论概念说明Basically Available基本可用允许损失部分可用性Soft State软状态允许中间状态Eventually Consistent最终一致性一段时间后达到一致三、分布式一致性3.1 一致性模型模型说明强一致性写入后立即可见最终一致性一段时间后可见因果一致性有因果关系的操作顺序一致3.2 共识算法┌─────────────────────────────────────────────────────────────┐ │ 共识算法对比 │ ├─────────────────────────────────────────────────────────────┤ │ Paxos经典共识算法复杂但完整 │ │ Raft易于理解工程实现友好 │ │ ZABZooKeeper 使用支持崩溃恢复 │ └─────────────────────────────────────────────────────────────┘四、分布式锁4.1 Redis 分布式锁publicclassRedisDistributedLock{AutowiredprivateStringRedisTemplateredisTemplate;privatestaticfinalStringLOCK_PREFIXlock:;privatestaticfinallongDEFAULT_EXPIRE30000;// 30秒/** * 加锁 */publicbooleantryLock(Stringkey,Stringvalue,longexpire){StringlockKeyLOCK_PREFIXkey;BooleanresultredisTemplate.opsForValue().setIfAbsent(lockKey,value,expire,TimeUnit.MILLISECONDS);returnBoolean.TRUE.equals(result);}/** * 解锁Lua脚本保证原子性 */publicbooleanunlock(Stringkey,Stringvalue){Stringscriptif redis.call(GET, KEYS[1]) ARGV[1] then return redis.call(DEL, KEYS[1]) else return 0 end;LongresultredisTemplate.execute(newDefaultRedisScript(script,Long.class),Collections.singletonList(LOCK_PREFIXkey),value);returnresult!nullresult1;}}4.2 ZooKeeper 分布式锁publicclassZkDistributedLock{privatefinalCuratorFrameworkclient;privateInterProcessMutexlock;publicZkDistributedLock(StringconnectString){clientCuratorFrameworkFactory.builder().connectString(connectString).retryPolicy(newExponentialBackoffRetry(1000,3)).build();client.start();}publicvoidlock(Stringpath){locknewInterProcessMutex(client,path);try{lock.acquire();}catch(Exceptione){thrownewRuntimeException(获取锁失败,e);}}publicvoidunlock(){try{if(lock!null){lock.release();}}catch(Exceptione){thrownewRuntimeException(释放锁失败,e);}}}五、分布式事务5.1 两阶段提交2PC┌─────────────────────────────────────────────────────────────┐ │ 两阶段提交流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 阶段一准备阶段 │ │ 协调者 ──► 参与者1: Prepare ──► 返回 Ready │ │ 协调者 ──► 参与者2: Prepare ──► 返回 Ready │ │ │ │ 阶段二提交阶段 │ │ 协调者 ──► 参与者1: Commit ──► 返回 Ack │ │ 协调者 ──► 参与者2: Commit ──► 返回 Ack │ │ │ └─────────────────────────────────────────────────────────────┘5.2 TCC 模式// TCC 接口定义publicinterfaceStockService{// Try: 预留资源TwoPhaseBusinessAction(nameprepareDeduct,commitMethodcommit,rollbackMethodrollback)booleanprepareDeduct(BusinessActionContextParameter(paramNameproductId)LongproductId,BusinessActionContextParameter(paramNamecount)Integercount);// Confirm: 确认扣减booleancommit(BusinessActionContextcontext);// Cancel: 取消预留booleanrollback(BusinessActionContextcontext);}// TCC 实现ServicepublicclassStockServiceImplimplementsStockService{OverridepublicbooleanprepareDeduct(LongproductId,Integercount){// 冻结库存returnstockMapper.freezeStock(productId,count)0;}Overridepublicbooleancommit(BusinessActionContextcontext){LongproductIdcontext.getActionContext(productId,Long.class);Integercountcontext.getActionContext(count,Integer.class);// 扣减冻结库存returnstockMapper.deductFrozenStock(productId,count)0;}Overridepublicbooleanrollback(BusinessActionContextcontext){LongproductIdcontext.getActionContext(productId,Long.class);Integercountcontext.getActionContext(count,Integer.class);// 释放冻结库存returnstockMapper.releaseFrozenStock(productId,count)0;}}5.3 最终一致性方案// 本地消息表 定时任务ServicepublicclassOrderService{AutowiredprivateOrderMapperorderMapper;AutowiredprivateMessageMappermessageMapper;TransactionalpublicvoidcreateOrder(Orderorder){// 1. 创建订单orderMapper.insert(order);// 2. 写入本地消息表MessagemessagenewMessage();message.setTopic(order_created);message.setContent(JSON.toJSONString(order));message.setStatus(0);// 待发送messageMapper.insert(message);}}// 定时任务扫描并发送消息Scheduled(fixedDelay5000)publicvoidsendPendingMessages(){ListMessagemessagesmessageMapper.selectPending();for(Messagemessage:messages){try{mqProducer.send(message.getTopic(),message.getContent());messageMapper.updateStatus(message.getId(),1);// 已发送}catch(Exceptione){log.error(发送消息失败,e);}}}六、分布式 ID 生成6.1 方案对比方案优点缺点UUID简单、无依赖无序、太长数据库自增简单、有序单点瓶颈Redis 生成高性能依赖 Redis雪花算法有序、高性能时钟回拨问题6.2 雪花算法实现publicclassSnowflakeIdGenerator{// 起始时间戳 (2024-01-01)privatefinallongtwepoch1704067200000L;// 机器ID所占位数privatefinallongworkerIdBits5L;privatefinallongdatacenterIdBits5L;// 最大机器IDprivatefinallongmaxWorkerId~(-1LworkerIdBits);privatefinallongmaxDatacenterId~(-1LdatacenterIdBits);// 序列号所占位数privatefinallongsequenceBits12L;// 位移privatefinallongworkerIdShiftsequenceBits;privatefinallongdatacenterIdShiftsequenceBitsworkerIdBits;privatefinallongtimestampLeftShiftsequenceBitsworkerIdBitsdatacenterIdBits;// 序列号掩码privatefinallongsequenceMask~(-1LsequenceBits);privatelongworkerId;privatelongdatacenterId;privatelongsequence0L;privatelonglastTimestamp-1L;publicSnowflakeIdGenerator(longworkerId,longdatacenterId){if(workerIdmaxWorkerId||workerId0){thrownewIllegalArgumentException(workerId 越界);}if(datacenterIdmaxDatacenterId||datacenterId0){thrownewIllegalArgumentException(datacenterId 越界);}this.workerIdworkerId;this.datacenterIddatacenterId;}publicsynchronizedlongnextId(){longtimestampSystem.currentTimeMillis();// 时钟回拨检测if(timestamplastTimestamp){thrownewRuntimeException(时钟回拨拒绝生成ID);}// 同一毫秒内if(lastTimestamptimestamp){sequence(sequence1)sequenceMask;if(sequence0){timestamptilNextMillis(lastTimestamp);}}else{sequence0L;}lastTimestamptimestamp;return((timestamp-twepoch)timestampLeftShift)|(datacenterIddatacenterIdShift)|(workerIdworkerIdShift)|sequence;}privatelongtilNextMillis(longlastTimestamp){longtimestampSystem.currentTimeMillis();while(timestamplastTimestamp){timestampSystem.currentTimeMillis();}returntimestamp;}}总结✅分布式系统概述定义、特征、挑战✅CAP/BASE 理论一致性、可用性权衡✅分布式一致性一致性模型、共识算法✅分布式锁Redis、ZooKeeper 实现✅分布式事务2PC、TCC、最终一致性✅分布式 ID雪花算法实现下篇预告领域驱动设计(DDD)实战指南作者刘~浪地球系列架构设计三更新时间2026-04-09