一.redis基本使用
神作:https://blog.51cto.com/linuxg/1862040
https://baijiahao.baidu.com/s?id=1625360738807649917&wfr=spider&for=pc
1.redis数据持久化相关介绍
# AOF和RDB持久性可以同时启用而没有问题。 如果在启动时启用AOF,Redis将加载AOF,这是具有更好的持久性保证的文件。
# Please check http://redis.io/topics/persistence for more information.
appendonly no ##aof日志的类型默认是no,如果要保持更好的数据持久性,设置为yes
补充:appendonly yes/no appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。
# The name of the append only file (default: "appendonly.aof")
仅追加文件的名称(默认值:“appendonly.aof”)
appendfilename "appendonly.aof"
appendfsync everysec #默认everysec即可
# appendfsync no
注:appendfsync no/always/everysec ,appendfsync是Redis将OS数据缓冲区中数据刷新到磁盘的策略
no表示操作系统不进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次,默认是everysec。
redis与memcached等缓存系统有一个最大的区别就是可以定期将内存中的数据保存到硬盘中,以实现数据持久化。
redis实现数据持久化有两种方式:第一种是RDB快照方式;另外一种是AOF方式!
1、RDB持久化
RDB持久化是根据一定的保存规则定期对redis在内存中的数据做一个快照,把快照数据同步到硬盘上,每次的快照文件就是一个保存着redis数据的二进制文件(log)。它也是redis默认的持久化方法。
RDB持久化保存快照文件的过程:
a、redis快照启动后,创建一个当前进程(父进程)的副本(子进程)。
b、父进程继续接受来自客户端的命令,子进程将内存中的数据开始同步到硬盘中,保存到一个临时文件中。
c、子进程完成快照后,快照的临时文件替换旧的快照文件,并断开与父进程的连接。
# 下面的例子的意思是:
# 900 秒内如果至少有 1 个 key 的值变化,则保存
# 300 秒内如果至少有 10 个 key 的值变化,则保存
# 60 秒内如果至少有 10000 个 key 的值变化,则保存
#
# 注意:你可以注释掉所有的 save 行来停用保存功能。
# 也可以直接一个空字符串来实现停用:
# save ""
RDB持久化配置,在redis.conf中,默认如下:
save 900 1
save 300 10
save 60 10000
这是一个保存规则,前面的redis配置文件详解中有介绍!
注意:如果不想启用RDB持久化,将save参数删除掉或者注释掉即可!
RDB持久化其他配置
dir ./ #持久化文件保存目录,可以自定义
dbfilename dump.rdb #RDB持久化保存的文件名,也可以自定义
stop-writes-on-bgsave-error yes #当保存时遇到错误(磁盘或者其他硬件错误)是否停止写入,默认为yes
rdbcompression yes #保存文件时是否启动压缩
rdbchecksum yes #是否启用RDB数据检验
在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发。
针对RDB方式的持久化,手动触发可以使用:
save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。
而自动触发的场景主要是有以下几点:
根据我们的 save m n 配置规则自动触发;
从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave;
执行 debug reload 时;
执行 shutdown时,如果没有开启aof,也会触发。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
除了save还有其他的保存方式么?
save 和 bgsave 保存
有的,Redis 提供了save和bgsave这两种不同的保存方式,并且这两个方式在执行的时候都会调用rdbSave函数,但它们调用的方式各有不同:
save 直接调用 rdbSave方法 ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
bgsave 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。因为 rdbSave 在子进程被调用,所以 Redis 服务器在 bgsave 执行期间仍然可以继续处理客户端的请求。
save 是同步操作,bgsave 是异步操作。
bgsave命令的使用方法和save命令的使用方法是一样的:

这里注意的是 fork 操作会阻塞,导致Redis读写性能下降。我们可以控制单个Redis实例的最大内存,来尽可能降低Redis在fork时的事件消耗。以及上面提到的自动触发的频率减少fork次数,或者使用手动触发,根据自己的机制来完成持久化。
2、AOF持久化
AOF持久化是将用户操作的命令(主要对修改数据的命令,就是除了查询以外的命令,包括增删改的命令)保存到一个文本文件中。
AOF持久化配置,在redis.conf中:
appendonly yes #默认是no,启动aof,就修改为yes
appendfilename "appendonly.aof" #保存aof持久化的文件名
appendfsync everysec #aof文件同步频率
注:启用AOF持久化,并不是马上将内存数据写到文件中,它是将它写到硬盘缓存中,然后根据一定频率同步到文件中
共有三个值可选择:always表示只要有更新就同步;everysec是每秒种同步一次;no表示不同步!
no-appendfsync-on-rewrite no #在不启用硬盘缓存同步到硬盘文件这个选项时,是否重写文件,默认为no,
如果发生redis服务阻塞,将此参数改为yes!
#重写文件的频率#
auto-aof-rewrite-percentage 100 #第一种表示当文件超过旧文件100%时进行重写
auto-aof-rewrite-min-size 64mb #第二种表示当文件超过64mb时进行重写
aof-load-truncated yes #当redis遇到退出时,重新载入时是否加载异常出现时的残余数据,默认yes
appendfsync everysec 它其实有三种模式:
always:把每个写命令都立即同步到aof,很慢,但是很安全
everysec:每秒同步一次,是折中方案
no:redis不处理交给OS来处理,非常快,但是也最不安全
AOF的整个流程大体来看可以分为两步,一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗),第二步是对aof文件的重写。
对于增量追加到文件这一步主要的流程是:命令写入=》追加到aof_buf =》同步到aof磁盘。那么这里为什么要先写入buf在同步到磁盘呢?如果实时写入磁盘会带来非常高的磁盘IO,影响整体性能。
aof重写是为了减少aof文件的大小,可以手动或者自动触发,关于自动触发的规则请看上面配置部分。fork的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。
手动触发: bgrewriteaof

AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:
Redis 执行 fork() ,现在同时拥有父进程和子进程。
子进程开始将新 AOF 文件的内容写入到临时文件。
对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
自动触发重写操作
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
3、RDB和AOF的比较以及优缺点
RDB优点:
a、RDB是一个非常紧凑(compact)的文件,保存了redis在某个时间点上的数据集,这种文件非常适合用于进行备份
可以根据自己的需求自定义备份,比如每小时备份一次RDB文件,或者每个月的每一天,也备份一个RDB文件。
b、RDB非常适用于灾难恢复(disaster recovery),它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的服务器。
c、RDB可以最大化Redis的性能:父进程在保存RDB文件时唯一要做的就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作
d、RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB缺点:
a、如果你无法接受偶尔的数据丢失,rdb方式不适合你,虽然这种方式可以自定义不同的save point来控制保存rdb文件的频率
但是,因为RDB文件需要保存整个数据集的状态,所以它并不是一个轻松的操作。因此你可能会至少5分钟才保存一次RDB文件。
在这种情况下,一旦发生故障停机,你就可能会丢失好几分钟的数据。
b、每次保存RDB的时候,Redis都要fork()出一个子进程,并由子进程来进行实际的持久化工作。在数据集比较庞大时,fork()会非常耗时和耗费内存资源
而且造成服务器在某某毫秒内停止处理客户端;如果数据集非常巨大,并且CPU时间非常紧张的话,那么这种停止时间甚至可能会更长!
#####
AOF优点
a、使用AOF持久化会让Redis变得非常耐久(much more durable),AOF的默认策略为每秒钟fsync一次,在这种配置下Redis仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据!
b、AOF文件是一个只进行追加操作的日志文件(append only log)因此对AOF文件的写入不需要进行seek,即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等),redis-check-aof工具也可以轻易地修复这种问题.
c、Redis可以在AOF文件体积变得过大时,自动地在后台对AOF进行重写:重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合
d、AOF重写也需要进行fork(),但无论AOF重写的执行间隔有多长,数据的耐久性都不会有任何损失。
AOF缺点
a、对于相同的数据集来说,AOF文件的体积通常要大于RDB文件的体积
b、在一般情况下,每秒fsync的性能依然非常高,而关闭fsync可以让AOF的速度和RDB一样快,即使在高负荷之下也是如此。
不过在处理巨大的写入载入时,RDB可以提供更有保证的最大延迟时间(latency)

4、在生产环境中如何选择redis的持久化方式
一般来说,如果想达到足以媲美PostgreSQL的数据安全性,你应该同时使用两种持久化功能。如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。有很多用户都只使用AOF持久化,但并不推荐这种方式:因为定时生成RDB快照(snapshot)非常便于进行数据库备份,并且RDB恢复数据集的速度也要比AOF恢复的速度要快!
5、redis备份相关
注:我在生产环境就是取消配置文件中的save,只保留appendonly!
RDB+AOF的备份方式,如下:
在redis.conf中取消rdb的自动save配置,启动aof的配置:
#save 900 1 #注释或者删除
#save 300 10
#save 60 10000
appendonly yes #启用aof持久化
appendfilename "appendonly.aof"
然后在服务器上定时对RDB数据进行备份(也可以不备份RDB)
#redis-cli save 或者 #可以每周或者每天执行一次
#redis-cli -h 10.0.9.25 -p 6379 save(指定端口来备份)
如果设置了密码,可以添加-a 参数,如下:
./bin/redis-cli -h 10.0.9.25 -a abcd123 -p 6379 save
#每天执行一次下面的bgrewriteaof###
/usr/local/redis/bin/redis-cli -h host -p 6379 BGREWRITEAOF > /root/backup/log/`date`.log #这个必须执行
补充:
BGREWRITEAOF:执行一个AOF文件重写操作。重写会创建一个当前AOF文件的体积优化版本。即使BGREWRITEAOF执行失败,也不会有任何数据丢失,因为旧的AOF文件在BGREWRITEAOF成功之前不会被修改。重写操作只会在没有其他持久化工作在后台执行时被触发,也就是说:如果Redis的子进程正在执行快照的保存工作,那么AOF重写的操作会被预定(scheduled),等到保存工作完成之后再执行AOF重写。在这种情况下,BGREWRITEAOF的返回值仍然是OK ,但还会加上一条额外的信息,说明BGREWRITEAOF要等到保存操作完成之后才能执行。在Redis 2.6或以上的版本可以使用INFO命令查看BGREWRITEAOF是否被预定。如果已经有别的AOF文件重写在执行,那么BGREWRITEAOF返回一个错误,并且这个新的BGREWRITEAOF 请求也不会被预定到下次执行。
2.Mysql和Redis数据一致性问题
现在有很对的架构都采用Redis+Mysql的结构作为存储结构,但是有很多的情况都可以造成Redis和Mysql当中的数据不一致的问题,比如:当在mysql当中进行了数据的跟新,但是还未来的及在Redis当中进行同步,此时有客户访问redis就会造成数据的不一致性。
解决办法如下:
1.分别进行处理
将对实时性要求不是很高的数据存放在Redis当中,比如历史排名,近期回复等直接存放在redis当中,对于实时性要求比较高的数据,比如虚拟货币量,订单的数量等数据可以直接穿透Redis存放在Mysql数据库当中,然后在跟新完毕之后,刷新到redis当中,这样既可以让Redis起到大量查询分流的作用,又可以保障数据的一致性
2.高并发的情况
当用户写入的操作很多,在mysql当中写入十分慢,此时可以将数据更新到redis当中,再有redis每个一段时间刷新到mysql当中,如果写入的数据太少,可以在写入到redis以后,立马进行刷新到mysql
3.基于Binlog的订阅/推送方式
阿里巴巴发明了一种开源框架canal,提供了一种发布/订阅的同步模式,当mysql的binlog日志发生变化的时候,此框架会将binlog的相关消息推送至redis当中,然后redis在那种binlog当中的相关信息进行跟新操作。
这个方法听着好想和Mysql的主从复制一样,因为此方法是模仿mysql的主从复制来完成的,主库Master当中所以的增删改操作都会记录到binlog日志当中,存库salve当中有一个I/O线程在实时的监控binlog日志,一旦binlog发生变化,就会读取binlog当中变化的消息,然后写入自己的中继日志relay当中,调用另一个slave线程Sql去执行中继日志relay当中的sql,
3.redis如何解决key冲突?
1、业务隔离
不同的业务使用不同的redis集群,或者协议使用redis的不同db。
2、良好的Redis Key的设计
格式:业务标识:系统名称:模块名称:关键词简写
比如:保险:用户管理:用户申请:手机号
Redis Key:bx:um:reg:mobile
以上在实际的生产环境中,应该同时存在。
网友评论