前言
当今互联网世界中,高并发一直是各大网站、应用面临的一大挑战。为了应对高并发的流量压力,各种技术手段被不断研究和应用。其中,Redis 作为一款高性能的内存数据库,被广泛应用于解决高并发问题。
与传统的关系型数据库不同,Redis 采用了内存存储的方式,可以实现快速的读写操作。同时,Redis 还具有丰富的数据结构和强大的缓存功能,可以大大提升系统的性能和可靠性。在处理高并发问题方面,Redis 也提供了诸如分布式锁、限流、队列等常用的解决方案,可以帮助开发者轻松应对高并发场景。
本篇文章将介绍 Redis 在处理高并发问题方面的应用,包括缓存穿透、缓存击穿和缓存雪崩问题等,并针对这些问题给出实际的解决方案(附代码),持续更新。希望本文能够对大家在解决高并发问题时提供帮助和启示。
缓存穿透
缓存穿透是指用户查询数据时,数据库和缓存中都没有数据。导致了查询请求直接绕过缓存,直接穿透到数据库。
解决方法:
缓存空值
查询Redis为null,查询数据库也为null,此时设置该key在缓存中,且值为null,过期时间为随机时间。random(10)。这样子能保证数据在这段时间暴力请求,也只会在这短暂的时间内获取null,而有另外的线程在读取数据库表,并缓存在Redis中
/**
* 解决缓存穿透
* @return
*/
public User getUser(String userId) {
//从缓存中获取user信息
User user = (User) redisTemplate.opsForValue().get(userId);
if(user == null) {
//如果缓存数据为空,从数据库中获取user信息
user = userService.getUserByUserId(userId);
if(user == null) {
//如果数据库中数据为空,则存入一个空值,设置短时间内过期,防止缓存穿透
redisTemplate.opsForValue().set(userId,null,5, TimeUnit.MINUTES);
}else {
//将数据写入缓存
redisTemplate.opsForValue().set(userId,user);
}
}
return user;
}
布隆过滤器
可参考:www.cnblogs.com/throwable/p…
布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
优点:
- 空间效率高,不用像Set集合一样保存元素的值,极大地节省了内存空间。只需将插入的key通过Hash计算放到bitMap中的一个位置,在判断是否存在该key的时候,只需判断bitMap中的位置是0还是1即可,达到了Set集合判断是否存在某值的效果。
- 查询效率高:布隆过滤器可以在非常快的时间内判断一个元素是否存在于集合中,而不需要像传统数据结构那样进行线性扫描。这对于大规模数据集和高并发查询场景尤其有用。
缺点:
- 布隆过滤器中的存储的key越多,误判率越高。将不存在的元素误判为存在。
- 不能删除布隆过滤器中已存在的key
具体使用:使用Guava中的API
导入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
构造BloomFilter的最多参数的静态工厂方法是BloomFilter create(Funnel funnel, long expectedInsertions, double fpp, BloomFilter.Strategy strategy),参数如下:
- funnel:主要是把任意类型的数据转化成HashCode,是一个顶层接口,有大量内置实现,见Funnels
- expectedInsertions:期望插入的元素个数
- fpp:猜测是False Positive Percent,误判率,小数而非百分数,默认值0.03
- strategy:映射策略,目前只有MURMUR128_MITZ_32和MURMUR128_MITZ_64(默认策略)
@RestControlle