Redis各种点杂记

Redis各种点杂记

整理不易,转载请注明: https://blog.csdn.net/zhangjingao/article/details/117601983

一致性哈希算法

一致性哈希算法将空间分为一个环形空间,在环形空间里,每台机器结点被分布在环上不同的点,当key值被计算到某个点后,会顺时针寻找一个结点,数据会被保存在那里。当一个机器宕机了或者新添加了一个机器,也只会影响就近的一部分key,不会影响后面所有的key,这样尽可能的减少了删除或者新增机器对结点rehash带来的影响。这个特点解决了单调性和负载均衡的特性。

  如果节点少,那么就存在两个问题:
    1、存在数据倾斜问题。将节点hash后放在环上,如果hash的结果不够均匀,那么就会存在数据倾斜问题。比如:有两个节点,hash后的值分别是
    2、存在缓存雪崩问题,如果节点中有一个节点被删除了,那么会有大量的key失效,那么就会有雪崩的问题。

  为了解决上面的问题,一致性哈希算法引入了虚拟节点的概念,将一个真实的节点分为很多个虚拟节点,将虚拟节点放在环上,那么在新增或删除节点时,受影响的点会大幅降低。
  如下图:v100和v101都是节点1的虚拟节点,v200和v201是节点2的虚拟节点,v300和v301是节点3的虚拟节点。此时如果删除节点1,那么相应的v100和v101就会消失,那么受影响的数据只有k1映射到v301上,k4映射到v200上。
在这里插入图片描述

一致性哈希算法给每个机器结点虚拟出来了很多个虚拟结点,均匀的分布在环上,这样解决了平衡性,不会导致某个结点缓存过多key,而某些结点缓存过少key这样不平衡的情况。

注意:真实的节点并不会放在哈希环上,只放虚拟节点。

哈希槽算法(当前使用的)

  当前redis集群使用的算法是哈希槽算法,并不是一致性哈希算法。
  哈希槽算法不在是一个环,是一个线性区间。一共有16384(2^14=281024)个槽位,在集群创建时,每个master节点负责哪些槽就已经分配好了,在之后新增和删除节点时,做的只是槽位的迁移。
  放一张经典的key、槽、节点、集群的关系图。
在这里插入图片描述
  维护槽和节点关系的是一个数组结构,key是槽下标,value是节点对象。这样就可以很快根据槽找到对应的处理的节点。

性能优化

压测命令:./redis-benchmark -h 127.0.0.1,我的电脑上get和set100000条数据使用了133s

redis内存有限,跟电脑有关,64G或者128G

内存有限,可使用分库分表来增加内存,对不同的key取模进行分服务器存储

读多写少的情况下,使用读写分离来实现速度的优化

RESP协议

Redis的java客户端jedis与redis进行通信的通信协议。基于TCP应用层协议。

缓存穿透

原因:客户端多次查询一个不存在的key,导致每次都在缓存中查询不到,从而每次都到达数据库中查询。
解决方案
缓存空key

redis缓存这个不存在的key,值设置为null,当在数据库中查询不到的时候,redis一样缓存这个不存在的key,设置过期时间。

使用BloomFilter。

BloomFilter是一个可以判断这个key是否存在的组件,可以加载缓存之前,如果在bloomfilter中判断key不存在,直接返回null,如果存在就查缓存再查db。

两种方案对比

当客户端可能经常使用重复率高的不存在的key查询,我们可以使用第一种方案,

当客户端使用的不存在的key重复率低,那么使用第二种方案。

缓存击穿

原因:当多个线程同时请求一个key,但是这时key恰好失效了,这就导致一瞬间很多个请求同时请求数据库,数据库压力剧增。
解决方案

当有多个线程请求数据库时,就用互斥锁锁住请求,当第一个线程请求到了数据,那么可以将数据存进缓存,那么其他线程就可以直接使用缓存了。

缓存雪崩

原因:指某一时刻大量数据同时失效,例如当缓存服务突然宕机了,那么所有的请求都会直接请求到数据库,数据库可能承受不住。
解决方案
事前

使用集群缓存,保证缓存服务的高可用,在redis中,可以使用主从+哨兵,redis cluster来避免redis全盘崩盘的情况。

事中

ehcache本地缓存 + Hystrix限流&降级,避免MySQL被打死

事后

开启redis持久化机制,恢复内存中的数据。

热点数据失效

原因:我们在设置缓存时,经常会设置过期时间,当多个热点数据同时过期时,可能会出现很多个请求同时到达数据库,导致数据库压力增加。
解决方案
设置不同的失效时间

给不同的热点数据设置不同的失效时间,失效时间可以是某一个确定的时间+一个不确定的在一个小范围内波动的随机值。

互斥锁

和缓存击穿的方案类似,给请求的线程加锁,当第一个线程在数据库中请求到数据库,请求相同数据的线程就不会再到数据库中,但这样的方案会降低系统吞吐量。结合情况使用。

持久化

持久化有两种方式:RDB和AOF

RDB

原理:redis调用fork线程,子线程会把数据更改写到rdb文件中,覆盖旧文件,是一种快照形式的持久化方式

优点

1、rdb会配置时间点,在达到时间点时更改量到达要求的数据时就会开始持久化,比如save 60 100,在60s内更改量达到了100就进行备份,可以有多个时间点配置

2、采用子线程备份,不用影响主线程的继续服务

3、在数据量大的情况下,RDB相比AOF更快能启动

缺点

1、设置的时间点过长,可能导致redis宕机等时候在上次时间点至宕机时候数据未恢复

AOF

原理:比较可靠,当redis数据被修改时,就会把命令添加到aof文件中,当redis重启时,就会把aof文件重新执行一遍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值