尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

分布式与微服务核心区别:架构风格 vs 部署形态

分布式与微服务核心区别:架构风格 vs 部署形态 这次我们直接聊一个面试和架构评审里都绕不开的问题分布式和微服务到底有什么区别很多人在简历上写了“精通微服务架构具备分布式系统开发经验”但被问住最多的地方恰恰是这两个概念本身。更常见的情况是Spring Cloud、Nacos、Seata 这些组件都在用真要让讲讲“你现在的系统是分布式还是微服务”反而说不清楚。这篇文章不绕概念直接给结论微服务是架构风格分布式是部署形态。两者经常组合出现但本质上是两回事。文章会从定义、拆分维度、典型中间件、落地路线和踩坑排查几个角度展开最后给出一套可以对照自己项目做架构判断的清单。1. 核心概念速览先建一张表把两者的关系限定清楚后面所有内容都围绕这张表展开维度分布式微服务本质系统部署与协作方式服务拆分与组织方式关注点多节点如何对外提供统一能力业务边界如何拆分、每个服务如何自治是否必须拆业务不一定可以按数据分片、按功能模块复制部署必须按业务域拆成独立服务是否必须多节点是至少两个节点协同不绝对单体也可以叫微服务风格但实践通常对应多节点典型例子Hadoop 伪分布式、Redis Cluster、MySQL 主从Spring Cloud 微服务、若依微服务、订单/库存拆分核心问题网络通信、数据一致性、分布式事务、分布式锁、分布式缓存服务治理、熔断降级、配置管理、服务发现、链路追踪常见组件Zookeeper、Redis、Kafka、SeataSpring Cloud、Nacos、Gateway、Sentinel、SkyWalking结论先放在这里分布式更偏向“多节点协同”的底层能力问题微服务更偏向“业务如何拆”的架构设计问题。微服务天生是分布式的但分布式不等于微服务。2. 分布式多节点协同对外像一个整体2.1 分布式的核心定义分布式系统是指多个独立计算机节点通过网络通信协作共同完成任务并且对用户来说表现为一个统一的系统。关键点有三个多个节点至少两台机器或者一台机器上多个进程。网络通信节点之间需要交换数据不能各干各的。对外统一用户访问的是同一个服务入口不需要关心背后有几个节点。Hadoop 伪分布式就是一个很好的入门例子。所谓伪分布式是在单台机器上模拟分布式环境HDFS 的 NameNode、DataNode、SecondaryNameNode 以独立进程的方式运行。这说明分布式的本质是“多进程 通信 协作”而不是必须有物理上的多台服务器。2.2 分布式要解决什么问题节点一多新问题就出来了数据一致性两个节点同时改同一份数据怎么办。分布式事务跨库、跨服务的数据操作如何保证原子性。分布式锁多节点抢同一个资源如何保证只有一个节点能拿到。分布式缓存缓存数据分散在多个节点如何保证访问路由和数据一致。分布式定时任务定时任务在多个节点部署后如何避免重复执行。分布式存储数据量超过单机容量如何分片存储。这组问题不依赖具体业务只要系统有多个节点协作就一定会遇到。2.3 分布式事务的四种典型方案这里必须提分布式事务因为它是分布式系统里最容易出问题、面试也最爱问的一块。常见方案是这四种方案核心思路典型组件适用场景2PC/XA两阶段提交先准备后提交Atomikos、Seata AT强一致性、短事务TCCTry-Confirm-Cancel 三阶段Seata TCC业务可拆分为预留/确认/撤销比如扣款最大努力通知允许最终不一致多次重试通知MQ 定时任务跨平台回调、支付结果通知本地消息表 MQ事务消息实现最终一致性RocketMQ、RabbitMQ订单、库存类异步削峰场景Seata 是目前 Java 生态里用得非常多的分布式事务框架AT 模式依赖全局锁和undo_log 表回滚。使用时要特别注意代理数据源配置不能用默认的 DataSource否则事务回滚不生效。下面是一段 Seata AT 模式的 YAML 配置示例结合 Spring Cloud 项目使用seata: enabled: true application-id: order-service tx-service-group: my_test_tx_group registry: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: group: SEATA_GROUP config: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: group: SEATA_GROUP对应 Spring Boot 主类上需要启用全局事务SpringBootApplication EnableAutoDataSourceProxy public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }注意Seata AT 模式需要业务表包含 undo_log 表且每个分支事务都要走 Seata 代理的数据源否则回滚时找不到原始数据。3. 微服务业务边界拆分服务独立演进3.1 微服务的核心定义微服务是一种架构风格将单个应用拆分成一组小型服务每个服务围绕业务能力构建独立开发、独立部署、独立扩展服务之间通过轻量级通信机制HTTP/RPC交互。微服务强调的是“边界”和“自治”。边界按业务域划分比如订单服务、库存服务、用户服务。自治每个服务有自己的数据库、自己的代码仓库、自己的发布节奏。3.2 微服务不是简单的“拆”很多人拿到一个单体应用直接复制一份再改改端口以为这就是微服务。这其实是“分布式部署的单体应用”不是微服务。判断一个系统是不是微服务可以看三个问题判断问题是微服务的话每个服务的数据是否独立是不允许跨库直接 join某个服务可以独立部署吗可以发布不影响其他服务服务团队是否需要和其他团队频繁协调不需要接口定义好就行如果答案是“数据还共用一个库”“发布必须一起发”那充其量是伪微服务或者叫分布式的单体。3.3 微服务落地的典型组件以 Java 技术栈为例一个完整的微服务架构需要这些能力能力典型组件作用服务注册与发现Nacos、Eureka、Consul服务实例动态注册和发现网关Spring Cloud Gateway统一入口、路由、鉴权负载均衡OpenFeign LoadBalancer服务间调用和负载均衡配置中心Nacos Config、Apollo集中管理配置支持动态刷新熔断降级Sentinel、Resilience4j保护依赖不健康的服务链路追踪SkyWalking、Zipkin全链路日志追踪和性能分析分布式事务Seata跨服务事务一致性用 Nacos 做注册中心时服务配置示例spring: application: name: user-service cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: public服务启动后可以在 Nacos 控制台看到实例列表。调用方通过 OpenFeign 声明式调用FeignClient(name user-service, path /api/user) public interface UserClient { GetMapping(/info) UserInfo getInfo(RequestParam(id) Long id); }这套结构是当前大部分 Java 微服务项目的通用骨架若依微服务版本也是基于 Spring Cloud Nacos 搭建的。4. 分布式和微服务的核心区别把两者放在一起对比核心区别可以归结为四个层次。4.1 拆分维度不同维度分布式微服务按什么拆按部署单元、数据分片、功能复制按业务能力边界拆分目标支撑更多请求、更大数据量提升研发效率、降低耦合、独立演进最小拆分单位进程/节点独立业务服务4.2 关注问题不同分布式关注的是多节点带来的技术问题数据一致性、网络分区、节点故障、时钟漂移。微服务关注的是架构管控问题服务怎么拆、接口怎么定义、依赖怎么管理、故障怎么隔离。4.3 是否共享数据这一点是很多人的盲区。分布式系统可以共享底层数据比如 Redis Cluster 每个节点负责一部分 slotMySQL 主从共享同一份逻辑数据。微服务则明确要求数据独立服务之间只能通过接口访问数据不能直接共享数据库表。4.4 一句话总结分布式解决的是“多台机器如何一起干活”的问题。微服务解决的是“一个复杂系统如何拆成小块维护”的问题。分布式是基础设施层面的特征微服务是应用架构层面的选择。微服务系统一定是分布式的但分布式系统可以是单体应用的集群部署。5. 从单体到分布式再到微服务5.1 单体阶段所有功能在一个应用里部署一个 jar/war共用一个数据库。优点开发简单、部署简单、事务天然一致。 缺点代码膨胀后无法维护任何一个功能发布都要整体回归。5.2 集群/分布式阶段单体应用复制多份部署到多台机器前面加负载均衡。这是“单体的分布式”。解决了高可用和高并发但没有解决代码耦合问题。这时候会遇到 Redis 分布式锁、分布式定时任务不重复执行等问题。Redisson 就是常用来解决分布式锁的框架RLock lock redissonClient.getLock(order:create:123); boolean locked lock.tryLock(3, 30, TimeUnit.SECONDS); if (locked) { try { // 执行订单创建逻辑 } finally { lock.unlock(); } }5.3 微服务阶段按业务能力拆分成多个服务每个服务独立部署、独立数据库。服务之间通过 OpenFeign、Dubbo 或者 HTTP 调用。这时候需要引入服务注册中心、网关、配置中心、熔断降级和链路追踪。5.4 三者关系演化表阶段实例数量数据存储业务耦合典型组件单体1单库高Spring Boot集群分布式N单库或主从高Nginx、Redis微服务N按服务拆分低Spring Cloud Nacos Seata6. 分布式带来的典型问题拆完之后更难了这是写代码之外最需要理解的部分。架构迁移到分布式或微服务后原本单体里简单的问题会变得复杂。6.1 分布式事务单体时代一个 Transactional 就能保证订单和库存同时更新。微服务拆分后订单服务和库存服务各自有库事务边界越界了。解决方案在 2.3 节已经列过实际项目建议按一致性要求选型。无法接受最终一致性、要求强一致的场景用 Seata AT 或 TCC。允许延迟一致、异步链路用事务消息和本地消息表比如订单创建成功后发送“库存扣减”消息。6.2 分布式锁在集群部署下传统的 synchronized 只能锁住单个 JVM 内的线程锁不住多节点。常见做法是 Redis 分布式锁使用 Redisson 封装好的 RLock避免自己写 setnx 出现释放锁错误。用 Zookeeper 临时顺序节点也可以实现分布式锁适合对一致性要求更高的场景。需要特别注意的是锁粒度、锁超时、可重入性以及业务执行时间超过锁过期时间导致的提前解锁问题。6.3 分布式缓存缓存从单机本地缓存变成 Redis Cluster 后要解决缓存穿透、缓存击穿、缓存雪崩、缓存一致性问题。面试老四样但在分布式环境下才真正变得严重。6.4 分布式定时任务定时任务在单机部署没问题多节点部署后同一个任务会被重复执行。方案有三类方案实现方式适用场景分布式锁任务执行前抢锁简单任务较少Quartz 集群模式基于数据库锁中小型集群XXL-Job独立调度中心 分片广播大规模、需要管理界面6.5 分布式压测这也是搜索结果里经常出现的词。JMeter 支持分布式压测master 节点分发脚本多台 slave 节点同时发起请求。目的不是让压力更大而是突破单机端口和连接数限制模拟更真实的流量。JMeter 分布式压测的格式# 在 slave 节点启动服务 jmeter-server -Dserver.rmi.port1099 # 在 master 节点执行远程测试 jmeter -n -t test.jmx -R 192.168.1.101:1099,192.168.1.102:1099 -l result.jtl注意master 和 slave 的 JDK 版本最好一致否则 RMI 通信会报错测试脚本中用到的 CSV 数据文件要手工同步到每个 slave 节点因为 JMeter 不会自动分发文件。7. 架构选型该用分布式还是微服务这是文章最实用的一节。很多开发者在“要不要微服务化”上反复纠结提供一套判断标准。7.1 什么时候用分布式单体应用遇到单机性能瓶颈需要横向扩容。需要高可用一台机器挂了服务不能断。数据量超过单库存储能力需要分库分表或引入分布式存储。需要多节点协作但业务不需要拆成独立服务。这时候选择“单体应用多实例部署”加 Nginx 做负载均衡再引入 Redis 做分布式缓存就已经是分布式系统了。不需要上微服务。7.2 什么时候需要微服务单体代码量快速膨胀模块之间耦合严重想拆拆不动。团队规模扩大多个团队需要在同一个系统并行开发。某个模块的流量远高于其他模块需要独立扩展。需要不同的技术栈实现不同业务域。业务变更频繁希望隔离故障单个模块出错不影响全局。7.3 什么时候不要上微服务团队只有几个人业务逻辑简单。没有独立运维能力没有监控、日志、链路追踪。项目还是原型验证阶段业务边界本身不清晰。事务一致性要求极高又不想承担分布式事务的技术成本。**不建议为了简历写“微服务经验”硬拆系统。**微服务是手段不是目的。拆完之后引入的注册中心、网关、配置中心、分布式事务、链路追踪每一样都是实实在在的运维负担。8. 常见问题与排查方法从搜索结果看分布式和微服务相关的坑集中在事务、锁、服务注册和配置管理上。问题现象可能原因排查方式解决方案服务启动后 Nacos 看不到实例服务未注册成功、namespace 不一致、网络不通检查 nacos 控制台、查看服务日志、确认 namespace修正 namespace 配置重启服务Feign 调用报 “No instances available”目标服务未注册或注册失效检查目标服务状态、Nacos 健康检查配置重启失效服务延长心跳超时时间Seata 事务不回滚未使用代理数据源、不会生成 undo_log查看分支事务日志、检查 undo_log 表启用EnableAutoDataSourceProxy补建 undo_log 表Redis 分布式锁提前失效业务执行时间超过锁超时时间加日志记录加锁时间和业务耗时延长过期时间或使用看门狗续期机制分布式定时任务重复执行多节点无互斥机制观察多个实例日志是否同一时刻执行引入 XXL-Job 或加分布式锁JMeter 分布式压测连接失败RMI 端口未开、JDK 版本不一致在 slave 机器 telnet 测试端口统一 JDK 版本开放 1099 端口配置修改后服务未生效Nacos Config 未配置自动刷新检查RefreshScope注解加注解或手动调用刷新接口微服务调用超时网络延迟、下游慢、连接池耗尽查 SkyWalking、调整 Feign 超时时间设置合理的超时和重试策略9. 最佳实践与使用建议结合真实项目经验给出几条工程化建议。9.1 先小参数验证再大规模拆分不要一次性把整个系统拆成几十个服务。先选一个业务边界清晰、相对独立的模块试点比如用户服务或者日志服务。跑通注册中心、网关、配置中心、日志链路之后再逐步扩大拆分范围。9.2 保留一套最小可运行配置把 Nacos、Seata、Redis、Sentinel 的最小配置模板存到代码仓库里。新服务拉下来改端口和数据库就能跑。不要每次新服务都重新配置一遍中间件。最小可运行配置至少包括spring: application: name: ${service.name} cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: public datasource: url: jdbc:mysql://127.0.0.1:3306/${db.name}?useUnicodetruecharacterEncodingutf8 username: root password: root seata: enabled: true application-id: ${service.name}9.3 目录和命名规范模型文件、输入素材、输出结果分目录管理。放到项目里对应的是代码、配置、日志、数据要分离。配置放到 Nacos 统一管理日志按 traceId 落盘输出结果统一走接口。服务命名用“业务域-子模块”的格式例如 order-service、stock-service。9.4 批量任务要加日志和失败重试分布式环境里批量任务一旦失败排查成本很高。每个任务要有任务 ID、执行日志、失败重试机制。推荐结合 MQ 做失败重试或者用 XXL-Job 的失败告警。9.5 接口服务和数据访问要限制范围将服务注册到 Nacos 后接口不能随意暴露到公网。网关层做鉴权内网服务之间通过 service name 调用不直接暴露 IP。数据库账号按服务隔离单个服务只能访问自己的 schema。9.6 发布或商用前要做效果复核微服务化之后每次发布都要做接口回归和压测。建议在测试环境完整跑一遍核心链路特别注意分布式事务和缓存一致性在真实请求量下是否稳定。10. 总结与下一步最值得记住的一句话是分布式是部署形态微服务是架构风格。如果面试官问区别从拆分维度、关注问题、数据共享三个角度回答能直接讲完核心。如果自己在做架构选型先问一个问题现在系统是单机遇到瓶颈还是单体代码耦合到无法维护前者考虑分布式集群后者才需要认真思考微服务拆分。最容易踩的坑是把单体复制多份起了一个分布式集群就对外宣称是微服务。代码层面没有边界拆分、数据层面没有独立、治理层面没有服务发现这就不是微服务。分布式事务和分布式锁是上手分布式后最先会碰到的技术难点。Seata 和 Redis/Redisson 是最快见效的组合。后续可以继续扩展的方向链路追踪SkyWalking、分布式定时任务XXL-Job、JMeter 分布式压测、服务网格Istio。建议先把 Nacos Seata Redisson 这三件套在一个 Spring Cloud 项目里跑通对照本文第 2、3 节的配置把注册、发现、事务、锁链完整验证一遍。这一套跑下来分布式和微服务的区别就不是概念问题了。
返回列表