Redis-分布式缓存(一)

零、本文纲要

一、单机Redis的问题
二、Redis持久化
(一)RDB持久化
(二)AOF持久化
(三)RDB与AOF对比
三、Redis主从

tips:Ctrl + F快速定位所需内容进行阅读吧。

一、单机Redis的问题

1、数据丢失问题

实现Redis数据持久化;

2、并发能力问题

搭建主从集群,实现读写分离;

3、故障恢复问题

利用哨兵机制,实现健康检测和自动恢复;

4、存储能力问题

搭建分片集群,利用插槽机制实现动态扩容。

二、Redis持久化

(一)RDB持久化

1、RDB持久化

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录

2、持久化执行时机

  • ① 执行save命令
    由Redis主进程来执行RDB,会阻塞所有命令;
127.0.0.1:6379> save 
OK
  • ② 执行bgsave命令
    开启子进程执行RDB,主进程可以继续处理用户请求,不受影响;
127.0.0.1:6379> bgsave
Background saving started
  • ③ Redis停机时;
    Redis停机时会执行一次save命令,实现RDB持久化,如下日志中的Saving the final RDB snapshot before exiting.
[47784] 30 Mar 21:55:57.615 # User requested shutdown... # 用户请求关闭服务                                        
[47784] 30 Mar 21:55:57.615 * Saving the final RDB snapshot before exiting.  # 在退出前保存RDB快照
[47784] 30 Mar 21:55:57.617 * DB saved on disk # DB快照成功保存至磁盘                    
[47784] 30 Mar 21:55:57.617 # Redis is now ready to exit, bye bye... # Redis准备退出,拜拜...
  • ④ 触发RDB条件时。
    Redis内部有触发RDB的机制(执行的是bgsave命令),可以在redis.conf文件中找到,格式如下:
#   save "" # remove all the previously configured save points # 开启此配置会使RDB持久化失效,默认关闭
save 900 1  # after 900 sec (15 min) if at least 1 key changed # 900秒内至少1个写操作,则触发RDB持久化
save 300 10  # after 300 sec (5 min) if at least 10 keys changed # 300秒内至少10个写操作,则触发RDB持久化
save 60 10000  # after 60 sec if at least 10000 keys changed # 60秒内至少10000个写操作,则触发RDB持久化

3、bgsave原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。
RDB原理.png
  • ① bgsave过程

fork主进程得到一个子进程共享内存空间;
Ⅱ 子进程读取内存数据并写入新的RDB文件
Ⅲ 用RDB文件替换旧的RDB文件。

  • ② bgsave缺点

Ⅰ 如果未触发条件宕机,两次bgsave间的数据有丢失风险;
Ⅱ fork子进程、压缩、写出RDB文件都比较耗时;
Ⅲ 写新的RDB文件时,主进程是copy数据副本操作的,如果大量的写操作则需要更多的内存空间。

注意:copy-on-write在理论极端情况下可能需要双倍的内存,所以实际生产环境请给Redis预留一些额外内存。

(二)AOF持久化

1、AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件

2、AOF配置

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"

AOF的命令记录的频率也可以通过redis.conf文件来配:

# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always 
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
appendonly.aof文件.png

3、AOF文件重写

AOF文件因为是记录命令,所以会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k1 v2
OK 
127.0.0.1:6379> set k2 v3
OK
127.0.0.1:6379> set k2 v4
OK
127.0.0.1:6379> bgrewriteaof  
Background append only file rewriting started

上述案例四条指令其实可以简化成mset k1 v2 k2 v4,使用bgrewriteaof指令可以帮助我们完成命令重写。

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写 
auto-aof-rewrite-min-size 64mb 

(三)RDB与AOF对比

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

RDB与AOF对比.png

三、Redis主从

(一)单机搭建主从

1、准备实例和配置

  • ① 创建各实例目录
# 进入/tmp目录
cd /tmp
# 创建目录
mkdir 7001 7002 7003
  • ② 拷贝配置文件到每个实例目录
    Ⅰ xargs:命令格式somecommand |xargs -item command
    Ⅱ -n num:后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的,此处我们指定-n 1
    Ⅲ -t 表示先打印命令,然后再执行;
    Ⅳ echo:用于字符串的输出,echo 7001 7002 7003输出字符串到|后面的命令。
# 方式一:逐个拷贝
cp /usr/local/src/redis-6.2.6/redis.conf 7001 
cp /usr/local/src/redis-6.2.6/redis.conf 7002 
cp /usr/local/src/redis-6.2.6/redis.conf 7003

# 方式二:管道组合命令,一键拷贝
echo 7001 7002 7003 | xargs -t -n 1 cp /usr/local/src/redis-6.2.6/redis.conf
  • ③ 修改每个实例的端口、工作目录
    Ⅰ sed:利用脚本来处理文本文件,语法sed [-hnV][-e<script>][-f<script文件>][文本文件]
    Ⅱ 数据的搜寻并替换:sed 's/要被取代的字串/新的字串/g',寻找dir .\/替换成dir \/tmp\/7001\/,其中\/是起到转义\的作用,等价于将dir ./替换成dir /tmp/7001/
    Ⅲ -e:表示多点编辑;
    Ⅳ -i:该选项可以直接修改文件内容,省去vi/vim操作;

修改每个文件夹内的配置文件,将端口分别修改为7001、7002、7003,将rdb文件保存位置都修改为自己所在目录(在/tmp目录执行下列命令):

sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf
sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf
sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf
  • ④ 修改每个实例声明的IP

虚拟机本身有多个IP,为了避免将来混乱,我们需要在redis.conf文件中指定每一个实例的绑定ip信息,格式如下:

# redis实例的声明 IP
replica-announce-ip 192.168.150.101
# 方式一:添加
sed -i 1a replica-announce-ip 192.168.150.101 7001/redis.conf 
sed -i 1a replica-announce-ip 192.168.150.101 7002/redis.conf 
sed -i 1a replica-announce-ip 192.168.150.101 7003/redis.conf

# 方式二:一键修改
printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip 192.168.150.101' {}/redis.conf

2、启动各实例

  • ① 批量启动
    Ⅰ printf:语法printf format-string [arguments...]
    Ⅱ %s:输出一个字符串;
    Ⅲ \n:换行;
    Ⅳ {}:指定一个替换字符串,一般是一行一行赋值给 {};
# 第1个
redis-server 7001/redis.conf
# 第2个
redis-server 7002/redis.conf
# 第3个
redis-server 7003/redis.conf

printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-server {}/redis.conf
  • ② 批量停止
    停止各实例的指令:
redis-cli -p 7001 shutdown 
redis-cli -p 7002 shutdown 
redis-cli -p 7003 shutdown

printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-cli -p {} shutdown

3、开启主从关系

要配置主从可以使用replicaof 或者slaveof(5.0以前)命令。

  • ① 主从关系配置

Ⅰ 修改配置文件(永久生效)
在redis.conf中添加一行配置:slaveof <masterip> <masterport>

Ⅱ 使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):

slaveof <masterip> <masterport>

注意:在5.0以后新增命令replicaof,与salveof效果一致。

  • ② 开启主从关系
# 连接 7002
redis-cli -p 7002
# 执行slaveof
slaveof 192.168.253.128 7001

# 连接 7003
redis-cli -p 7003
# 执行replicaof 
replicaof 192.168.253.128 7001

# 连接 7001
redis-cli -p 7001
# 查看状态
info replication
开启主从关系.png
  • ③ 测试主从

Ⅰ 主:可读可写;
Ⅱ 从:可读。

测试主从.png

(二)数据同步原理

1、全量同步

  • ① 全量同步过程

主从第一次连接时会发生全量同步:

全量同步.png
  • ② 全量同步原理

Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid;

offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

2、增量同步

  • ① 增量同步过程

从节点再次连接主节点,则可能发生增量同步,也可能是全量同步:

增量同步.png

repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步

repl_baklog覆盖.png

3、优化主从集群

  • ① 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO;
  • ② Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO;
  • ③ 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步;
  • ④ 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力。

四、结尾

以上即为Redis分布式缓存(一)的内容,感谢阅读。

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

推荐阅读更多精彩内容