
我接触这个行当快十年了面试过不下两百个候选人发现有个特别有意思的现象很多干了三四年的开发你让他写CRUD溜得很一聊到“分布式”、“微服务”、“单体架构”这些词就开始含糊其辞。要么是背了一堆面试题但心里没底要么是把微服务当万能药张口闭口要上Spring Cloud。说白了大部分人没想明白一件事这些架构概念不是考试题它们是不同规模、不同阶段的业务演化出来的生存形态。今天这篇我不聊那些晦涩的论文定义就用大白话把这几个词拆开揉碎讲讲它们到底是什么、怎么选、以及分布式系统里那些绕不开的坑分布式锁、分布式事务、分布式缓存这些到底是怎么回事。写这篇文章的目的很直接如果你是刚入行的新人帮你建立一套完整的技术认知框架如果你是有几年经验的开发帮你把零散的知识点串成一条线下次面试或者做技术方案时脑子里的图是清晰的。1. 先把概念摆清楚单体、分布式、微服务到底在说什么这三个词听着高大上其实类比到现实生活里特别简单。你就把一套软件系统想象成一家餐厅。1.1 单体架构一个厨房所有菜都在这做单体架构英文叫Monolithic Architecture翻译过来就是“一块巨石”。最直白的理解就是一个应用程序包打天下代码、页面、数据库操作、业务逻辑全在一个项目里打成一个包比如一个JAR包或者WAR包部署在一台服务器上。这种模式就像街边的小饭馆老板、厨师、服务员、收银员往往是同一个人或者一两个人包圆。从买菜、洗菜、炒菜到端盘子上桌全在这个小厨房里完成。单体架构的核心特点就是开发简单、部署简单、调试简单。你改一行代码把整个应用重新打包部署一次就行了排查问题的时候从请求进来到数据库返回结果全链路都在一个进程里日志随便打断点随便断。很多中小型项目的技术选型早期都会从这个开始。你看那些知名的开源项目早期版本基本都是单体比如早期的电商系统、CMS系统甚至各种企业管理系统几年的代码全堆在一个工程里也是常态。1.2 分布式架构多个厨房协作但菜单统一当饭馆生意好起来了一个厨房忙不过来了老板是怎么干的他可能会在旁边再租个店面再搭个厨房。这两个厨房各炒各的菜但对外还是同一家店菜谱是一样的收银是统一的。这时候系统就不止一个节点了而是由多个独立的计算节点通过网络连接起来共同完成一个任务的系统——这就是分布式架构的基本形态。分布式架构的核心特征是“多个节点 网络通信 共同任务”。业务量上去了单台服务器扛不住最简单直接的方案就是把应用在多台服务器上部署多份前面加个负载均衡器把请求分发到不同的节点上。这就是最基础的水平扩展Scale-out。需要注意分布式架构并不等于微服务。分布式是描述系统物理部署和协同模式的微服务是一种更具体、更极端的架构风格。你可以有分布式的单体——也就是同一个单体应用复制部署到多台机器上但逻辑上它还是一个应用。也可以有微服务架构——不同的业务功能拆成多个独立服务分别部署在不同机器上服务之间通过接口调用。1.3 微服务架构一个档口一道菜各管各的微服务是近几年最火也最容易被滥用的概念。它的核心思想是不要把所有业务都塞进一个项目里而是把一个大型应用拆分成一组小服务每个服务独立部署、独立扩展各服务之间通过轻量级通信机制通常是HTTP RESTful API或消息队列互相调用。回到餐厅的比喻微服务就是把小饭馆升级成美食广场。一个档口专门做炒饭一个档口专门做麻辣烫一个档口专门做饮料。每个档口自己有完整的出餐流程自己的一套菜谱和操作标准甚至可以有独立的用餐区域。顾客想吃什么就去对应档口点。不同档口之间也有协作比如你点了一份炒饭和一杯饮料炒饭档口和饮料档口可以同时开工互不干扰。从这里你应该能看出来单体、分布式、微服务其实不是同一个维度上的对立关系。更准确地说单体是一种部署和开发形态分布式是一种系统架构模型微服务是服务拆分的一种组织和架构风格。现实中绝大多数微服务系统本身就是分布式系统。而单体系统在升级到微服务之前往往也会先走一步部署成分布式的形态。1.4 三者的关系与核心区别速览用一张表来对比信息会更清楚维度单体架构分布式架构广义微服务架构进程数量通常1个多个多个每个服务独立进程业务模块耦合度完全耦合取决于拆分粒度高度解耦各自独立部署方式单包部署多个节点部署同一应用每个服务独立打包部署扩展方式垂直扩展加硬件配置水平扩展加机器按服务维度独立扩展开发维护成本前期较低后期代码膨胀后高中等前期高运维复杂度大适用规模小型项目、早期产品中型项目、流量增长期大型复杂业务系统故障影响范围一个故障可能导致整个系统不可用部分节点故障可由其他节点接管单服务故障被隔离不影响整体前提是做好容错这里我要特别强调一点很多人一说微服务就觉得很高级一说单体就觉得是落后产物。这个观念大错特错。技术选型应该结合团队规模、业务复杂度、发展阶段来定。对大部分日活不过万的系统来说单体架构反而是最优解因为团队就那么几个人微服务带来的运维成本和开发复杂度会直接拖垮效率。这一点后面我会在选型建议里详细展开。2. 从单体到分布式再到微服务这条演进路是怎么走出来的理解了三个概念的基本定义接下来最关键的问题是为什么要演进是什么逼着架构越变越复杂这背后的逻辑如果搞清楚了你以后做技术方案会有方向感很多。2.1 单体是怎么撑不住的单体架构初期是很快的因为代码都在一个项目里业务之间的调用就是本地方法调用不存在网络开销也没有分布式事务的烦恼。但业务量上涨之后问题就慢慢浮出来了。第一个问题是性能瓶颈。当用户量增长到一定量级单台服务器的CPU、内存、带宽总有上限。你不可能无限地加高配置一台物理机比如64核、512GB内存的成本是指数级上升的而且总有物理极限。这时候唯一的出路就是多搞几台服务器把流量分一分。第二个问题是团队协作。一个单体仓库几十个人同时开发代码冲突、模块间相互牵制每次发版都得协调所有人的排期。前端改个样式后端就得陪着一起发布。业务模块之间耦合严重改一个下单逻辑可能要翻遍几十个文件确保不影响到支付逻辑。第三个问题是稳定性。单体应用是一个进程这个进程里任何一个小模块出现内存泄漏、死循环比如一个报表导出功能因为数据量过大导致内存溢出整个应用就挂了。你会遇到特别憋屈的场景深夜上线了一个小功能因为某个地方并发处理不当把整个服务搞崩了用户全被拒之门外。这些痛点催生了架构演进的原始动力。但演进不是一步到位的中间其实有一个非常关键的过渡环节。2.2 过渡阶段集群化和水平扩展单体撑不住了最自然的思路是什么不是立刻把业务拆开而是将这个单体应用在同一份代码的情况下复制部署到多台服务器上前面用Nginx做负载均衡把用户请求分散到不同节点。这就是集群化部署。这是最划算的起步方案。因为所有的节点跑的代码是一模一样的数据库还是那一套不存在数据一致性的问题也不需要服务间通信开发成本几乎没有增加只是增加了运维侧的工作量多部署几台机器而已。这是很多中型系统从单体迈向分布式的最常见一步。这种模式下系统从物理层面来讲已经是“多节点部署”了但逻辑上还是同一个应用所以我说它是“分布式的单体”。它不是微服务但它实实在在解决了一部分“扛不住”的问题。你会发现一个有意思的现象很多人嘴上把“微服务”叫做“分布式微服务”实际上微服务是基于分布式基础之上的一种更进一步的组织形态。分布式关注的是“多机器如何配合”微服务关注的是“业务如何拆分”。2.3 微服务的本质为了团队规模和独立演进当业务复杂度继续膨胀用户量大了业务线特别多比如电商领域的商品、订单、用户、支付、库存各业务团队的目标和迭代节奏完全不一样单体架构的牵制效应就成了严重的拖慢因素。这时候微服务的价值才真正体现出来。它带来的核心收益不是性能——事实上微服务由于网络通信的加入反而会比本地调用性能差——而是组织层面的松绑。每个服务由一个相对独立的团队维护服务可以按需独立部署、独立伸缩。比如大促期间只有订单服务流量暴涨那就只给订单服务加机器不需要把整个系统全部扩容一遍。微服务是一套“组织架构”的解法它解决的是单体架构后期“人多、业务复杂、相互牵制”的全局性效率问题。3. 分布式的核心难题从锁到事务这些绕不开的坑一旦系统从单机变成多节点原来在单机环境里理所当然的事情全都变得不理所当然了。比如变量共享、事务一致性、唯一ID生成……这些在单体架构里通过JVM内存锁、数据库本地事务、数据库自增ID就能解决的问题分布式环境下全部成了新难题。这些也是面试官最爱问的也是实际开发中最容易翻车的地方。我结合积累的经验逐个说透。3.1 分布式锁多台机器抢同一个资源背景单体时代处理并发更新库存这种场景直接用Java的synchronized或者Lock就行因为多个线程在同一个JVM进程里锁是进程内共享的。变成集群部署之后请求被负载均衡分发到不同服务器每台服务器都有自己的JVM内存锁。假设两台机器同时收到减库存请求JVM级别的锁根本无法互斥两个进程同时把库存扣成负数超卖就出现了。解法需要一个所有进程都能访问到的第三方媒介来承载“锁”这个状态。目前最主流的做法是基于Redis实现分布式锁相关面试题中出现的概率极高。Redis分布式锁的基本实现逻辑不复杂多个进程去Redis里执行一条SET命令带上NX——即只在key不存在时写入以及EX——设置过期时间只有第一个执行成功的进程才算是拿到了锁。业务逻辑执行完毕之后删除这个key释放锁。这就是所谓的Redis分布式锁。这里有两个大坑必须注意坑一锁的过期时间设置。过期时间设太短业务还没执行完锁就自动释放了别的进程可以拿到锁并发操作安全隐患就产生了设太长万一持有锁的进程崩溃其他进程等待时间会很长。成熟的做法是用Redisson框架它内部有看门狗机制会自动给锁续期默认每10秒续期到30秒解决业务执行时间超过锁过期时间的问题。坑二释放锁时的误删。进程A拿到锁执行完准备释放锁但此时锁已经因为过期被Redis删除了进程B拿到新锁并开始执行。A执行删除操作删掉的是B的锁导致B的临界区失去保护。解决办法是删除锁之前先比较当前线程持有的唯一标识比如UUID和Redis中存的value是否一致一致才删除。这一段逻辑建议用Lua脚本保证原子性否则“比较删除”这两步之间插入别的事件也会出错。补充一个点Redis分布式锁还有一个更进阶的形态叫Redlock引入多个Redis节点来提升锁的可靠性。不过实际生产中如果单节点Redis高可用做得足够好Redlock用得并不多反而因其复杂度常被诟病。大家面试时可以提一嘴但落地时别一上来就上Redlock。3.2 分布式事务跨服务的数据一致性难题背景单体时代一个下单操作扣库存、生成订单、扣减余额全在同一个数据库里用一个本地事务BEGIN TRANSACTION...COMMIT就行要么全成功要么全回滚。微服务拆分之后订单是订单服务库存是库存服务支付是支付服务每个服务各自用独立的数据库。这时候一个操作要跨三个服务、三个数据库还怎么保证要么全成功要么全回滚这就是分布式事务要解决的问题。它分几种解决思路按严格程度层级递进方案一最终一致性本地消息表。这是很经典、很务实的方案。核心思想是订单服务在本地事务里除了写入订单数据同时往一张“本地消息表”里插入一条待发送消息。这两个操作在同一个本地事务中保证原子性。之后有一个定时任务扫描消息表将消息发送给MQ消息队列库存服务消费消息去扣库存。如果扣库存失败消息表里的消息一直处于未确认状态可以重试。库存服务处理完后再回调订单服务标记消息为已消费。这种方式能保证事务的最终一致性但做不到强一致性——也就是说会有那么一小段时间订单已经生成了但库存还没扣掉。方案二TCCTry-Confirm-Cancel。它把业务拆成三个步骤Try阶段试运行锁定资源Confirm阶段确认执行业务Cancel阶段对Try阶段的操作进行补偿回滚。比如下单场景——Try阶段先把库存冻结住Confirm阶段真正扣减库存Cancel阶段解冻库存。这个方案实现复杂度高每个服务都要写三段逻辑一般业务体量下不建议直接用但它确实是分布式事务高可靠方案的典型代表面试时是重要知识点。方案三基于可靠消息的最终一致性方案。这是目前绝大多数互联网企业的落地选择。相比于本地消息表它是把“消息可靠性”的责任转移给了MQ本身。比如使用RocketMQ的事务消息或者利用MQ的“生产端确认消费端手动ACK重试机制”来保障最终一致性。它要求业务侧遵循一个黄金原则先把业务数据落库再发消息确保消息一定能被消费消费方处理失败了要能重试而且重试逻辑要幂等。说到幂等这是分布式事务里头最关键也最容易忽略的细节。无论是网络重发还是消费者重试消息很可能被消费两次。比如扣库存的请求被重试了两次库存就被扣了两次。解决办法一般是在消费者里加一个“去重表”用业务唯一键比如订单号商品ID做唯一约束处理前先查一下是否处理过。关于分布式事务还有必要喷一句很多团队一上来就搜个Seata框架集成觉得用了框架就万事大吉了。实际上Seata的AT模式在复杂业务场景下性能消耗不小且对数据库规范有要求。个人建议是先把“最终一致性幂等重试”这一套基础能力吃透这比任何框架都重要。框架只是工具而分布式事务的架构思维才是搞懂这道题的关键。3.3 分布式缓存和分布式ID每个细节都藏着坑很多人都知道缓存但很少认真想过为什么缓存也要强调“分布式”其实核心原因是容量的扩展问题。单机Redis内存也就几十GB业务数据量大了之后单节点放不下。这时候就需要把数据分散到多个Redis节点上让每个节点只存一部分数据。这就引入了数据如何分布的问题。常见的方案是一致性哈希一致性哈希环和Redis Cluster的哈希槽机制。哈希槽的引入是为了解决一致性哈希在节点增删时大量key重分布的问题。这套东西不复杂但很实用建议重点理解一致性哈希的原理面试和实践中都很有价值。另外一个容易被忽视的问题是分布式ID。单体时代数据库自增主键就够了。分布式环境里数据分散到多个数据库分片如果每个库都自增就会出现重复ID。业内常见的方案有UUID简单但不可读、不递增不适合作为数据库主键影响索引结构。雪花算法Snowflake用“时间戳 机器ID 序列号”生成64位长整型ID趋势递增性能极高是应用最广泛的方案。美中不足是强依赖服务器时钟时钟回拨会导致ID重复或混乱。基于数据库/Redis生成比如利用Redis的INCR命令生成递增ID可以结合日期前缀做订单号等可读性要求高的场景。分布式ID这块我推荐大家都去看一眼美团的Leaf方案基本算是把雪花算法的坑都填好了的标杆实践。3.4 分布式定时任务和分布式会话大型系统的活细节再补充两个热词里提到的“分布式定时任务”和“分布式会话”。定时任务在单体里很简单一个Scheduled注解就完事。到分布式环境多台机器都会执行同一个定时任务就产生了“同一份任务被重复执行多次”的问题。解决办法有两种一是引入分布式锁让同一时间只有一台机器能执行二是使用专业的分布式调度框架比如XXL-JOB、Elastic-Job或Spring Cloud架构中常见的解决方案。这些框架支持分片任务、故障转移等功能本质上解决的是“谁来做”和“怎么做”的协调问题。分布式会话也是不少人踩坑的地方。单体时代Session直接放服务器内存里集群化之后用户第一次请求打到A机器Session存在A第二次请求被负载均衡分到B机器B上找不到Session用户就被迫重新登录。解决思路是把Session从各服务器内存中抽出来统一放到Redis这样的集中式存储里让所有服务节点共享。这同时也呼应了Spring Cloud各类组件在网关层做的各种用户身份透传。4. 微服务落地实操怎么拆、怎么通信、怎么保证稳定如果你们团队确实业务复杂度到了需要微服务的阶段那接下来要面对的就是一系列很现实的问题服务怎么拆服务之间怎么通信坏了一个服务怎么不被波及4.1 微服务拆分原则按业务域拆别按技术层拆这是很多初学微服务的人最容易犯的错。有人按技术分层拆分把“Controller层”、“Service层”、“DAO层”分别做成三个服务这是最典型的反面教材。这样拆分之后订单的Controller调用订单的Service是网络调用订单的Service调用订单的DAO又是网络调用一个业务操作在网络调用上绕了好大一圈性能直接崩塌。正确的拆法应该是按业务领域纵向拆分也就是从“独立的业务能力”角度出发。参考DDD领域驱动设计中的“限界上下文”概念把系统划分成多个具备完整业务闭环的子域。比如电商系统可以拆成用户服务、商品服务、订单服务、库存服务、支付服务、物流服务。每个服务内部自己包含controller、service、dao全套逻辑独立完成这个领域内的业务闭环。判断标准很简单一条业务链路中如果几个功能点总是要一起联调、一起发版、它们的数据总是强一致地互相引用那它们应该在一个服务内部反之如果关联性弱、可以独立演进、数据独立存储那就可以拆出来。拆分时还有条铁律服务间禁止共享数据库。如果两个服务用的是同一个数据库那它们本质上还是耦合的一个整体事务问题还绕不开数据库锁微服务的意义就丧失了大半。每个服务应该拥有自己独立的存储服务之间的数据通过接口进行交换而不是直接操作对方的表。4.2 微服务的通信方式同步REST和异步MQ怎么选拆完之后服务之间需要通信。目前主流的两种方式HTTP RESTful API同步调用以及MQ消息队列异步通信。同步调用场景客户端发起一个查询需要立即拿到结果比如用户查看订单详情时可能需要订单服务去调用用户服务获取用户昵称。这种方式直观、易调试可以用OpenFeign这类声明式HTTP客户端实现消费端的调用这也是Spring Cloud里主流的做法。它的缺点是当调用链路很长时A调B、B调C、C调D任何一个节点变慢都会拖累整个链路。所以设计上一定要控制好调用深度能异步的尽量异步。异步调用场景业务逻辑允许一定延迟比如下单成功之后给用户发通知、更新积分、推送物流信息等。这种场景就应该走MQ。引入MQ之后两个服务之间不存在“等待关系”系统吞吐量和抗压能力都会明显提升。这里分享一个我在实际项目中反复强调的观点设计服务间依赖关系时要多用“事件驱动”的思路而不是“请求驱动”的思路。订单服务不需要知道扣完库存之后下一步是干什么它只需要在产品创建后发布一个“OrderCreated”事件然后对它感兴趣的库存服务、通知服务自己去订阅处理。这样做出来的系统各服务之间耦合度更低扩展性更强——新增一个服务去监听这个事件完全不需要改动已有的其他服务。这也是Spring Cloud架构下事件驱动微服务的一个标准动作。4.3 服务稳定性三板斧注册发现、熔断限流、网关路由微服务数量一多服务之间的调用关系就像一张蜘蛛网。怎么让请求能自动找到对应的服务服务出现故障了怎么不会像多米诺骨牌一样全链条崩溃这里有几个核心组件。注册中心与负载均衡。Spring Cloud架构中Nacos、Eureka这类组件扮演注册中心的角色。每个服务启动后把自己的IP端口注册上去调用方从注册中心拿到对方的实例列表再结合负载均衡策略轮询、随机等选择一台发起调用。Nacos现在国内用得最多因为它除了注册中心还兼容了配置中心的功能比Eureka和Spring Cloud Config的组合更轻量。如果你是自己搭建微服务基础设施可以重点考虑Nacos。熔断与降级。当某个下游服务异常变慢或者不可用时如果上游服务还在一直傻等线程池会被耗尽故障就会向上游蔓延。这就是所谓的“雪崩效应”。Hystrix早期 Resilience4j Sentinel是目前主要可用的库或组件。Sentinel由阿里开源使用起来直观、有控制台界面在国内受欢迎。它做的事可以用一个生活例子概括当某个下游服务的失败率超过阈值Sentinel直接熔断——不再发起真实调用立刻返回一个兜底结果或抛出降级提示同时隔一段时间放一个试探请求看服务是否恢复。这就像跳闸的空气开关直接切断危险电路保护其他电路正常工作。API网关。它就是微服务体系的“总大门”。外部请求不是直接打到各个服务上而是先进入网关Spring Cloud Gateway是主流的下一代网关由网关做统一的路由转发、权限校验、限流、日志记录等操作。这能避免外部客户端感知到复杂的微服务内部结构也让一些横切逻辑认证、防刷有了统一落地的地方。4.4 微服务的部署与容错别让小而美的服务变成运维噩梦这是我在实际项目中感受最深的部分。微服务拆出来是爽了开发和部署上的噩梦才刚刚开始。举个例子。一个单体应用你只需要监控一个进程拆成二十个微服务你就要监控二十个进程每个服务的日志、指标、告警都得到位。运维成本一下子多了二十倍。所以微服务落地的前提条件非常明确必须有一套成熟的容器化和编排方案通常就是Docker KubernetesK8s。同时链路追踪工具比如SkyWalking、Zipkin也得安排上不然排查一个跨了六个服务的请求问题会像大海捞针一样绝望。另一个常常被忽略的点是配置管理。单体时代一个配置文件搞定微服务时代每个服务都有自己的配置。Spring Cloud配置中心或Nacos配置管理可以将所有服务的配置集中在同一个地方管理支持动态刷新改配置不用重新发版。这个细节对运维体验的改善不是一点半点。5. 架构选型建议别为了用微服务而微服务聊到这里核心概念和技术点都覆盖了。但作为踩过不少坑的老兵我特别想跟大家掏心窝子地聊聊选型这个终极问题。很多人在网上刷到“微服务是趋势”就觉得自己系统也得拆一拆不然简历上不够好看。这种心态我太熟悉了因为我刚接触微服务那几年也是这个状态。后来经历过的、见到的教训多了才慢慢形成了一套相对务实的判断标准。5.1 什么情况该选单体什么情况该上分布式选单体的理由团队规模小10个人以内业务复杂度不高几个模块能说清楚用户量也不大日活几万以内。这种规模下单体架构是最好的选择。它的优势是开发效率极高调试方便部署简单资源消耗少。你可以把所有精力放在业务功能本身而不是和基础设施搏斗。选分布式的理由单机确实扛不住流量了或者系统对可用性有很高的硬性要求不允许单点故障。这时候你考虑集群部署先用负载均衡把单体复制成多份这是成本最低、见效最快的提升手段。从这个阶段开始你需要重新考虑日志收集统一收集到ELK、会话共享等问题。选微服务的理由业务模块之间确实可以清晰划分出边界且团队规模已经具备划分为多个功能小组的条件各小组需要独立开发和独立发布。还有一个特征业务链路中确实存在冷热不均的情况比如搜索、推荐消耗大量CPU而用户系统流量没那么大需要独立扩展。这个前提很关键——微服务是一种组织级的高成本架构如果你没有一个超过20人的研发团队我大概率会劝你留在单体上。这也是为什么很多大厂的高并发系统反而内部推行“大团队内聚模式”小团队不适合微服务团队规模是微服务分不分开的决策基础。5.2 从单体到微服务的过渡路线如果你判断下来确实需要微服务了也不要一步到位直接全拆。建议按下面这个路线平滑演进第一步先上线——用单体支撑住业务。先把MVP最小可行产品快速跑起来能用、稳定收集用户反馈验证商业模式。此时任何微服务的“完美设计”都是过度设计。第二步集群化——解决容量瓶颈。当出现性能瓶颈优先做集群部署和读写分离主从复制。这一步不需要修改代码主要工作在运维和配置层面。如果有条件把后端存储也一并做一下缓存设计用上Redis把所有热点数据挡在数据库前面。第三步局部拆分——按业务模块逐个拆出服务。盯住业务链路上最大的瓶颈模块进行拆分比如支付、订单这种核心链路先把它拆成独立服务独立部署独立扩容。其他模块暂时维持原状。这种渐进式改造比一次性全拆成功率要高得多。第四步全面微服务化——引入全套基础设施。到了这一步你已经验证了拆分带来的收益团队也积累了对微服务开发和运维的初步心得。这时再去铺开注册中心、配置中心、网关、熔断、链路追踪等基础设施才不会被反噬。我见过太多团队一上来就上全套Spring Cloud Alibaba结果日常80%的开发时间都在跟Nacos、Sentinel、Seata搏斗业务功能却迟迟推不动。这种“基建先行”的结果往往是项目延期团队士气受挫。5.3 给新手的一点实操学习路径如果你现在是个Java开发者正在学习这些概念我建议的学习路径是先在单体项目里把业务逻辑吃透再部署一个单体集群手动配一次Nginx负载均衡感受一下Session共享问题的滋味然后引入Redis把分布式缓存和分布式锁用一遍再去学习Spring Cloud Alibaba用Nacos OpenFeign Sentinel搭一套最小微服务骨架最后把分布式事务的几种方案的理论搞明白用本地消息表的方式自己实现一次最终一致性。踩过一遍完整的坑你才算真正懂了微服务和分布式解决的问题。而不是像很多人那样停留在“会用注解”的程度。做技术把“为什么”搞清楚意义远大于把“怎么做”背下来。6. 常见问题速查摸爬滚打中总结的避坑清单这部分整理一下我这些年带团队、做方案、踩坑复盘过程中沉淀下来的高频问题和处理经验可以当速查表用。问题场景典型错误做法正确姿势与心得业务量不大但想“跟上技术潮流”拆微服务直接拆成几十个服务团队被运维拖垮从单体起步确认业务复杂度足够时再做演进参考5.2的路线分布式锁过期时间设置固定设置10秒或30秒不做动态续期使用Redisson的看门狗机制或根据业务最长执行时间合理设置并留足余量释放分布式锁直接DEL key可能误删别人的锁先比对唯一标识再删除用Lua脚本保证原子性跨服务更新数据一致性问题用分布式事务框架Seata AT模式硬钢性能优先设计为最终一致性方案本地消息表 MQ 幂等消费服务间共享数据库两个服务操作同一张表以为省事微服务第一铁律服务必须独立数据库通过接口交换数据定时任务多服务重复执行多个实例都跑Scheduled重复处理业务接入XXL-JOB等分布式任务调度平台或分布式锁控制执行权服务间同步调用链路过深A→B→C→D串行调用成功率逐层衰减尽量用MQ异步化同步调用控制在两层以内必要处加缓存网关层处理所有业务逻辑把参数校验、数据处理都写到网关代码里网关只做公共横切逻辑认证、限流、路由业务逻辑留在服务内排查跨服务问题时间过长问题出现后靠人工比对多个服务的日志从一开始就建设链路追踪SkyWalking生成TraceId贯穿全链路这里多补充一个心得也是踩过最多坑的一个总结不管架构怎么演变把“边界”定义清楚永远是第一要务。单体时代边界是模块之间的包划分分布式时代边界是节点之间的接口协议微服务时代边界是服务与服务的领域所有权。很多代码写不好、系统不稳定根子不在技术选型而在边界模糊。另外还有一个小习惯建议大家养成任何架构决策都要有明确的“度量指标”。比如你认为某块业务需要从单体中拆出来原因不能是“觉得它比较独立”而应该是“这块业务每周发版3次并且它占用了全系统80%的计算资源”——有量化指标方案评审时才有说服力。我个人在实际操作中的体会是做架构选型和落地推进最怕的不是不懂技术而是被概念绑架。分布式、微服务这些词本来只是工具箱里的几件不同规格的工具而已。用合适规模的工具解决合适规模的问题就是一个合格的架构师最大的专业素养。你先能从零独立设计出高可用的单体系统再一步步理解分布式里那些锁、事务、缓存和链路追踪的取舍那些曾经让你发怵的名词就会慢慢变成肌肉记忆里的常识。