Redis高级
主从复制
好处:
1.读写分离
2.容灾快速恢复
主从配置
主服务器负责写操作,从服务器只能读
从服务器挂掉
从服务器重启后,仍是主服务器,需要执行 salverof 主机ip 端口 变为从服务器
从服务器会将主服务器的数据从头开始复制
主服务器挂掉
从服务器不做任何事情,主服务器重启后还是主服务器
原理:
1.当从连接上主服务器之后,从服务器向主服务发送进行数据同步消息
2.主服务器接到从服务器发送过来同步消息,把主服务器数据进行持久化生成rdb文件,把rdb文件发送从服务器,从服务器拿到rdb进行读取
3.每次主服务器进行写操作之后,和从服务器进行数据同步
哨兵模式
主服务器挂掉后,挑选从服务器的优先级规则
1.redis.conf : replica-priority 100(默认) 数值越小,优先级越高
2.偏移量(和原主机的同步值)越大,优先级越高
3.选择runid最小的从服务器
当原来的主服务器重启后,它变为新的主服务器的从服务器
集群
解决问题:redis容量不够,并发写操作
无中心化集群
Redis集群实现了对Redis的水平扩展,启动N个redis结点,将整个数据库分布存储在N个结点中,
每个结点存储总数据的1/N
Redis集群通过分区来提供一定程度的可用性:即使集群中有一部分结点失效或者无法通信,集群也可以继续处理命令请求
一个集群至少要有三个主节点
选项--cluster-replicas 1表示我们希望为集群中的每个主节点创建一个从节点
分配原则尽量保证每个主数据库运行在不同的P地址,每个从库和主库不在一个P地址上
通过哈希函数,把每个key,哈希到插槽中,插槽不在主服务器的范围内,就会切换到相应的主服务器
在redis-cli每次录入、查询键值,redis都会计算出该key应该送往的插槽,如果不是该客户端对应服务器的插槽,redis 会报错,并告知应前往的redis实例地址和端口
在集群中加入多个值,定义组
mset name{user} LHY age{user} 20
故障恢复
某一段插槽的主从都挂掉:
1.cluster-require-full-coverage为yes,那么,整个集群都挂掉
2.cluster-require-full-coverage为no,那么,该插槽数据全都不能使用,也无法存储
缓存
缓存穿透
原因:redis查询不到数据,出现很多非正常的url访问,需要一直访问数据库,应用服务器压力增大,最后崩溃
解决方案:
1).对空值缓存,设置空结果的过期时间很短
2).设置可访问的白名单(位图)
使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和 bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。
3).采用布隆过滤器
4).进行实时监控,当redis的命中率急剧降低,需要排查访问对象和访问数据
缓存击穿
现象
1.数据库访问压力瞬时增加
2.redis里面没有出现大量key过期
3.redis正常运行
原因:redis某个key过期了,大量访问使用这个key
1.预先设置热门数据,把一些热门数据提前存入到redis,加大热门数据key的时常
2.实时调整,现场监控热门数据,实时调整key的过期时长
3.使用锁
缓存雪崩
现象:数据库压力变大,服务器崩溃
原因:在极少时间段,查询大量key的集中过期情况
解决:
1.构建多级缓存架构:nginx缓存 + redis缓存 + 其他缓存
2.使用锁或者队列
3.设置过期标志更新缓存
4.将缓存失效时间分散开
分布式锁
setnx 设置锁
del 释放锁
expire 设置锁的过期时间
为了避免在上锁之后,服务器异常,无法设置过期时间,导致锁无法释放
解决:在上锁的同时就设置过期时间 set user 1 nx ex 3
优化:防止误删,设置uuid,相同则删除
set key uuid nx ex 5
lua保正删除的原子性
分布式锁使用条件
1.互斥性。在任意时刻,只有一个客户端能持有锁
2.不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
3.解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了
4.加锁和解锁必须具有原子性