redis

139 阅读5分钟

redis主从复制原理

  1. Slave启动成功连接到master后会发送一个sync命令
  2. Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步
  3. 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
  4. 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
  5. 但是只要是重新连接master一次完全同步/全量复制将被自动执行

哨兵模式选举原理

  1. 选择优先级靠前的,优先级在redis.conf中默认:slave-priority 100,值越小优先级越高。
  2. 选择偏移量最大的,即获得原主机数据最全的。
  3. 选择runid最小的从服务。每个redis实例启动后都会随机生成一个40位的runnid
  4. 挑选出新的主服务之后,sentinel向原主服务的从服务发送slaveof新主服务的命令,复制新master。
  5. 老的主服务重新上线时,sentinel会向其发送slaveof命令,让其成为新主服务的从机。

集群

redis集群实现对redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数的1/N

redis集权通过分区来提供一定程度的可用性,即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。

如果所有某一段插槽的主节点都宕掉了,redis服务是否能继续?

如果某一段插槽的主从都挂掉,而cluster-require-full-coverage位yes,那么整个集群都挂掉。如果为no,那么该插槽全部不能使用,也无法存储。其他插槽能继续提供服务。

redis问题

缓存穿透

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压倒数据源,从而可能压垮数据源。比如用户一个不存在的用户id获取用户信息,不论缓存还是数据库都没有。

出现原因

  1. redis查询不到数据
  2. 出现很多非正常url访问

解决方案

  1. 对空值缓存,如果一个查询返回的数据为空(不管是数据是否不存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。
  2. 设置可访问的名单(白名单):使用bitmaps类型定义一个可以访问的名单,名单id做bitmaps的偏移量,每次访问何bitmap里面的id进行比较,如果访问id不存在bitmaps里面,进行拦截,不允许访问。
  3. 采用布隆过滤器:布隆过滤器是1970年由布隆提出的,它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。布隆过滤器可以用于检索一个元素是否在一个集合中,它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识率和删除困难,将所有可能存在的数据哈希到一个足够大的bitmaps中,一个一定不存在的数据会被这个bitmaps拦截掉,从而避免了对底层存储系统的查询压力。
  4. 进行实时监控:当发现redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。

缓存击穿

key对应的数据存在,但在redis中某一个key过期,此时若有大量并发请求过来,这些请求发现缓存过期,一般会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

解决方案

  1. 预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里,加大这些热门数据key的时长
  2. 实时调整:线程监控那些数据热门,实时调整key的过期时长
  3. 使用锁:

1.就是在缓存失效的时候(判断拿出来的值为空),不是立即去load DB。

2.先使用缓存工具的某些带成功操作返回值的操作去set一个mutex key

3.当操作返回成功时,在进行load DB 的操作,并回设缓存,最后删除mutex key

4.当操作返回失败,证明有线程在load DB,当前线程睡眠一段时间再重试整个get缓存的方法。

image.png

雪崩

key对应的数据存在,但在redis中大批量过期,此时若有大量并发请求发过来,这些请求发现缓存过期,一般会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮

解决方案

构建多级缓存架构:nginx缓存+redis缓存+其他缓存 使用锁或对列:用加锁或者对列的方式保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上,不适合高并发情况。