文章目录
Redis常见问题
redis通常是被做为缓存来使用的,既然做为缓存来使用,就可能会出现缓存雪崩,缓存击穿,缓存穿透,数据一致性等问题。
1. 缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机,终究还是数据库发生的问题。
这个在我们编码的时候就应该考虑到。
解决方案:
- 针对缓存区设置随机过期时间,可以范围性的随机。比如说 ,当前缓存过期时间24小时,我们可以在23到24小时设置个随机值。防止同时时间大量数据过期现象发生。
- 根据业务来设置过期时间,尽量不要在业务最大情况并发情况让数据过期。比如说抢购,是在一个点发生的,这个点的时候,不要让大量的数据过期。
2. 缓存穿透
缓存击穿是指缓存在数据库中都没有数据,而用户不断发送请求,由于缓存是不命中时被动写的,并且处于容错考虑,正常从存储层差不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
在流量大,可能DB就挂掉了,或者说有人估计攻击系统。
解决办法:
- 接口层增加校验,针对查询的值,数据库中大概率是有一个范围的,比如ID,ID基本上是不会小于0的,这样我们在接口层就可以拦截了。
- 从缓存取不到数据,在数据库中也没有找到,这时可以将key-value 写成key-null 。缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没办使用)。这样就可以防止攻击用户反复用一个id暴力攻击。
3. 缓存击穿
缓存击穿指的是,某一个数据在某一时刻失效(一般是过期时间到了),这时由于并发用户特别多,同时读取缓存没读取到数据,又同时去数据库取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案:
- 布隆过滤器。bloomFilter类似于一个hash set,用于快速判断某个元素是否在于集合中,其典型的应用场景就是快速判断一个key是否在于某个容器中。不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小。
- 针对redis数据的过期时间进行优化
- 接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可以用的时候,进行熔断,失败快速返回机制。
- 给查询接口加一个分布式互斥锁。保护数据库。
4. 缓存一致性问题
如何去保证mysql的数据和redis的数据保证一致性?
4.1 先删除缓存,再操作数据库,等下次再来查询的时候,写入到缓存中。
当更改操作来的时候,先去删除缓存,再去更新数据库,等下次再来查询的时候,再写入缓存。
当然存在缓存被删除了,数据库的信息还没有更改完成,数据会出现问题。
解决方案:
- 如果都是单机系统,针对数据库操作加一个读写锁。
- 如果是分布式缓存,针对数据库的操作加一个分布式锁。
4.2 先更新数据库再删除缓存,等下次再来查询的时候,写入到缓存中。
当更改操作来的时候,先去更新数据库,再去更新缓存。
存在数据更新完,但是还没来得及刷新缓存,数据依然会出现问题。
解决方案:
- 单机系统, 通过CAS 算法,针对查询的操作加一个标识,如果查询过程中发现标识是有人修改数据库了,就直接去数据库中查询。等修改数据库的改完并且回写到缓存中,再次对标识符进行修改。
- 分布式缓存,在redis中设置一个表示符号,同以上的操作。
4.3 基于阿里巴巴的开源canal框架,实现redis数据一致性。
后续进行研究。
5. 布隆过滤器(Bloom filter)
Bloom filter 是一种空间效率很高的随机数据结构,它利用位数组很简洁的表示了一个集合,并能判断一个元素是否属于这个集合。判断的时候会有误差。
- 空间效率高的概率型数据结构,用来检查一个元素是否在一个集合中。
- 对于一个元素检测是否存在的调用,BloomFilter会告诉调用者两个结果之一:可能存在或者一定不存在。
原理分析:
初始状态下,布隆过滤器是一个包含M为的位数组,每一位置为0。
插入数据:
当我们需要把数据插入到布隆过滤器中的时候,会通过多个hash算法,进行计算。每一个hash算法都会计算出一个hash值,然后将数据中索引对应的下标的值改为1。
检查数据:
- 如果数据不都为1,说明数据一定不存在。
- 如果数据全部为1,说明数据可能存在,因为采用hash算法,此数据对应的位置可能被其他字符串所记录过。
Delete操作:
字符串加入了就被不能删除了,因为删除会影响到其他字符串。实在需要删除字符串的可以使用Counting bloomFilter(CBF),这是一种基本Bloom Filter的变体,CBF将基本bloom Filter 每一个Bit 改为一个计数器,这样就可实现删除字符串的功能了。
可以使用guava的内置好的组件。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>