Redis架构手记

目录

1、Redis持久化

  • 优缺点对比
  • 实际配置
  • 根据RDB文件的恢复过程

2、Redis读写分离架构

  • 注意事项
  • 复制流程
  • 数据丢失场景
  • 哨兵

3、Redis集群架构

  • 数据的负载均衡算法
  • 实际操作
  • 主备切换过程

4、缓存架构

  • 一般缓存架构
  • 多级缓存架构

5、数据清除策略

  • 配置
  • 流程

Redis持久化

持久化策略共提供了两种

  • RDB 全量备份
    每隔一个时间间隔做Redis的一份快照,记录当前Redis中的全都数据

  • AOF 增量备份
    记录Redis的每一次操作到AOF文件

AOF流程:

Redis只有一个AOF文件,在Redis和AOF文件间存在一个OSCache系统级缓存,Redis每次写操作先存储在OSCache中,每隔一段时间执行fsync操作,将OSCache中的数据再写入磁盘中的AOF文件,这时才真正的存储在磁盘上。

Redis的内存是一定量的,AOF则是记录每条数据的操作,所以会逐渐变大。当Redis执行LRU策略淘汰某些数据时,AOF中记录的数据就会过期,所以当AOF到一定程度时会有rewrite操作。rewrite操作会根据当前Redis中的数据,重新构建一个新AOF文件,以清除过期失效的记录缩小AOF文件大小,构建完成后替换旧的AOF文件。

优缺点对比

RDB优点:适合冷备、性能高(不必一条条记录写磁盘)、数据恢复快
RDB缺点:丢数据多(时间间隔内的数据)、数据量多时恢复会有延迟

AOF优点:最多丢时间间隔内的数据(间隔比RDB短)、append-only模式不需寻址写入AOF文件性能高,文件不易破损
AOF缺点:相同情况下AOF文件大于RDB文件大小、拖慢Redis的QPS、数据恢复慢(重放操作)

实际配置

RDB

redis.conf文件,SNAPSHOTTING节点下设置RDB的相关参数

默认设置
save 900 1
save 300 10
save 60 1000
即:每隔60秒超过1000个key发生变更,则生成一个dump.rdb文件
配置文件内可配置多个检查点

生成的dump.rdb文件在配置的dir目录下,新文件覆盖旧文件

安全退出Redis,会自动触发生成当前Redis的dump.rdb文件

AOF

redis.conf文件,APPEND ONLY MODE节点下设置AOF的相关参数

RDB是默认打开的,而AOF是默认关闭

appendonly yes 打开AOF

若Redis重启且AOF和RDB都开启的情况下,优先AOF恢复(数据完整性较RDB好)在dir目录下查找AOF文件进行恢复

fsync操作的设置,会影响数据的丢失量

appendfsync always 每写入一条数据,立即执行fsync操作将数据写入磁盘,性能差、吞吐量低
appendfsync everysec 每秒将OSCache中的数据刷入磁盘,QPS在万级别,默认项
appendfsync no 数据进入OSCache后,由OS决定刷入磁盘的时机

rewrite策略,控制AOF文件不至于无限增长

auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb

较上次rewrite的AOF文件大小,增长比例达到100%,且AOF文件大于min-size大小,则触发rewrite操作

rewrite流程:

  • Redis fork一个子进程,基于当前内存的数据构建日志,写入新AOF文件中。
  • 此时Redis主进程能继续接收外部的写操作,并将操作记录存入一块内存同时写入旧AOF文件中。
  • 子进程完成后,主进程将内存中新记录追加到新AOF文件中
  • 新AOF文件替换旧AOF文件

AOF 文件修复

因为AOF文件采用append-only模式写入,所以文件破损只会发生在文件尾部

redis-check-aof --fix [file] 通过此命令进行AOF的文件修复

RDB全量备份与AOF的rewrite不会同时进行,若发生则等待前一操作完成后执行(磁盘IO开销太大)

根据RDB文件的恢复过程

1.关闭AOF配置项,否则默认根据AOF恢复,如没有发现AOF文件则会生成一份空的AOF文件,并根据空的AOF文件恢复

2.拷贝RDB文件到目录,重启Redis,完成恢复

3.热修改开启AOF,这时生成的AOF文件会存储当前数据,但通过热修改配置的方式在配置文件内并没有实际修改

4.关闭Redis,手动修改配置开启AOF,再次重启Redis

Redis读写分离架构

Redis缓存主要应对的是读请求场景,对于未命中项则会请求到数据库,MySQL正常的QPS在1~2K。要想达到高并发,需要将读请求在Redis缓存层处理掉。

单机Redis可承载万级的QPS(视业务场景、机器而定),要承载更高的并发需要进行读写分离,master node只负责写操作,slave node负责读操作,两者数据一致。当并发量增加时,可横向扩展增加slave node来分摊QPS。

注意事项

  • master node采用异步的方式复制数据到slave node,不会影响master node的正常操作

  • slave node复制数据期间会提供对外的读操作,只不过数据复制完成前提供的数据是旧数据。复制完成后,删除旧数据加载新数据阶段,会暂停对外的服务。

  • 采用主从架构需要对master node做持久化,否则master node故障重启后(侦测机制还未触发)数据丢失,将会影响所有的slave node

  • slave node不会过期key,master node过期key后会del通知给slave node

  • master node和slave node之间通过心跳相互联系

  • 一个master node可以配置多个slave node,slave node之间也可以互相连接

复制流程

slave node启动时,读取conf配置slaveof中master node的IP和port,slave node内部的定时任务,定期检查是否有新的master node需要连接和复制,并进行socket连接

slave node发送ping命令给master node,若master node设置了requirepass,则slave node必须发送masterauth口令进行认证

如果是第一次连接会触发full resynchronization,master node采用异步的方式复制数据到slave node;如果是重连,master node仅会复制slave node缺少的数据。

开始full resynchronization时,master node会用后台线程做一份RDB的快照文件,slave node会将RDB文件写入自己的磁盘后再加载到内存。期间master node的写操作会记录在内存,master node会将内存中的写命令发送给slave node

master node和slave node都会维护一个offset,且在不断累加,记录当前的数据。slave node会定期上报master node自己的offset,master node也会记录各个slave node的offset,用来知晓相互间的数据差异。

若在复制的过程中连接断开重连,slave node可以从offset的位置继续复制,如果找不到对应的offset则会执行resynchronization;slave node也会记录master run id,若发现master run id不同,可能是master node重启或发生变化,需要做全量复制

配置文件redis.conf中可以设置生成的RDB文件是否落在本地磁盘

repl-diskless-sync no 是否开启无磁盘化复制
repl-diskless-sync-delay [] 延迟复制,等待更多的slave node连接

参数配置

slaveof [ip] [port] 填入master node的信息
slave-read-only yes 默认开启slave node只读

数据丢失场景

异步复制
集群脑裂

解决方法

min-slaves-to-write 1 最少要写入slave node的数量为1
min-slaves-max-lag 10 master node和slave node间数据延迟不能超过10秒
此配置默认未开启

此配置只是降低数据损失量,剩余要client做降级操作减少损失

哨兵

哨兵是分布式的架构,最少有3个实例,以保证自己的健壮性。

哨兵只保证Redis的高可用,不保证数据的零丢失

哨兵间的通讯通过Redis的pub/sub系统实现

功能

  • 集群监控 监控Redis中master node和slave node是否正常工作
  • 消息通知 Redis实例故障时发送通知
  • 故障转移 如果master node故障,会选举新master node
  • 配置中心 故障转移时会将新配置项通知各个端

工作流程

哨兵有两种失败状态,1个哨兵认为master node挂了就是sdown(主观宕机),quorum数量个哨兵认为master node挂了就是odown(客观宕机)。

当哨兵ping master node响应时间超过设置的down-after-milliseconds时进入sdown状态

如果master node被认为odown,且有majority数量的哨兵允许主备切换,就会有一个哨兵执行主备切换的操作,选举一个slave node作为新master node

考虑因素包括:与master node断开的时长、slave node的优先级、offset值、run id值

配置参数

sentinel.conf

哨兵可以监控多个Redis的主从架构
sentinel monitor [架构名] [ip] [quorum] 监控的主从架构信息
sentinel down-after-milliseconds [架构名] 60000 超过设置时间认为sdown
sentinel failover-timeout [架构名] 180000 执行故障转移的超时时间
sentinel parallel-sync [架构名] 1 并行同步数,新选举的master node,每次同步slave node的数据量,数据同步完成后才会执行后面slave node的同步

port [] 端口号
bind [ip] 绑定本机IP
daemonize yes 后台执行
logfile /var/log/sentinel/*.log 设置日志文件

Redis集群架构

  • 读写分离架构:master node负责写操作,slave node负责读操作,配合哨兵能够达到高可用。

  • 集群架构:存在多个master node,每个master node上可挂载多个slave node。各个master node之间数据不同,能够提供读写操作。当master node挂掉后,slave node顶上以达到高可用。

读写分离的架构能够存储的数据量仅为master node的内存容量,在海量数据场景下会产生瓶颈,因此在海量数据场景下适用集群架构

数据的负载均衡算法

Hash算法(散列算法)用一种较短的信息来保证内容唯一性的算法。在Redis集群架构下如果某一节点挂了,则会导致全部信息失效。

一致性Hash算法,节点之间采用环形,在Redis集群架构下如果某一节点挂了,则只会丢失此节点数据。热点问题采用虚拟节点来负载均衡

Hash slot算法,数据存储在slot上,slot存储在节点上,如果某一节点挂了,数据是寻找slot而不是节点,且挂掉的节点会将本节点上的slot迁移到其他节点。

实际操作

配置参数

cluster-enabled yes 启动集群架构,不可同时开启读写分离架构
cluster-config-file [配置文件] 指定配置文件
cluster-node-timeout [] 节点超时时长,超时则主备切换

port []
daemonize yes
pidfile /var/run/redis_[port].pid
dir /var/redis/[port]
logfile /var/log/redis/[port].log
bind [ip]
appendonly yes

集群操作

redis-trib.rb create --replicas [slave node数量] [ip:port] [ip:port] [ip:port] [ip:port]... 启动cluster

redis-trib.rb add-node [ip:port]... 扩容master

redis-trib.rb reshard [ip:port] 会有交互提示输入数据迁移的参数

redis-trib.rb add-node --slave --master-id [id] [ip:port] 给master节点增加slave

redis-trib.rb del-node [ip:port] [id] 删除节点

master node不存在slot时,cluster会将其slave node挂到其他master node上

cluster会将冗余的slave node分配给其他master node,以保证高可用

主备切换过程

各个节点保存集群元数据,节点间采用gossip协议进行通讯,通过节点间不断的通讯以保持整个集群的数据完整性

当一个节点认为另一个节点宕机了(响应时间超过cluster-node-timeout)称为pfail(主观宕机),多个节点认为一个节点宕机了称为fail(客观宕机)

对于宕机的master node,从其slave node中选取一个切换为master node

筛选的条件和哨兵类似:断开连接时间(时间超过cluster-node-timeout*cluster-slave-validity-factory的slave node没有资格参见选举)、priority、offset、run id

缓存架构

一般缓存架构

1.用户发起请求
2.读请求发起后被web服务器转发到web服务上
3.web服务先向Redis缓存查询
4.数据命中则将数据返回给用户
5.未命中则去数据库查询数据
6.数据命中后返回给web服务
7.web服务接收到数据后将数据返回给用户,同时缓存数据

多级缓存架构

缓存操作

  • 同步缓存操作

1.用户向XX服务发送写请求
2.XX服务将数据同步更新到DB和Redis缓存

  • 异步缓存操作

1.用户向XX服务发送写请求
2.XX服务将数据更新到DB同时向MQ发送消息
3.web服务接收到消息后,将数据写到本地缓存和Redis缓存中

读取操作

1.用户向web服务器发送读请求
2.在web服务器缓存中命中则返回,否则向Redis缓存请求数据
3.Redis缓存命中则返回数据
4.web服务器接收到Redis缓存中的数据则返回,否则向web服务发起读请求
5.web服务在堆缓存中查找数据,命中则返回并缓存到Redis缓存
6.web服务在堆缓存中未命中数据,则向DB请求数据
7.DB将数据返回给web服务
8.web服务拿到数据后,将数据在堆缓存、Redis缓存中保存,并返回web服务器

web服务器Nginx本地缓存主要存储热点数据,避免不必要的访问网络开销

Redis分布式大规模缓存,对应的是海量离散数据

web服务的堆缓存是为了避免Redis宕机,导致web服务器大量的请求涌入,打死DB(虽然效果甚微,总比没有要强)

数据清除策略

  • 一种是对key设置存活时间(TTL),当访问的key超过存活时间,则返回null并删除本地数据

  • 另一种则是存储的数据量超过了最大设置量

以下内容为第二种策略

配置

maxmemory 设置数据清除策略开始的大小
maxmemory-policy 数据满是所执行的策略

noeviction 拒绝写入
allkeys-lru 所有key执行LRU
volatile-lru 仅对设置了存活时间(TTL)的key执行LRU
allkeys-random 随机删除key
volatile-random 随机挑选设置了存活时间(TTL)的key删除
volatile-ttl 移除TTL较短的key

流程

1.外部有写入请求
2.检查是否超过maxmemory限制,是则执行maxmemory-policy策略清除部分数据
3.执行写入操作

常用策略:allkeys-lru

Redis的LRU清除策略是近似的LRU算法,它通过采样采集数据进行处理而非全量数据,采样参数maxmemory-sample

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容