Redis从入门到入土——Redis哨兵机制、集群以及缓存问题

Redis入门第五天:主要介绍了Redis哨兵机制以及Redis Cluster集群和缓存穿透、缓存击穿、缓存雪崩

Redis

系列文章

Redis第一天

Redis第二天

Redis第三天

Redis第四天

Redis第五天

Redis Sentinel哨兵机制

简介

​ Sentinel(哨兵)进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,其已经被集成在redis2.6+的版本中,Redis的哨兵模式到2.8版本之后就稳定了下来。

哨兵进程的作用

  • 集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
  • 消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
  • 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
  • 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。

哨兵进程的工作方式

  • 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器Slave从服务器以及其他Sentinel(哨兵)进程发送一个PING命令
  • 如果一个实例(instance)距离最后一次有效回复PING命令的时间超过down-after-milliseconds选项所指定的值,则这个实例会被Sentinel(哨兵)进程标记为主观下线(SDOWN)。
  • 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器确实进入主观下线状态
  • 当有足够数量的Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN),则Master主服务器会被标记为客观下线(ODOWN)
  • 在一般情况下,每个Sentinel(哨兵)进程会以每10秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送INFO命令。
  • 当Master主服务器被Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的Master主服务器的所有Slave从服务器发送INFO命令的频率会从10秒一次改为每秒一次。
  • 若没有足够数量的Sentinel(哨兵)进程同意Master主服务器下线,Master主服务器的客观下线状态就会被移除。若Master主服务器重新向Sentinel(哨兵)进程发送PING命令返回有效回复,Master主服务器的主观下线状态就会被移除。

实现

修改从机的sentinel.conf
sentinel monitor mymaster  192.168.127.129 6379 1
启动哨兵服务器
redis-sentinel

Redis集群

Redis Sentinal

​ 着眼于高可用性,在master宕机时会自动将slave提升为master,继续提供服务。

​ 哨兵必须用三个实例去保证自己的健壮性的,哨兵加主从并不能保证数据不丢失,但是可以保证集群的高可用性。

Redis Cluster

​ 着眼于扩展性在单个redis内存不足时,使用Cluster进行分片存储。

Redis Cluster集群

redis-cluster框架图

Redis从入门到入土——Redis哨兵机制、集群以及缓存问题_第1张图片

框架细节

  • 所有的redis节点彼此互联(PING-PING机制),内部使用二进制协议优化传输速度和带宽
  • 节点的fail是通过集群中超过半数的几点检测失效时才生效
  • 客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群所有节点。连接集群中任何一个可用节点即可
  • redis-cluster把所有的物理节点映射到【0-16383】slot上,cluster负责维护node<->slot<->value

​ Redis集群中内置了16385个哈希值,当需要在Redis群中放置一个key-value时,redis先对key使用crc16算法算出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16384之间的哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同节点。

redios-cluster投票:容错

  • 集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉。

  • 什么时候整个集群不可用(cluster_state:fail)?

    • 如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态。也可以理解成集群的[0-16384]slot映射不完全时进入fail状态。
    • 如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。

缓存穿透、缓存击穿、缓存雪崩

缓存数据步骤

  • 查询缓存,如果没有数据,则查询数据库
  • 查询数据库,如果数据不为空,就将结果写入缓存

缓存穿透

介绍

​ 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查询。如果key对应的value是一定不存在的,并且对key并发请求量很大,就会对后端系统造成很大的压力,这就叫做缓存穿透。

解决
  • 对于查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对象的数据insert了以后再清楚缓存
  • 布隆过滤器(Bloom Filter):利用高效的数据结构和算法快速判断出这个key是否在数据库中存在,不存在就直接return,存在就去查了DB刷新KV再去return
  • 在接口层进行校验,比如用户鉴权校验、参数做校验

缓存雪崩

介绍(很多key)

​ 当缓存服务器重启或者大量缓存集中中某一时间段失效,这样在失效的时候,也会给后端系统带来很大的压力

解决
  • 缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待
  • 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
  • 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
  • 如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也可以避免全部失效的问题
  • 或者设置热点数据永不过期,有更新操作就更新缓存,电商首页的数据也可以用这个来操作。

缓存击穿

介绍(一个key)

​ 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,这个时候就需要缓存被击穿的问题。

​ 缓存在某个时间点过期的时候,恰在这个时间点对这个key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会把后端DB压垮

解决
  • 设置热点数据永不过期
  • 使用redis的setnx互斥锁先进行判断,这样其他线程就处于等待状态,保证不会有大并发操作去操作数据库
public static String getDate(String key) throws InterruptedException{
    //从redis查询数据
    String result = getDataByKV(key);
    //校验参数
    if(StringUtils.isBlank(result)){
        //获取锁
        if(reenLock.tryLock()){
            //去数据库查询
            result = getDataByDB(key);
            //校验
            if(StringUtils.isNotBlank(result)){
                //搞进缓存
                setDataToKV(key,result);
            }
            //释放锁 正常会在finally里面释放
            reenLock.unLock();
        }else{
            //睡一会再拿
            Thread.sleep(100L);
            result = getData(key);
        }
    }
    return result
}

避免以上情况

  • 事前:Redis高可用性,主从加哨兵,Redis cluster、避免全面崩溃
  • 事中:本地ahcache缓存+Hystrix限流+降级,避免MySql被打死
  • 事后:Redis持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速回复缓存数据。
  • 限流组件:设置每秒的请求,有多少能通过组件,剩余的未通过的请求,走降级,返回一些默认值(友好提示或者空白值)

最后

  • 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
  • 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
  • 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。

image

你可能感兴趣的:(Redis,redis)