redis持久化的意义,在于故障恢复.
比如你部署了一个redis,作为cache缓存,当然也可以保存一些较为重要的数据。如果没有持久化的话,redis遇到灾难性故障的时候,就会丢失所有的数据
如果将数据持久化在磁盘上,然后定期比如说同步和备份到一些云存储服务上去,那么就可以保证数据不丢失全部,还是可以恢复一部分数据回来的.
RDB配置:
(1) 在redis.conf配置文件中配置如下:
save 60 1000
每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,快照.
也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成
save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件
3.1 RDB持久化机制的工作流程:
(1)redis根据配置自己尝试去生成rdb快照文件
(2)fork一个子进程出来
(3)子进程尝试将数据dump到临时的rdb快照文件中
(4)完成rdb快照文件的生成之后,就替换之前的旧的快照文件
dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照(如果没有对旧的快照进行覆盖的话,那么则会出现大量的重复快照文件,占用不必要的磁盘空间)
4 AOF的配置及使用详解(AOF的日志文件就一个):
(1)AOF持久化,默认是关闭的,默认打开RDB持久化
(2)appendonly yes,可以打开AOF持久化机制,在生产环境里面,一般来说AOF都是要打开的,除非你说随便丢个几分钟的数据也无所谓
(3)打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再fsync一下
(4)即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为aof数据比较完整
(5)AOF的fsync持久化策略(只有fsync到磁盘中了,才是安全的):
(always)每次写入一条数据就执行一次fsync(每次写入一条数据,立即将这个数据对应的写日志fsync到磁盘上去,性能非常非常差,吞吐量很低; 确保说redis里的数据一条都不丢);
一种是每隔一秒执行一次fsync(常用生产环境配置);
一种是不主动执行fsync(仅仅redis负责将数据写入os cache就撒手不管了,然后后面os自己会时不时有自己的策略将数据刷入磁盘,不可控了);
4.1 redis的rewrite操作: redis中的数据很多都会自动过期,以及用户会自己删除.很多数据不存在但是数据的写操作可能还记录在aof中,所以为了防止aof文件的不断膨胀,也为了清理redis中冗余的内存空间,需要对aof文件进行rewrite操作.
4.2 redis aof rewrite : redis2.4版本之后,后台定时自动去进行rewrite操作,比如日志里已经存放了针对100w数据的写日志了; redis内存只剩下10万; 基于内存(而不基于之前的aof文件)中当前的10万数据构建一套最新的日志,到AOF中; 覆盖之前的老日志; 确保AOF日志文件不会过大,保持跟redis内存数据量一致.
5 生产环境下的持久化配置:
5.1 根据你自己的应用和业务的数据量,save 60 10000
5.2 AOF一定要打开,fsync,everysec
缓存架构的设计:
在高并发的系统要求下,缓存架构设计必不可少,mysql的高并发,通过分库分表等一系列操作,QPS达到几万的话,算是不错的选择了,但是考虑到电商等系统的并发,那么除了整体架构之外,缓存架构的设计显得尤为重要.(多级缓存架构,热点数据缓存等)
6.1 redis不能支持高并发的瓶颈在哪里?
单机,内存,网络带宽
6.2 redis要支撑超过10万+的并发,how?
单机的redis几乎不太可能说QPS超过10万+,除非一些特殊情况,比如你的机器性能特别好,配置特别高,物理机,维护做的特别好,而且你的整体的操作不是太复杂,单机在几万
–读写分离:
一般来说,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟几千,一两千
主从架构 -> 读写分离 -> 支撑10万+读QPS的架构
redis replication的核心机制:主从架构,数据在主从之间进行同步,复制不仅仅作用于在读写分离方面,同时对于redis的高可用来说,同样意义重大.
7.1 主从复制的操作流程:
(1)redis采用异步方式复制数据到slave节点
(2)一个master node是可以配置多个slave node的
(3)slave node也可以连接其他的slave node
(4)slave node做复制的时候,是不会block master node的正常工作的.
(5)slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了
(6)slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量
8 redis集群–读写分离:
8.1 主从复制中,数据的迁移是单向的,只能从主节点到从节点.master只负责写,slave只负责读.
一个主节点可以存在0或者多个从节点,但是一个从节点只能存在一个主节点.
默认情况下,每一台redis服务器都是主节点,主机不用配置,只需要从机配置主机即可(认定老大)
SLAVEOF host 6379(从机配置主机的地址,端口,命令的方式配置,真实的生产环境配置需要在配置文件中配置,这样才是永久生效的)
8.1.1主从架构的核心原理:
当启动一个slave node的时候,它会发送一个PSYNC命令给master node.
如果这时slave node重新连接master node,那么master node仅仅会复制给slave部分缺少的数据; 否则如果是slave node第一次连接master node,那么会触发一次full resynchronization(全量)
开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。(将rdb文件同步之后,再同步后续的写产生的同步数据)
slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node.
8.1.2 主从复制的断点续传
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份
master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制
但是如果没有找到对应的offset,那么就会执行一次resynchronization
8.1.3 redis主从复制的方式有两种:
(1)磁盘化同步:Redis主进程创建一个编写RDB的新进程放入磁盘文件。稍后,文件由父进程传输进 程以增量的方式传递给从进程
(2)内存RDB: master在内存中生成RDB文件,并且通过socket传输给slave节点,不会经过磁盘
默认是磁盘化传输,如果需要改为内存传输的话,需要修改配置.无磁盘化的方式适用于网络好的情况
8.1.4 从节点过期key的处理: 丛节点不会主动的过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave.
8.2 哨兵模式–架构:
哨兵是redis集群架构中非常重要的一个组件,主要功能如下
(1)集群监控,负责监控redis master和slave进程是否正常工作
(2)消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
(3)故障转移,如果master node挂掉了,会自动转移到slave node上
(4)配置中心,如果故障转移发生了,通知client客户端新的master地址
哨兵本身也是分布式的,作为一个哨兵集群去运行,互相协同工作
哨兵冷知识:
在故障转移之前,如果master挂了,那么不会立即进行故障转移,当其他哨兵节点服务器都去连接master的时候,发现master确实宕机,那么才会进行故障转移,根据配置选举算法,从从机中选中一台机器作为主机.
(1) 哨兵至少需要3个实例,来保证自己的健壮性
(2) 哨兵 + redis主从的部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性
8.2.0: redis哨兵主备切换的数据丢失问题:异步复制、集群脑裂
(1)异步复制导致的数据丢失
因为master -> slave的复制是异步的,所以可能有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了
(2)脑裂导致的数据丢失
脑裂,也就是说,某个master所在机器突然脱离了正常的网络,跟其他slave机器不能连接,但是实际上master还运行着
此时哨兵可能就会认为master宕机了,然后开启选举,将其他slave切换成了master
这个时候,集群里就会有两个master,也就是所谓的脑裂
此时虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还继续写向旧master的数据可能也丢失了
因此旧master再次恢复的时候,会被作为一个slave挂到新的master上去,自己的数据会清空,重新从新的master复制数据
解决方案:
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1个slave,数据复制和同步的延迟不能超过10秒
如果说一旦所有的slave,数据复制和同步的延迟都超过了10秒钟,那么这个时候,master就不会再接收任何请求了
上面两个配置可以减少异步复制和脑裂导致的数据丢失
(1)减少异步复制的数据丢失
有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内
(2)减少脑裂的数据丢失
如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求
这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失
上面的配置就确保了,如果跟任何一个slave丢了连接,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求
因此在脑裂场景下,最多就丢失10秒的数据(通过配置尽量减少脑裂导致的数据丢失)
8.2.1 redis高可用架构: 又称故障转移,failover,也叫做主切换(同上),如果系统在一年的时间内,99.99%时间内都是可用状态,那么就成为高可用.
9 redis缓存穿透与雪崩:
缓存穿透与击穿的区别在于:穿透意味真大面积的缓存失效,那么应用则会跳过缓存去访问数据库,而击穿则是某个人热点key,被大量的访问所请求,导redis服务器宕机.
缓存击穿的解决方案:
缓存穿透解决方案:
在事务队列中的命令s,如果执行过程中,有一条命令报错了,那么则会抛出异常,但是还是会继续执行事务队列中的其他命令,所以redis事务是不能保证一组命令的原子性的.
2 redis实现乐观锁:
原理: 使用watch命令,去监控key,操作key之前,会比较key的值是否改变.假设clientA开启事务,并进行业务操作
multi
Incr balance 1000
Decr account 100
… //假设这个时候,在exec执行之前,clentB对balance进行update
exec
那么clientA对key的操作就会失败.
解决方案: 需要进行unwatch解锁操作,重新使用watch命令加乐观锁.
3 redis实现分布式锁:
set key value nx,必须是这个key此时是不存在的,才能设置成功,如果说key要是存在了,此时设置是失败的
比如说有很多台机器,要竞争一把锁,此时你可以让他们对同一个锁的key,比如lock_key,设置一个value,而且都是要加上nx选项的,此时redis可以通过nx选项,保证说只有一台机器可以设置成功,可以加锁成功,其他机器都是会失败的.