From a5f32c58e839167ddf86ebb48650eefbfd69c08d Mon Sep 17 00:00:00 2001 From: huifer Date: Thu, 31 Oct 2019 18:48:49 +0800 Subject: [PATCH] =?UTF-8?q?Create=20redis=E9=9B=86=E7=BE=A4=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E5=BA=94=E7=94=A8=E5=9C=BA=E6=99=AF.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Redis/redis集群以及应用场景.md | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 docs/database/Redis/redis集群以及应用场景.md diff --git a/docs/database/Redis/redis集群以及应用场景.md b/docs/database/Redis/redis集群以及应用场景.md new file mode 100644 index 00000000..c963ffc3 --- /dev/null +++ b/docs/database/Redis/redis集群以及应用场景.md @@ -0,0 +1,145 @@ +# Redis 集群以及应用 + +## 集群 +### 主从复制 +#### 主从链(拓扑结构) +![主从](https://user-images.githubusercontent.com/26766909/67539461-d1a26c00-f714-11e9-81ae-61fa89faf156.png) + +![主从](https://user-images.githubusercontent.com/26766909/67539485-e0891e80-f714-11e9-8980-d253239fcd8b.png) + +#### 复制模式 +- 全量复制:master 全部同步到 slave +- 部分复制:slave 数据丢失进行备份 + +#### 问题点 +- 同步故障 + - 复制数据延迟(不一致) + - 读取过期数据(Slave 不能删除数据) + - 从节点故障 + - 主节点故障 +- 配置不一致 + - maxmemory 不一致:丢失数据 + - 优化参数不一致:内存不一致. +- 避免全量复制 + - 选择小主节点(分片)、低峰期间操作. + - 如果节点运行 id 不匹配(如主节点重启、运行 id 发送变化),此时要执行全量复制,应该配合哨兵和集群解决. + - 主从复制挤压缓冲区不足产生的问题(网络中断,部分复制无法满足),可增大复制缓冲区( rel_backlog_size 参数). +- 复制风暴 + +### 哨兵机制 +#### 拓扑图 +![image](https://user-images.githubusercontent.com/26766909/67539495-f0086780-f714-11e9-9eab-c11a163ac6c0.png) + +#### 节点下线 +- 客观下线 + - 所有 Sentinel 节点对 Redis 节点失败要达成共识,即超过 quorum 个统一. +- 主管下线 + - 即 Sentinel 节点对 Redis 节点失败的偏见,超出超时时间认为 Master 已经宕机. +#### leader选举 +- 选举出一个 Sentinel 作为 Leader:集群中至少有三个 Sentinel 节点,但只有其中一个节点可完成故障转移.通过以下命令可以进行失败判定或领导者选举. +- 选举流程 + 1. 每个主观下线的 Sentinel 节点向其他 Sentinel 节点发送命令,要求设置它为领导者. + 1. 收到命令的 Sentinel 节点如果没有同意通过其他 Sentinel 节点发送的命令,则同意该请求,否则拒绝. + 1. 如果该 Sentinel 节点发现自己的票数已经超过 Sentinel 集合半数且超过 quorum,则它成为领导者. + 1. 如果此过程有多个 Sentinel 节点成为领导者,则等待一段时间再重新进行选举. +#### 故障转移 +- 转移流程 + 1. Sentinel 选出一个合适的 Slave 作为新的 Master(slaveof no one 命令). + 1. 向其余 Slave 发出通知,让它们成为新 Master 的 Slave( parallel-syncs 参数). + 1. 等待旧 Master 复活,并使之称为新 Master 的 Slave. + 1. 向客户端通知 Master 变化. +- 从 Slave 中选择新 Master 节点的规则(slave 升级成 master 之后) + 1. 选择 slave-priority 最高的节点. + 1. 选择复制偏移量最大的节点(同步数据最多). + 1. 选择 runId 最小的节点. +#### 读写分离 +#### 定时任务 +- 每 1s 每个 Sentinel 对其他 Sentinel 和 Redis 执行 ping,进行心跳检测. +- 每 2s 每个 Sentinel 通过 Master 的 Channel 交换信息(pub - sub). +- 每 10s 每个 Sentinel 对 Master 和 Slave 执行 info,目的是发现 Slave 节点、确定主从关系. + +### 分布式集群(Cluster) +#### 拓扑图 + +![image](https://user-images.githubusercontent.com/26766909/67539510-f8f93900-f714-11e9-9d8d-08afdecff95a.png) + +#### 通讯 +##### 集中式 +> 将集群元数据(节点信息、故障等等)几种存储在某个节点上. +- 优势 + 1. 元数据的更新读取具有很强的时效性,元数据修改立即更新 +- 劣势 + 1. 数据集中存储 +##### Gossip +![image](https://user-images.githubusercontent.com/26766909/67539546-16c69e00-f715-11e9-9891-1e81b6af624c.png) + +- [Gossip 协议](https://www.jianshu.com/p/8279d6fd65bb) + +#### 寻址分片 +##### hash取模 +- hash(key)%机器数量 +- 问题 + 1. 机器宕机,造成数据丢失,数据读取失败 + 1. 伸缩性 +##### 一致性hash +- ![image](https://user-images.githubusercontent.com/26766909/67539595-352c9980-f715-11e9-8e4a-9d9c04027785.png) + +- 问题 + 1. 一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成缓存热点的问题。 + - 解决方案 + - 可以通过引入虚拟节点机制解决:即对每一个节点计算多个 hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。 +##### hash槽 +- CRC16(key)%16384 +- +![image](https://user-images.githubusercontent.com/26766909/67539610-3fe72e80-f715-11e9-8e0d-ea58bc965795.png) + + + + + + +## 使用场景 +### 热点数据 +### 会话维持 session +### 分布式锁 SETNX +### 表缓存 +### 消息队列 list +### 计数器 string + + + + + +## 缓存设计 +### 更新策略 +- LRU、LFU、FIFO 算法自动清除:一致性最差,维护成本低. +- 超时自动清除(key expire):一致性较差,维护成本低. +- 主动更新:代码层面控制生命周期,一致性最好,维护成本高. +### 更新一致性 +- 读请求:先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应. +- 写请求:先删除缓存,然后再更新数据库(避免大量地写、却又不经常读的数据导致缓存频繁更新). +### 缓存粒度 +- 通用性:全量属性更好. +- 占用空间:部分属性更好. +- 代码维护成本. + +### 缓存穿透 +> 当大量的请求无命中缓存、直接请求到后端数据库(业务代码的 bug、或恶意攻击),同时后端数据库也没有查询到相应的记录、无法添加缓存. + 这种状态会一直维持,流量一直打到存储层上,无法利用缓存、还会给存储层带来巨大压力. +> +#### 解决方案 +1. 请求无法命中缓存、同时数据库记录为空时在缓存添加该 key 的空对象(设置过期时间),缺点是可能会在缓存中添加大量的空值键(比如遭到恶意攻击或爬虫),而且缓存层和存储层数据短期内不一致; +1. 使用布隆过滤器在缓存层前拦截非法请求、自动为空值添加黑名单(同时可能要为误判的记录添加白名单).但需要考虑布隆过滤器的维护(离线生成/ 实时生成). +### 缓存雪崩 +> 缓存崩溃时请求会直接落到数据库上,很可能由于无法承受大量的并发请求而崩溃,此时如果只重启数据库,或因为缓存重启后没有数据,新的流量进来很快又会把数据库击倒 +> +#### 出现后应对 +- 事前:Redis 高可用,主从 + 哨兵,Redis Cluster,避免全盘崩溃. +- 事中:本地 ehcache 缓存 + hystrix 限流 & 降级,避免数据库承受太多压力. +- 事后:Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据. +#### 请求过程 +1. 用户请求先访问本地缓存,无命中后再访问 Redis,如果本地缓存和 Redis 都没有再查数据库,并把数据添加到本地缓存和 Redis; +1. 由于设置了限流,一段时间范围内超出的请求走降级处理(返回默认值,或给出友情提示). + + +