关于Redis的介绍和特点,这里就不细说了,不然要千言万语。今天我们就来重点介绍一下在企业中使用Redis时的一些常见问题以及相应的解决方法。当一个请求到达业务系统,想要获取某个数据时,通常是先从缓存中获取。如果缓存中不存在,则到数据库中查询。如果找到结果,则将数据保存在缓存中,并返回结果。一项新技术的引入必然会带来一些额外的问题,那么像Redis这样优秀的NoSQL数据库又会带来什么样的问题呢?让我们等着看。CachebreakdownCachebreakdown看名字看不懂什么意思,很容易和另一个词——缓存穿透混淆。缓存击穿意味着某个键一直承载着高并发。所谓高并发就是大量的请求都是为了获取这个key对应的值。而这个key在某个时候突然过期,是不是意味着大量的请求获取不到缓存中的数据,而是去请求数据库,很可能导致数据库被压垮。这是缓存故障。既然知道了问题,该如何处理呢?这个比较简单。由于密钥是流行的,所以不要设置过期时间。如果key的数据有更新,通过mutex更新。为什么要使用互斥量?如果不使用互斥锁,很容易导致数据不一致。这里,为了保证缓存和数据库的一致性,只能牺牲一点点效率。CacheAvalanche不知道各位小伙伴是哪里来的。我们有一种方言叫做“Avalanche”,意思是事情已经崩溃了。这里的RedisAvalanche好像也是这个效果。首先我们要知道什么是Redis雪崩。Redis雪崩一般称为缓存雪崩,是指在某个时间节点,大量的key失效,导致大量的请求因为无法从缓存中获取数据而请求数据库。根据上图,我们来画一下雪崩的情况是怎样的:上面黑色的部分表示缓存失效,也就是说所有的请求都需要去数据库查询数据。那么数据库的压力必然会急剧增加。如果是在一线互联网这样的超高并发场景下,数据库会直接宕机。重启也没用,因为重启之后,就会有一个巨大的流量涌入,然后会一直关机。因此,防止缓存雪崩的发生具有重要意义。缓存雪崩加随机值的解决方案前面已经详细介绍了什么是缓存雪崩以及它是如何发生的。如何防止缓存雪崩?很简单,因为上面说了缓存雪崩是某个时间节点大量key失效导致的,所以现在的问题就是如何防止同一时间节点大量key失效的情况发生。?最简单的情况就是分散key的过期时间,也就是在设置key的过期时间的时候加上一个随机值,这样就可以完美解决缓存雪崩的问题。但你认为我在这里完成了吗?既然是综合安排,我不会只告诉你一个解决方案就完事了。继续看缓存雪崩解决方案的锁。很多人看到这个解决方案可能会说他们不接受。加锁不限制并发吗?加锁必然导致阻塞。如果是加锁,那么执行是这样的:流程是这样的,当多个请求同时到达业务系统时,只有一个线程可以获取到锁,然后继续在数据库中缓存或者查询数据,然后后面的过程和之前一样。执行完成后释放锁,然后其他线程竞争锁,然后重复前面的过程。这种方案的优点是可以很好的保护数据库不被挂掉,缺点是并发度极低。其实上面的方案还是可以优化的:这个是如果在缓存中拿不到,那就去串行访问数据看看,这里不一定要串行,可以配合线程池控制一定的并发数。虽然弊端很多,但也不失为一种解决方法。是否使用取决于实际业务场景。毕竟没有无用的技术方案,只有不适合业务场景的技术方案(手动狗头)。缓存穿透缓存穿透就是访问了一个不存在的key,结果发现数据库中没有这个数据,最终所有访问key的请求都是直接向数据库请求的。如果是高并发的场景,很容易把数据库搞垮。您是否注意到我们所做的一些事情是保护“弱数据库”。既然知道了问题,那么如何解决这个问题呢?缓存空数据缓存穿透解决方案什么是缓存空数据?就是假设某条关键数据不存在,那么就存一个NULL,但是不要忘记设置过期时间,因为假设id=3的记录不存在,那么本次访问不查询data,缓存中存储的为null。如果过段时间新增了一条3条数据的记录,如果缓存没有设置过期时间,那么这条数据是永远获取不到的。缓存穿透方案Bloomfilter之Bloomfilter?这东西是什么意思?Bloomfilter是一种数据结构,更准确地说是一种概率数据结构,因为它可以确定一个元素是否一定不存在或可能存在。这句话忽悠了很多人,今天硬要给大家解释一下。布隆过滤器是一个位数组,一个很长的位数组和一系列哈希函数。让我们看看下面的图片,现在让我们举个例子。假设有两个人,小强和旺财,他们经过3次hash后得到的下标分别是这样的(Bloomfilter不存储元素,它只检查一个元素是否存在做一个标志)小强经过hash后得到的下标上面三个hash分别是:2、4、5,那么数组的2、4、5位置都会被置为1,就是这个时候的样子同理,通过上面三个hash后,得到的下标byWangCaijing分别是:3、7、11,那么数组的3、7、11位置都会被设置为1,也就是目前假设是这样的来个007,得到上面之后的下标三个hash分别是:11、13、15。因为13和15的位置都是0,所以可以判断007一定不存在。但是现在又多了一个9527,上面三个hash后得到的下标分别是:2,5,7,但是你会发现257的三个位置都是1,那么这到底是说9527存在还是不存在呢??从我们上面的解释可以看出9527之前是不存在的,但是由于hash冲突,9527的三个下标值也刚好落在已经设置为1的下标位置,导致无法判断此时9527是否存在的。这就是布隆过滤器的原理。一段让你震惊的代码怎么样?下面我们使用google包下的类来测试一下。首先需要添加依赖
