微服务名词概述
微服务架构四大问题
服务与服务之间如何通信
- 同步通信
HTTP (Apache Http Client)
RPC (Dubbo、gRPC、Apache Thrift) - 异步通信 - 消息队列
- 同步通信
这么多服务,如何管理(服务治理 - 服务注册与发现)
- 基于客户端(消费者拉取服务列表,自行负载均衡)- Zookeeper、Eureka、Consul
- 基于服务端(由中间层转发请求)- Nginx、Kubernetes Service
服务挂了怎么办
重试机制、服务熔断、服务降级、服务限流
客户端如何访问(Api 网关)
服务雪崩
因服务提供者不可用导致服务调用者不可用,并将不可用逐渐放大的过程。应对手段:重试、熔断、降级、限流(见下文)。
缓存雪崩
缓存中数据大批量到过期时间(或缓存服务整体宕机),而查询数据量巨大,引起数据库压力过大甚至 down 机。
解决方案:热点数据永远不过期、过期时间设置随机、分布式存储缓存等。
缓存穿透
用户不断请求缓存和数据库中都没有的数据,如发起为 id 为“-1”的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:用户鉴权校验、id 做基础校验;将 key-value 对写为 key-null,缓存有效时间可以设置短点,如 10 秒(设置太长会导致正常情况也没法使用),防止用户反复用同一个 id 暴力攻击;数据量大时可用布隆过滤器,把存在的 key 提前登记进过滤器,不存在的直接拦下,不触达缓存和数据库。
缓存击穿
缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力 。
解决方案:热点数据永远不过期、加互斥锁(在缓存过期期间,最多只有一个线程能够查询数据库更新缓存)等。
集群脑裂
由于网络断开原因,一个集群被分裂成两个集群;如 Elasticsearch 和 Zookeeper 等,通过选举确定主节点,都面临此问题;他们采用节点数过半机制保证集群脑裂后还能正常工作;
过半机制就是可用节点数 > 总节点数 / 2,集群才对外提供服务,否则集群不可用;
分布式锁
在分布式系统中,多个节点(计算机或进程)并行运行,操作同一资源时先竞争该资源的锁,业务完成后释放,保证同一时刻只有一个节点操作该资源——一句话:跨进程的互斥。
三种主流实现:
| 实现方式 | 加锁原理 | 优点 | 缺点 |
|---|---|---|---|
| 数据库 | 唯一索引或行记录加锁 | 简单可靠 | 性能差,无超时易死锁 |
| Redis | SETNX + 过期时间 | 性能高,自动过期 | 主从切换可能丢锁 |
| ZooKeeper | 临时顺序节点,序号最小者得 | 强一致,断连自动释放 | 性能较低,运维较重 |
Redis 方式的四个关键细节(也是手写实现的四个坑):
加锁与设过期必须一条命令原子完成
# 先 setnx 再 expire 的两步写法,中间宕机就是一把永不过期的死锁 set lock value nx ex 10value 存唯一标识(如 UUID):释放时校验是自己的锁才删,防止删掉别人的锁(自己的锁已过期、别人已持有);
校验与删除要用 Lua 脚本保证原子性,拆成两步同样存在删错锁的窗口
-- KEYS[1] 为锁的 key,ARGV[1] 为加锁时写入的唯一标识 if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end业务没执行完锁先过期:Redisson 的看门狗(watchdog)后台自动续期解决,生产环境直接用 Redisson。
主从异步复制导致锁丢失的进一步方案是 RedLock(向多个独立实例加锁,过半成功才算持有),争议较大,了解即可。ZooKeeper 的临时顺序节点同时天然规避了羊群效应(见下文)。
公平锁和可重入锁
公平锁
操作资源时排队取号,先到先得,独占一把锁;
可重入锁
同一个线程拿到锁后可以再次获取(计数 +1),释放时计数 -1,归零才真正解锁,避免自己锁死自己;
羊群效应
一个节点挂掉,所有节点都去监听,然后做出反应,会给服务器巨大压力;所以有了临时顺序节点,当一个节点挂掉时,只有他后面那个节点才会做出反应;
CI、CD
持续集成 (Continuous Integration,CI):
目的: 将团队代码集成到本地仓库中,然后在 测试环境 中自动运行构建和测试。目的是早期发现和解决集成问题,提高代码质量,减少集成错误。
持续交付 (Continuous Delivery,CD):
定义: 不仅自动构建和测试代码,自动化部署到一个 预生产环境 ,供进一步的手动测试或用户验收测试使用。
目的: 缩短交付周期,使得软件在任何时候都是可部署的状态,降低发布新版本的风险。
持续部署 (Continuous Deployment,CD):
定义: 强调通过自动化流程将软件部署到 生产环境 ,从而实现在每次通过了测试的代码提交后,都能自动发布到生产环境。
目的: 最大限度地减少发布新版本的手动干预,提高交付速度和可靠性。
总的来说,持续集成注重代码集成和测试,持续交付强调自动化部署到预生产环境,而持续部署则将这一自动化扩展到生产环境。
垂直扩容和水平扩容
垂直扩容(纵向扩容,scale up)是通过增加单个节点、服务器或实例的处理能力。水平扩容(横向扩容,scale out)是通过增加系统中节点、服务器或实例的数量。
CAP 理论
CAP 理论提出在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性),不能同时成立。
一致性 C
所有节点在同一时间得到的数据是一样的。
可用性 A
在合理的时间内响应请求,没有阻塞。
分区容错性 P
网络分区(节点间通信中断)时系统仍能继续工作,是分布式系统必须具备的基本能力。
一致性和可用性本来就相互矛盾,因为如果所有节点要保证数据一致,在同步数据期间,节点会拒绝请求导致系统不可用;
只能在 CP 和 AP 之间取舍,AP(可用性+分区容错性)系统在实践中更为常见和主流,提供不间断的服务直接影响用户满意度、留存率和收入。
尽管 AP 更常见,CP(一致性+分区容错性)系统在金融核心系统、分布式锁与协调服务、关键配置管理、分布式事务、消息队列等场景中应用较多,牺牲可用性(在分区时)是必要的代价。
服务熔断
服务熔断(Circuit Breaker),当某个微服务连续的失败次数或错误率达到某个预置点,所有请求都会被阻止,当检测到服务响应正常后,又逐步恢复调用链路的过程。
服务熔断防止系统因连续故障而崩溃,通过切断故障点来保护系统的整体稳定性,服务熔断主要包括以下几个过程:
打开熔断(拒绝所有请求)→ 半开(允许部分请求)→ 关闭(所有请求正常处理)。
服务降级
服务降级(Fallback),在服务出现问题时,尽可能提供部分功能或返回友好数据,减少对用户的影响。

