diff --git a/notes/pics/cache-aside-race.png b/notes/pics/cache-aside-race.png new file mode 100644 index 00000000..bd150ceb Binary files /dev/null and b/notes/pics/cache-aside-race.png differ diff --git a/notes/pics/circuit-breaker.png b/notes/pics/circuit-breaker.png new file mode 100644 index 00000000..3ddc6e37 Binary files /dev/null and b/notes/pics/circuit-breaker.png differ diff --git a/notes/pics/fencing-token.png b/notes/pics/fencing-token.png new file mode 100644 index 00000000..9f714c3e Binary files /dev/null and b/notes/pics/fencing-token.png differ diff --git a/notes/pics/paxos-example.png b/notes/pics/paxos-example.png new file mode 100644 index 00000000..3f66cdbf Binary files /dev/null and b/notes/pics/paxos-example.png differ diff --git a/notes/分布式.md b/notes/分布式.md index 9e651eaf..7cd66180 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -89,6 +89,8 @@ Redis 8.4 新增了 `DELEX lock_key IFEQ unique_value` 指令,可以直接原 RedLock 依赖各个节点的时钟基本同步,并且无法应对进程暂停(例如 GC)导致锁过期后客户端仍然认为自己持有锁的情况,因此存在争议。更可靠的做法是让锁服务每次加锁时返回一个单调递增的栅栏令牌(Fencing Token),客户端访问资源时带上令牌,资源拒绝令牌比已处理过的更小的请求。 +

+ ### Zookeeper 的有序节点 #### 1. Zookeeper 抽象模型 @@ -332,6 +334,8 @@ Acceptor 接受一个提议之后,会将该提议发送给所有的 Learner。 - A 发送 Prepare(2),X 和 Y 做出承诺并响应。A 得到大多数响应之后发送 Accept(2, 8),X 和 Y 接受该提议,此时值 8 已经被选定; - 之后 B 发送 Prepare(4),它收到的大多数响应中至少有一个来自 X 或 Y,响应中包含已经接受过的提议 [2, 8],因此 B 只能发送 Accept(4, 8),而不能使用自己的提议值,从而保证了选定的值不会改变。 +

+ ### 约束条件 #### 1\. 正确性 diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index 959ff9a0..fa9c0e97 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -111,6 +111,10 @@ - 降级:主动关闭部分非核心功能,从而保证核心功能可用; - 熔断:某个依赖的服务持续出错时,暂时不再调用它而是直接返回默认结果,避免故障沿着调用链扩散。 +熔断器有关闭、打开和半开三种状态:失败率超过阈值时打开;打开一段时间后进入半开状态,放行少量请求试探,成功则关闭,失败则重新打开。 + +

+ ## 五、安全性 要求系统在应对各种攻击手段时能够有可靠的应对措施,常见的攻击手段和防范方法见 [攻击技术](攻击技术.md)。 diff --git a/notes/缓存.md b/notes/缓存.md index eb293c3c..1a6cffa1 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -128,6 +128,8 @@ CDN 主要有以下优点: 删除缓存而不是更新缓存,是因为两个并发的写操作到达缓存的顺序可能和到达数据库的顺序不同,导致缓存中是旧值。先更新数据库再删除缓存,是因为反过来的话,删除缓存之后、更新数据库之前的读请求会把旧值重新写入缓存。 +

+ 这种模式仍然存在小概率的不一致,例如删除缓存失败。常用的补救措施: - 为缓存设置过期时间作为兜底; diff --git a/tools/diagram/src/cache-aside-race.svg b/tools/diagram/src/cache-aside-race.svg new file mode 100644 index 00000000..92e67788 --- /dev/null +++ b/tools/diagram/src/cache-aside-race.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + 先删除缓存再更新数据库 + + + + + + + 写请求 + + + 缓存 + + + 数据库 + + + 读请求 + + ① 删除缓存 + + ② 读缓存未命中 + + ③ 读到旧值 + + ④ 更新为新值 + + ⑤ 把旧值写入缓存 + 缓存中一直是旧值,直到被删除或过期 + diff --git a/tools/diagram/src/circuit-breaker.svg b/tools/diagram/src/circuit-breaker.svg new file mode 100644 index 00000000..37a27dd7 --- /dev/null +++ b/tools/diagram/src/circuit-breaker.svg @@ -0,0 +1,47 @@ + + + + + + + + + 熔断器状态 + + + + + 关闭 + Closed,正常调用 + + + + + 打开 + Open,直接返回 + + + + + 半开 + Half-Open,少量试探 + + + 失败率超过阈值 + + + 等待一段时间 + + + 试探请求失败 + + + 试探请求成功 + diff --git a/tools/diagram/src/fencing-token.svg b/tools/diagram/src/fencing-token.svg new file mode 100644 index 00000000..d6f2f6fd --- /dev/null +++ b/tools/diagram/src/fencing-token.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + 栅栏令牌 + + + + + + + 客户端 1 + + + 锁服务 + + + 客户端 2 + + + 存储 + + 获取锁 + + 成功,令牌 33 + + + GC 停顿 + 锁过期 + + 获取锁 + + 成功,令牌 34 + + 写入,令牌 34 + 接受,记录 34 + + 写入,令牌 33 + 拒绝,33 < 34 + diff --git a/tools/diagram/src/paxos-example.svg b/tools/diagram/src/paxos-example.svg new file mode 100644 index 00000000..28e0bcc7 --- /dev/null +++ b/tools/diagram/src/paxos-example.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + Paxos 示例 + + + + + + + + Proposer A + + + Acceptor X + + + Acceptor Y + + + Acceptor Z + + + Proposer B + + Prepare(2) + + Prepare(2) + + 承诺 + + 承诺 + + Accept(2, 8) + + Accept(2, 8) + + 接受 + + 接受 + X、Y 构成多数派,值 8 已被选定 + + Prepare(4) + + Prepare(4) + + 承诺 + + 承诺,已接受 [2, 8] + + Accept(4, 8) + + Accept(4, 8) + B 只能沿用值 8,不能使用自己的提议值 +