ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

分布式系统开发实战:锁、事务、缓存与分布式ID解析

分布式系统开发实战:锁、事务、缓存与分布式ID解析 1. 分布式架构先摸清“团建”的底层逻辑分布式系统这个词在技术圈被聊得最多也最容易被聊糊。一搜“分布式”出来的全是分布式锁、分布式事务、分布式缓存、分布式架构、分布式爬虫、分布式定时任务、分布式UUID……知识点碎得跟一地零件似的。在Java分布式系统开发这个方向上这些几乎就是必修课。我自己的体会是与其死记这些名词不如换个角度把一群服务器当成一支团队。分布式系统说白了就是组织一场“分布式团建”——每个节点都是独立个体有自己算力、自己内存、自己的磁盘网络还可能随时抖动而你要做的就是让这群“性格各异”的节点像同一个团队一样协作完成一件单机干不了的事。这篇文章我就按这个思路把分布式里最常见的几个技术点挨个拆开讲连命令、代码、踩坑记录一起给你摆出来。1.1 单机撑不住的时候就是需要“团队”的时候先用大白话说清楚为什么要分布式。单机时代一台服务器吃喝拉撒全包接收请求、处理业务、读写数据库、存文件。它能扛的并发量其实就是靠线程池堆扛不住就加内存、加CPU也就是“垂直扩容”。垂直扩容有个硬天花板机器配置越往上越贵而且到了一定规模后加了配置也不一定线性提升性能。我做过一个纯单机的接口八核十六G的机器压测到2000 QPS就开始出现明显抖动线程池排队、GC频繁再加内存也只是延迟问题爆发的时间。更重要的是可用性。再好的服务器也有宕机的一天重启、断电、硬件老化、机房故障随便哪个都够单点喝一壶。一旦这台机器挂了整个业务全断用户直接骂街。分布式要解决的核心问题不外乎三个一是性能扩展让多个节点分担请求压力二是可用性一个节点挂了其他节点接着顶三是数据容量单机磁盘不够用时把数据分散到多台机器上。这也是为什么现在大家张口就是“分布式架构”“分布式算力”——本质上是想用一群便宜、普通甚至偶尔不稳定的机器拼出一台“可靠的大机器”。1.2 节点、注册中心与CAP团队协作的基本规则分布式架构里每个独立运行的进程就是一个节点。节点和节点之间要通信就得通过网络比如HTTP、RPC、消息队列。但光能通信不够上游调用下游怎么知道下游在哪、有几个这就轮到注册中心登场了。常见的注册中心有Nacos、Eureka、Consul、ZooKeeper服务启动时往注册中心登记自己的IP和端口调用方再去注册中心拉取服务列表动态选一个来调这就是“服务发现”。配置中心则用来统一管理所有节点的配置修改一个配置项不需要一台台机器去改文件推送到所有节点就行。这就像是团建前的分工表和统一口径没有这两样几十个节点各怀心思协作根本无从谈起。这套协作框架不仅在应用层成立网络设备领域的分布式交换机系统架构比如VxLAN、SDN控制器本质也是把控制面和数据面分离到不同节点采用同样的协调思想。讲分布式绕不开CAP理论。C是一致性A是可用性P是分区容忍性。分布式系统里网络分区一定会发生所以P必须选剩下C和A只能二选一。理解CAP的要点在于所谓“取舍”不是说系统完全不要一致性或者完全不要可用性而是说在极端场景下选择优先保全哪一边。比如注册中心Nacos默认是AP模式允许短暂的数据不一致保证服务调用不中断而像ZooKeeper则更偏CP节点挂了之后宁可暂时不可用也要保证数据一致。实际做架构选型时第一件事就是问自己业务在分区发生时更怕数据错还是更怕服务停1.3 分布式的本质在不可靠环境里达成共识如果让我用一句话概括分布式系统的本质就是“在不可靠的环境里达成共识”。网络会断、机器会宕、消息会延迟但业务还是得跑数据还是得对。分布式锁是让多个节点对“谁进临界区”达成共识分布式事务是让多个服务对“业务到底成没成”达成共识分布式ID是让所有节点对“编号不重复”达成共识。只要带着这个视角去学你会发现分布式技术不是一堆孤立的方案而是一套围绕“共识”展开的组合拳。后面几章我按这个逻辑一个个拆。2. 分布式锁团队里只有“一杆话筒”团建里最怕抢话发言没秩序一个项目就乱套。分布式里的“抢话”就是多个节点同时操作同一个共享资源。典型场景是库存扣减、秒杀下单、账号提现、分布式定时任务防重。分布式锁的使用场景基本都逃不开这几个。2.1 为什么单机锁到了分布式环境就失灵单机环境下我们用synchronized、ReentrantLock就能把并发线程挡在门外但分布式环境下多个请求可能被负载均衡分发到不同的节点上每个节点有自己的JVM锁谁也锁不住别人。我举个真实例子。做一个秒杀接口商品库存只有10件前端一放开10000个请求进来。第一个节点先查库存发现还有10件刚要执行UPDATE库存减1同一瞬间另一个节点也查到了10件两个节点都认为自己扣减成功最后库存只减了1超卖就发生了。解决思路是让多个节点去访问一个公共的“锁服务”谁拿到锁谁才有资格操作共享资源。这个公共锁服务就是分布式锁。Redis分布式锁为什么能做这事因为Redis是单线程执行命令命令之间有天然的原子性。只要多个节点都去同一个Redis实例上执行SETNX同时只能有一个节点设置成功这就形成了“一杆话筒”的效果。2.2 Redis分布式锁的经典写法和那点“坑”目前最常见的分布式锁实现是Redis核心是SET命令加NX和PX参数SET lock:order:1001 1 NX PX 30000这条命令的含义是只有当lock:order:1001这个key不存在时才设置成功同时设置30秒过期时间。设置成功就说明拿到了锁业务处理完再释放锁。释放锁不能直接DEL因为你可能拿到锁之后业务执行超过了30秒锁已经自动过期被别人拿走了再DEL就误删别人的锁了。所以要带上身份校验用Lua脚本保证判断和删除的原子性if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end这里ARGV[1]是加锁时写入的唯一标识一般是UUID加线程ID用来标识“这把锁是我拿的”。工程上我更推荐直接用Redisson它把加锁、解锁、续期都封装好了。Redisson会为锁启动一个“看门狗”机制默认锁30秒如果业务还没执行完看门狗会自动把锁续期避免业务没跑完锁先过期的问题。RLock lock redissonClient.getLock(stock:sku:1001); if (lock.tryLock(3, 30, TimeUnit.SECONDS)) { try { // 扣库存业务逻辑 } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } }tryLock第一个参数是等待锁的时间第二个是锁的有效期需要结合业务执行时间压测来定别死记参数。坑主要在两方面一是Redis主从切换导致锁丢失如果主节点还没把锁数据同步到从节点就挂了新主节点上这把锁就没了另一个节点就能拿到同一把锁产生并发问题。Redis官方提出过RedLock算法让客户端向多个独立的Redis实例同时申请锁超过半数成功才算加锁成功但RedLock本身争议很大工程上应用不多。实践中的常规做法是充分评估业务对“锁失效窗口”的容忍度必要时改用ZooKeeper、etcd这类带强一致语义的锁服务。2.3 ZooKeeper、etcd锁更稳但是更重ZooKeeper实现分布式锁用的是临时顺序节点。多个节点同时在一个锁路径下创建临时顺序节点序号最小的节点拥有锁其他节点监听自己前一个节点的删除事件前一个节点释放锁就轮到下一个。由于ZooKeeper节点是强一致模型同时只有一个节点能拿到锁所以不会有Redis主从切换导致的锁丢失问题。缺点也很明显性能不如Redis加锁解锁要多轮网络交互而且需要维持Session客户端一旦和ZK断开会话临时节点会被删除锁也会释放。etcd用Revision机制实现锁思路类似但是etcd的线性一致性读在分布式协调场景下更可靠云原生项目里用得越来越多。三者的选择可以简单粗暴地这样记追求性能、业务允许短时间锁异常选Redis业务强一致敏感、锁生命周期短、并发量不太大选ZooKeeper或etcd。如果问我的话除了强一致场景我基本都是Redis毕竟部署运维成本最低出问题也好排查。2.4 分布式锁面试题绕不开的几个问题聊到分布式锁面试官最爱问的几个问题大概是Redis分布式锁过期了怎么办比如业务超时导致锁被自动释放其他节点进入临界区。解法就是上面说的看门狗自动续期或者结合业务做幂等兜底。再问锁的粒度怎么设计答案是锁的key尽量细化锁用户维度就别锁全表锁商品维度就别锁订单锁粒度越细并发度越高。还会问可重入怎么做Redisson里默认就是可重入的它内部用hash结构记录持有锁的线程和计数同一线程重复tryLock会累加计数释放一次减一次减到0才真正释放。这些题没有标准答案核心是理解分布式锁的本质它是在不可靠的网络上让多个节点对“只有一个赢家”达成共识。3. 分布式事务与一致性团建要求“全员行动一致”3.1 订单和库存的“跨库难题”为什么会有分布式事务因为微服务化之后数据被拆开了。一个下单流程涉及订单服务、库存服务、积分服务每个服务的数据都放在自己的数据库里。本地事务只能保证自己的库跨库、跨服务的事务本地事务就管不到了。我用一个大家都懂的“订单与库存分布式事务”场景来说明。用户下单支付成功后假设业务规则是订单表落一条记录库存表减一个SKU数量用户积分表加积分。如果订单落库成功、库存扣减失败怎么办用户看不到订单但可能已经扣了钱如果库存扣了但订单失败了库存白白少一件。传统单机数据库一条SQL能解决的事在分布式环境下要设计一套跨服务的一致性方案。分布式事务的思路不是“数字上完全同时成功”而是“最终都成功或者都已经明确失败并补偿”。这就要分清两种模型强一致模型和最终一致模型。3.2 强一致方案2PC、TCC、SAGA强一致的代表方案是两阶段提交2PC。事务协调者先问所有参与者“准备好了吗”也就是第一阶段prepare所有参与者都返回OK后协调者再发commit指令让所有人同时提交。2PC的弊端也众所周知协调者是单点prepare之后如果协调者挂了所有参与者都在等着资源被长时间锁定性能很差所以在互联网高并发场景下基本不直接用。TCC则把事务拆成Try、Confirm、Cancel三个动作。Try阶段完成资源预留和业务检查比如冻结库存Confirm阶段真正执行业务扣减预冻的库存Cancel阶段回滚释放资源。TCC优点是业务控制力强缺点是要为每个操作写三套逻辑开发量翻倍适合银行转账这类对一致性要求极高的场景。SAGA则把一个长事务拆成一系列子事务每个子事务都有对应的补偿操作按顺序执行某一步失败就按逆序执行补偿。SAGA更贴近业务流程但补偿逻辑设计复杂而且中间状态对外可见需要考虑业务是否接受。考虑到多数互联网业务其实没那么强一致我更推荐下面的最终一致方案。3.3 最终一致性本地消息表与消息队列最终一致的核心思想是“先保住本地事务然后通过异步不断重试确保最终都落地”。最经典的是本地消息表方案流程大概是这样的订单服务在自己的本地事务里同时做两件事写订单数据写一条消息记录到本地消息表状态为“待发送”。本地事务提交后订单服务启动一个定时任务扫描消息表中状态为“待发送”的记录把消息发送到MQ。库存服务消费MQ里的消息执行库存扣减处理成功后回调订单服务把消息状态更新为“已发送/已处理”。如果库存服务处理失败或者MQ消息丢失本地消息表里的消息一直没被确认定时任务就会重发。重发时消费方要处理幂等也就是重复消息不能重复扣库存。这套方案的关键点有两个第一业务操作和写消息必须在同一个本地事务里这是“最终一致”的起点第二消息表和定时任务要设计好防止消息积压和重复发送。后来出现的RocketMQ事务消息其实就是把本地消息表搬到了MQ内部思路完全一致。如果不想自己开发可以使用Seata框架。Seata的AT模式对业务侵入很小它通过全局事务管理器记录数据快照业务SQL正常写Seata自动完成回滚。AT模式适合“单库不大、SQL相对简单”的业务性能比TCC好但快照管理和全局锁会有额外开销需要压测确认。简单说TCC适合高一致性高控制力MQ最终一致适合高并发高吞吐Seata适合想快速落地、业务逻辑不太复杂的团队。3.4 选型的真实经验别为了分布式事务而事务我见过不少团队业务量一天就几万单非要把简单的下单流程搞成TCC三套逻辑结果开发周期翻倍线上问题还更多。我的建议是先用本地事务加消息表把最终一致做起来订单状态单独用一张状态机表维护补偿逻辑写在定时任务里。等到订单量确实大到消息表成了瓶颈或者业务确实需要实时强一致再引入分布式事务中间件。分布式事务是最后的武器不是常规的默认姿势。4. 分布式缓存与ID公告栏和工牌号4.1 缓存三大问题穿透、击穿、雪崩分布式系统里缓存几乎是标配它的作用是在数据库前面加一层“公共公告栏”读请求先看公告栏有就直接返回没有再查库再回填。最常见的实现是Redis和数据库构成Cache Aside模式读的时候先读缓存读不到读数据库然后回写缓存写的时候先是更新数据库再删除缓存。但这套模式有几个知名大坑。第一个是缓存穿透请求查询一个数据库中根本不存在的数据缓存永远没有请求每次都会打到数据库。大量恶意请求用不存在的ID刷你接口数据库很快被打垮。解决手段是布隆过滤器把所有合法ID预先放进过滤器查询前先判断ID是否存在不存在直接拒绝。第二个是缓存击穿某个热点key的缓存刚好过期一瞬间大量请求同时回源查库数据库被瞬时打爆。解决方案是加互斥锁只允许一个请求去重建缓存其他请求等待更简单粗暴的方法是逻辑过期也就是不给key设置物理过期时间而是在value里存一个过期时间戳后台异步刷新。第三个是缓存雪崩大量key在同一时间过期或者Redis实例宕机所有请求一起打到数据库数据库直接崩掉。解决思路是过期时间加随机抖动不要把过期时间设成同一个值同时做多级缓存本地缓存一份Redis一份数据库最后兜底。真遇到Redis宕机还要有降级预案比如直接走数据库限流。4.2 分布式ID为什么不用UUID团建要给人发工牌每个人都要有一个不重复的编号。在分布式系统里这个编号就是分布式ID。最常见的做法是数据库自增ID但数据库一旦分库分表每个表自己自增就会重复。有人会用UUID全局唯一没问题但UUID无序、太长32位字符串存进数据库当主键索引体积变大写入时还因为随机性导致页分裂性能比自己增ID差很多。所以业界普遍用雪花算法Snowflake。一个64位的long型ID组合为1位符号位不用 41位时间戳毫秒级可以支撑约69年 10位机器ID支持最多1024台机器 12位序列号同一毫秒内支持4096个不重复ID。这个结构的好处是趋势递增查询索引友好而且不需要中心化节点每个机器自己生成就行。public class SnowflakeIdWorker { private final long twepoch 1288834974657L; private final long workerIdBits 5L; private final long datacenterIdBits 5L; private final long sequenceBits 12L; private long workerId; private long datacenterId; private long sequence 0L; private long lastTimestamp -1L; public synchronized long nextId() { long timestamp System.currentTimeMillis(); if (timestamp lastTimestamp) { throw new RuntimeException(时钟回拨拒绝生成ID); } if (timestamp lastTimestamp) { sequence (sequence 1) 4095; if (sequence 0) { timestamp tilNextMillis(lastTimestamp); } } else { sequence 0; } lastTimestamp timestamp; return ((timestamp - twepoch) 22) | (datacenterId 17) | (workerId 12) | sequence; } }这段代码只是个骨架真正落地时要注意几个问题。时钟回拨是雪花算法的经典隐患服务器NTP时间同步往前跳同一个毫秒内生成的ID可能会重复。解决思路有几种回拨时间小于阈值时等待大于阈值时拒绝服务或者用ZooKeeper等外部组件记录上一次生成ID的时间戳用内存默认值兜底。机器ID的分配也要管理最好有个配置平台下发避免两台机器用同一个机器ID导致ID冲突。4.3 分布式IO与跨节点通信的底层形态分布式节点之间要交换数据绕不开网络IO。常见的有两种编程模型传统BIO每一个连接要一个线程连接多了线程数爆炸而NIO通过事件驱动一个线程可以管理成千上万个连接。像Netty框架就是基于NIO的典型实现很多RPC框架的底层通信都建立在它之上。EventLoopGroup bossGroup new NioEventLoopGroup(1); EventLoopGroup workerGroup new NioEventLoopGroup(); ServerBootstrap bootstrap new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializerSocketChannel() { Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new StringEncoder()); } }); bootstrap.bind(8080).sync();这段代码就是一个最简单的Netty服务端骨架两个线程组分别负责接受连接和处理IO事件。理解了NIO你就会明白为什么分布式系统里一个节点撑几万连接不稀奇。有些特殊领域也会用到“分布式驱动”的思想比如Trucksim这类车辆动力学仿真软件做多机联合仿真时把整车模型拆成多个子模块每个子模块跑在一台机器上通过网络同步状态数据本质上也是分布式协同。你把这套底层模型搞清楚再去看Hadoop伪分布式、分布式爬虫、分布式算力都会觉得顺理成章。5. 分布式定时任务与爬虫值班表和分头行动5.1 分布式定时任务防止“全员重复值班”定时任务在老系统里就是一台服务器的cron表到点执行。分布式环境下问题来了多个节点上如果都部署了定时任务同一个任务会被重复执行比如每天凌晨给用户发短信结果三个节点各发一遍用户得被短信轰炸。要解决这个问题要么用分布式锁把任务锁起来要么用专门的分布式任务调度框架。最简单的方式是ShedLockSpring生态里常用的轻量方案。它的原理其实就是在数据库或Redis里记录一把锁任务执行前先尝试加锁加锁成功才执行。配置一个锁的有效期确保任务执行期间锁不会被释放还要注意任务崩溃后锁要能自动过期别把任务卡死。Spring Cloud架构下任务简单数量少的场景ShedLock或者Quartz集群已经够用。真正复杂的定时任务场景比如需要分片处理几十万条数据、需要失败重试、需要动态调整任务建议用XXL-JOB或ElasticJob。XXL-JOB是中心化架构调度中心负责任务管理、触发、日志执行器部署在业务节点上负责干活。一个任务可以在多个执行器上做分片比如10台机器轮流处理用户列表每台处理十分之一效率一下就上去了。ElasticJob则更偏分布式架构没有集中调度中心用的ZooKeeper做注册和协调适合高可用要求更高的场景。我的建议很简单任务复杂需要管理界面和分片直接上XXL-JOB运维和排障体验好得多。5.2 分布式爬虫任务分派与结果汇总分布式爬虫和分布式定时任务其实是一对兄弟都是“把一个大任务拆成很多小任务分给多个节点干”。设计思路通常是Master节点维护一个待抓取URL队列一般用Redis的List或Set存储多个Worker节点启动时从Master同步队列任务抓到页面后解析出新的URL回填到队列抓取失败的URL要进入重试队列最后结果统一写入数据库或消息队列。这里有个很容易被忽视的细节URL去重。一个网站内页互相链接同一个URL可能被多个Worker抓到不去重的话爬虫效率极低还可能把目标站搞垮。去重用Redis的Set集合数据量小的时候问题不大数据量超过千万级别就要用布隆过滤器牺牲少量误判率换取极低的内存占用。为了防止请求频率过高被目标站点封IPWorker节点还要维护代理池定期换IP。你认真想想这套架构和后台系统的任务调度没有任何本质区别理解了“任务分派 结果回收 去重幂等”这个套路分布式爬虫基本就是手到擒来。6. 常见问题与排查技巧实录6.1 三个经典故障脑裂、超时重试、幂等分布式系统里我遇到最多的三类故障第一类就是脑裂。所谓脑裂就是网络分区后一部分节点联系不上主节点它们自己选出一个新的主节点导致系统里同时出现两个“主”。数据库主从切换、消息队列的leader选举、ZooKeeper集群都可能遇到。处理脑裂的核心是“多数派原则”也就是只有获得超过一半节点投票的候选者才能当主也就是Quorum机制。设计系统时对每个选举和写操作都要问一句如果分区发生系统会不会出现两个大脑第二类是超时重试引发的数据重复。分布式调用不可避免会超时超时后通常会重试。但如果第一次请求其实已经成功只是响应超时重试就会让服务方执行两次。比如支付回调很可能因为网络延迟导致支付网关回调重复发送。解决方法是消费方做幂等用订单号和事件类型生成一个唯一约束处理前先去Redis查一下这个事件是否处理过或者数据库加唯一索引。幂等是分布式开发里最重要的基础功。第三类是级联故障。上游服务没做降级和限流依赖的下游服务出现慢查询导致上游线程全部阻塞最后整个链路雪崩。排查时先看慢调用拓扑找到拖后腿的节点再针对它做熔断降级。6.2 排查手段链路追踪、日志与监控分布式问题最麻烦的地方是“不知道请求到底走了哪些节点”。几十个微服务一个请求来回跳好几跳出了问题看每个服务自己的日志根本连不起来。所以一定要在最开始就把链路追踪做好最简单的办法是每个请求入口生成一个traceId塞进日志里各服务打印日志时都带上它排查时按traceId一把梭。更专业的方案是用SkyWalking或Zipkin自动采集调用链数据在界面上直接看到每个请求调用了哪些服务、每跳耗时是多少、哪一段变慢了。日志输出也要注意几条经验一是全链路必须保持同一套时间标准服务器都同步好时钟不然排查时时间对不上二是日志要带业务标识单号、用户ID、订单ID都要出现在日志里三是日志里别打印敏感信息比如密码、手机号明文等出安全事故就麻烦了。监控则要覆盖基础指标CPU、内存、磁盘、GC、线程数、数据库连接池占用、Redis命中率、MQ积压量。这些指标不一定要全但关键节点一定要有不然故障一发生你连“现在到底谁出了问题”都不知道。6.3 高频问题速查表问题表现可能原因排查方向常用解法分布式锁偶尔失效Redis主从切换、锁未续期查Redis集群状态、客户端日志用Redisson看门狗、必要时换etcd定时任务重复执行多节点未做互斥查看任务调度日志ShedLock、XXL-JOB分片幂等消息重复消费消费端未做幂等查看MQ消费日志、数据库是否重复唯一索引、Redis幂等标记接口突然变慢缓存穿透、击穿、雪崩看缓存命中率、数据库慢SQL布隆过滤器、互斥锁重建、过期时间抖动支付回调重复处理网络重试、回调重复推送按订单号查操作流水幂等表加唯一索引服务间调用超时线程池被打满、慢SQL、网络抖动链路追踪看瓶颈节点、线程dump熔断降级、连接池调优集群脑裂网络分区、选举机制不合理检查节点心跳、投票记录多数派机制、踢出孤岛节点ID冲突雪花算法时钟回拨、机器ID重复查看生成ID的机器标识和时间戳时钟回拨处理、机器ID统一管理这张表是我实际工作中反复遇到的场景汇总不全面但足够覆盖多数团队前期的分布式踩坑需求。6.4 从伪分布式开始学习一套组合拳如果你是一名刚开始接触分布式的新手别一上来就折腾K8s、微服务全家桶。我建议从Hadoop伪分布式搭建入门。所谓伪分布式就是在一台机器上把HDFS的NameNode、DataNode以及YARN的ResourceManager、NodeManager这些进程分别起出来每个进程扮演一个“虚拟节点”。虽然都在同一台机器上但它们的通信方式、数据读写流程、主备切换机制和真实集群完全相同。你可以在上面练习HDFS文件读写、提交MapReduce任务、观察数据块分布这套东西跑通一遍对“分布式到底在协调什么”的体感会比只看文档强得多。搭建过程不复杂准备一台Linux机器装好JDK下载Hadoop安装包配置SSH免密登录修改core-site.xml、hdfs-site.xml、yarn-site.xml三个文件然后执行start-dfs.sh、start-yarn.sh访问对应端口就能看到集群状态。伪分布式的意义不在于能抗多大并发而在于让你低成本地理解NameNode如何管理元数据、DataNode如何汇报心跳、任务如何被调度。等你想通了这些再回来看微服务那套注册中心、负载均衡、配置中心会发现都是同一个思想在具体场景里的不同变形。分布式开发这几年一直是面试重点也是工程难点但说白了就是一群人节点在不可靠的环境里齐步走。你按“团建”的思路去理解先理清角色分工架构设计再管好发言秩序分布式锁然后统一行动标准分布式事务最后设计好公告栏和工牌缓存和ID多数场景都能找到清晰的答案。我在实际项目中最大的体会是不要一上来就追求所有技术都上全套先把一个简单的分布式锁用明白把一条消息链路的幂等做扎实比堆砌一堆高大上的组件有用得多。架构是生长的不是装修出来的。真遇到拿不准的方案回到那句老话——如果这是一支团队你会怎么安排答案往往就在那里。
返回列表