前言
redis 实现高并发次要依附主从架构。
一主多从,一般来说,很多我的项目其实就足够了,单主用来写入数据,单机几万 QPS,多从用来查问数据,多个从实例能够提供每秒 10w 的 QPS。
如果想要在实现高并发的同时,包容大量的数据,那么就须要 redis 集群,应用 redis 集群之后,能够提供每秒几十万的读写并发。
1. redis 主从架构
单机的 redis,可能承载的 QPS 大略就在上万到几万不等。对于缓存来说,个别都是用来撑持读高并发的。因而架构做成主从 (master-slave) 架构,一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读申请全副走从节点。这样也能够很轻松实现程度扩容,撑持读高并发。
redis replication -> 主从架构 -> 读写拆散 -> 程度扩容撑持读高并发
redis replication 的外围机制
redis 采纳异步形式复制数据到 slave 节点,不过 redis2.8 开始,slave node 会周期性地确认本人每次复制的数据量;
一个 master node 是能够配置多个 slave node 的;
slave node 也能够连贯其余的 slave node;
slave node 做复制的时候,不会 block master node 的失常工作;
slave node 在做复制的时候,也不会 block 对本人的查问操作,它会用旧的数据集来提供服务;然而复制实现的时候,须要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了;
slave node 次要用来进行横向扩容,做读写拆散,扩容的 slave node 能够进步读的吞吐量。
留神,如果采纳了主从架构,那么倡议必须开启 master node 的长久化,不倡议用 slave node 作为 master node 的数据热备,因为那样的话,如果你关掉 master 的长久化,可能在 master 宕机重启的时候数据是空的,而后可能一通过复制,slave node 的数据也丢了。
另外,master 的各种备份计划,也须要做。万一本地的所有文件失落了,从备份中筛选一份 rdb 去复原 master,这样能力确保启动的时候,是有数据的,即便采纳了后续解说的高可用机制,slave node 能够主动接管 master node,但也可能 sentinel 还没检测到 master failure,master node 就主动重启了,还是可能导致下面所有的 slave node 数据被清空。
1.redis 主从复制的外围原理
当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node。如果这是 slave node 首次连贯到 master node,那么会触发一次 full resynchronization 全量复制。此时 master 会启动一个后盾线程,开始生成一份 RDB 快照文件,同时还会将从客户端 client 新收到的所有写命令缓存在内存中。RDB 文件生成结束后,master 会将这个 RDB 发送给 slave,slave 会先写入本地磁盘,而后再从本地磁盘加载到内存中,接着 master 会将内存中缓存的写命令发送到 slave,slave 也会同步这些数据。slave node 如果跟 master node 有网络故障,断开了连贯,会主动重连,连贯之后 master node 仅会复制给 slave 局部短少的数据。
#### 主从复制断点续传
从 redis2.8 开始,就反对主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么能够接着上次复制的中央,持续复制上来,而不是从头开始复制一份。
master node 会在内存中保护一个 backlog,master 和 slave 都会保留一个 replica offset 还有一个 master run id,offset 就是保留在 backlog 中的。如果 master 和 slave 网络连接断掉了,slave 会让 master 从上次 replica offset 开始持续复制,如果没有找到对应的 offset,那么就会执行一次 resynchronization。
如果依据 host+ip 定位 master node,是不靠谱的,如果 master node 重启或者数据呈现了变动,那么 slave node 应该依据不同的 run id 辨别。
无磁盘化复制
master 在内存中间接创立 RDB,而后发送给 slave,不会在本人本地落地磁盘了。只须要在配置文件中开启 repl-diskless-sync yes 即可。
repl-diskless-sync yes
# 期待 5s 后再开始复制,因为要等更多 slave 从新连贯过去
repl-diskless-sync-delay 5
过期 key 解决
slave 不会过期 key,只会期待 master 过期 key。如果 master 过期了一个 key,或者通过 LRU 淘汰了一个 key,那么会模仿一条 del 命令发送给 slave。
复制的残缺流程
slave node 启动时,会在本人本地保留 master node 的信息,包含 master node 的 host 和 ip,然而复制流程没开始。
slave node 外部有个定时工作,每秒查看是否有新的 master node 要连贯和复制,如果发现,就跟 master node 建设 socket 网络连接。而后 slave node 发送 ping 命令给 master node。如果 master 设置了 requirepass,那么 slave node 必须发送 masterauth 的口令过来进行认证。master node 第一次执行全量复制,将所有数据发给 slave node。而在后续,master node 继续将写命令,异步复制给 slave node。
全量复制
master 执行 bgsave,在本地生成一份 rdb 快照文件。
master node 将 rdb 快照文件发送给 slave node,如果 rdb 复制工夫超过 60 秒(repl-timeout),那么 slave node 就会认为复制失败,能够适当调大这个参数 (对于千兆网卡的机器,个别每秒传输 100MB,6G 文件,很可能超过 60s)
master node 在生成 rdb 时,会将所有新的写命令缓存在内存中,在 slave node 保留了 rdb 之后,再将新的写命令复制给 slave node。
如果在复制期间,内存缓冲区继续耗费超过 64MB,或者一次性超过 256MB,那么进行复制,复制失败。
client-output-buffer-limit slave 256MB 64MB 60
slave node 接管到 rdb 之后,清空本人的旧数据,而后从新加载 rdb 到本人的内存中,同时基于旧的数据版本对外提供服务。
如果 slave node 开启了 AOF,那么会立刻执行 BGREWRITEAOF,重写 AOF。
增量复制
如果全量复制过程中,master-slave 网络连接断掉,那么 slave 从新连贯 master 时,会触发增量复制。
master 间接从本人的 backlog 中获取局部失落的数据,发送给 slave node,默认 backlog 就是 1MB。
master 就是依据 slave 发送的 psync 中的 offset 来从 backlog 中获取数据的。
heartbeat
主从节点相互都会发送 heartbeat 信息。
master 默认每隔 10 秒 发送一次 heartbeat,slave node 每隔 1 秒 发送一个 heartbeat。
异步复制
master 每次接管到写命令之后,先在外部写入数据,而后异步发送给 slave node。