一、缓存雪崩
当缓存服务器处于单点情况下,一旦缓存服务器崩溃,所有的请求就全部落到数据库层,此时,如果由于访问量过大则会导致数据库宕机,进而导致整个网站或服务不可用,这种缓存的故障就是缓存雪崩。
解决方案:提高缓存服务高可用性,建立分布式的高可用缓存系统,一台服务器如果宕机,另外一台继续工作,从而分担了数据库的压力。
二、缓存冲突
如果某一个key对应的数据不存在,而又未对该key做缓存,所以每次请求都会穿过缓存直接到数据库进行查询,并发量高的情况下进而导致数据库直接宕机。
解决方案:把null值或者空列等也缓存起来,如果存在恶意攻击一个不存在的key,在控制层做频率限制是必须的
三、缓存预热
新的缓存系统没有任何的缓存数据,在缓存重建数据的过程中,系统性能和数据库负载 都不太好,需要在系统上线之前就要把缓存的数据先加载到缓存中
四、过期策略
1、expire key ttl 定时器,主动淘汰,消耗cpu资源
2、惰性过期,等key下次请求的时候判断是否淘汰,被动淘汰,不过占用大量的内存
3、定期过期
淘汰策略:
1、volatile-lru:对于设置ttl的key,淘汰最近最少使用的key
2、allkeys-lru:对于所有的key,淘汰最近最少使用的key
3、volatile-lfu:对于设置ttl的key,淘汰使用频率最少的
4、allkeys-lfu:对于所有的key,淘汰使用频率最少的
5、volatile-random:对于ttl的key,随机删除
6、allkeys-random:随机删除
7、volatile-ttl:
8、noeviction:不做处理,导致只能读,不能写拉
五、持久化机制
1、rdb(redis database)
生成一个dump.rdb快照文件,配置文件里面一个save 会触发生成快照文件,shutdown或者flushall都会触发
手动触发生成rdb,执行save命令,会进入阻塞状态
bgsave后台执行,fork一个子进程,进行持久化操作
优点:
1、只有一个文件dump.rdb,方便持久化
2、容灾性号,一个文件可以保存到安全的磁盘上
3、性能最大化,fork子进程来完成写操作,让主进程继续处理命令,保证了redis的高性能
4、如果数据集偏大,rdb的启动效率比AOF高
缺点:
1、数据安全性低,rdb是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失
2、由于rdb是通过fork子进程来协助完成数据持久化工作的,因此,如果如果当数据集较大时,可能会导致整个服务停止几百毫秒
2、aof (append only file):以日志的形式记录服务器处理的每一个操作,查询操作不会记录,弥补rdb数据不一致性
优点:
1、数据安全性高,aof持久化可以配置appendfsync属性,其中always,每进行一次命令就记录到aof文件中
2、通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof解决数据一致性
3、aof机制的rewrite模式,可以删除其中的某些命令,比如flushall
缺点:
1、aof文件比rdb文件大,恢复速度慢,数据集大的时候,比rdb启动效率低
2、根据同步策略的不同,aof在运行效率上往往会慢于rdb
六、pipeline
当set10000条数据,发现会很慢
客户端到服务端来回通信的时间,假设一次来回20ms,10000条数据就是10000*20ms
七、redis分布式
为什么需要部署redis集群?
1、性能
2、扩展
3、可用性,安全
主从节点设置(三种方式)主节点允许读写,从节点只允许读
1、从节点客户端执行:slaveof 主节点ip 主节点端口号
2、在从节点启动的时候,直接加上命令:redis-server --slaveof 主节点ip 主节点端口号
3、在从节点redis.conf配置文件中配置:replicatiof 主节点ip 主节点端口号
查看主从节点信息:info replication
断开主从设置关系:从节点上执行slaveof no one
主从数据同步-主从复制原理:
全量复制
定时器会定时扫描该节点是否是其他节点的字节点,如果是,会直接建立socket,与master通信
master节点会生成一个rdb文件,然后将rdb文件发送给slave从节点
新接受到的命令先存储到缓冲区中,然后再发送到从节点中
增量复制
缺点:
一旦主节点挂掉的话,只能手动切换
如何实现自动切换主从节点?
sentinel哨兵模式
功能:
1、监控所有的master,slaver节点
2、通知其他节点发起投票
3、自动故障转移
4、配置管理
节点有三种状态:follower,candidate,leader
节点有俩个超时时间:第一个超时时间,当节点没有接受到redis服务器信息,会超时,当率先超时,会转成candidate候选人节点。然后会发送信息给其他节点,谁同意谁返回他当leader节点,如果投票通过,则当选为leader节点
第二个超时时间:是该leader节点定时发送心跳给其他节点,表示我还活着,如果其他节点接受到信息,会把超时时间置空,不断的重新来过,防止其他节点继续参与投票
在第一个时间中,如果俩个节点同时成为了候选人的时候,第一次投票失败,继续观察超时时间,谁先到达,谁先率先发起投票
sential:发送俩条指令
slaveof no one
slaveof ip 端口号
上述虽然可以实现了自动的主从切换,但在切换的过程中可能会导致数据丢失,因为只有一个master.水平扩容的问题没解决,需要多个master进行写操作:数据分布到多个master的话,写和读会遇到一些问题
1、基于客户端的方案,采用分片的逻辑,同逻辑进行读写操作
2、基于redis服务本身实现分片(shard,proxy[Twemproxy,Codis])
八、redis集群搭建
1、原生redis集群的基本搭建过程
我是在192.168.131.166服务器上搭了六个redis实例
这六个文件夹分别是对应的节点的redis.conf文件,端口号分别位7000,7001,7002,7003,7004,7005
具体修改的位置:
a、配置完毕之后,分别启动这六个节点:
查看启动状态:ps -ef | grep redis
此时这六个节点依旧是单节点,客户端执行命令会出现错误,显示必须要先分派槽位
b、meet操作,将节点合并成一个集群
cluster meet ip port
c、指派槽位
查看crc16算法算出key的槽位命令:cluster keyslot key
d、分配主从:cluster replicate node_id
命令:redis-cli --cluster create 192.168.131.166:7000 192.168.131.166:7001 192.168.131.166:7002 192.168.131.166:7003 192.168.131.166:7004 192.168.131.166:7005 --cluster-replicas 1
以上命令直接实现了a,b,c三个步骤:设置所有的ip,端口号建立了通信完成a步骤,cluster-replicas设置了需要分配从机的比例完成d步骤,得到三个主机,然后默认均分槽位,总槽位16384
连接到客户端命令:redis-cli -h 192.168.131.166 -p 7000 -c
-c是redis-cli固有的,算出的槽位能够重定向到对应槽位的服务器上,如果不-c的话,算出的槽位如果不在该客户端对应服务器的槽位段之间,会报错
cluster nodes:查看集群的消息
集群扩容,缩容
扩容:先把需要扩容的redis实例启动起来
添加主节点:redis-cli --cluster add-node 新添加redis实例(ip:端口号) 集群里面任意一个实例(ip:端口号)
默认添加到集群成为主节点
添加从节点:redis-cli --cluster add-node 新添加redis实例(ip:端口号) 集群里面任意一个实例(ip:端口号) --cluster-slave --cluster-master-id 实例id
查看一下:已经成功添加到集群
但是新添加的实例,槽位是没有,这样显然是不行,纯粹浪费资源,所以我们需要重新分配槽位
redis-cli --cluster reshard ip:端口号
500是分配槽位的数量,自己输入
查看一下
以上集群扩容工作完毕!