什么是缓存击穿
我们通常使用redis作为数据缓存,当请求进来时先通过key去redis缓存查询,如果缓存中数据不存在,需要去查询数据库的数据。当数据库和缓存中都不存在的数据来查询时候,请求都打在数据库的请求中。如果这种请求量很大,会给数据库造成更大的压力进而影响系统的性能。
解决这类问题的方法
方法一:当DB和redis中都不存在
key
,在DB返回null
时,在redis中插入当
key
再次请求时,redis直接返回null
,而不用再次请求DB。
方法二:使用redis提供的
redisbloom
,同样是将存在的key放入到过滤器中。当请求进来时,先去过滤器中校验是否存在,如果不存在直接返回null
。
官方文档上面提供docker安装redisbloom和下载编译的方式引入redisbloom的模块。
下面介绍一下编译的方式来引入redisbloom模块
git clone https://github.com/RedisLabsModules/redisbloom.git
cd redisbloom
make # 编译redisbloom
启动redis-server时引入redisbloom模块
./redis-5.0.4/src/redis-server --loadmodule ./redisbloom/rebloom.so
在redis.conf中配置
loadmodule ../redisbloom/rebloom.so
bf.reserve {key} {error_rate} {size}
127.0.0.1:6379> bf.reserve userid 0.01 100000
OK
{error_rate}
过滤器的错误率在0-1之间,如果要设置0.1%,则应该是0.001。该数值越接近0,内存消耗越大,对cpu利用率越高。bf.add {key} {item}
bf.madd {key} {item} [item…]
127.0.0.1:6379> bf.add userid '101310299'
(integer) 1
127.0.0.1:6379> bf.madd userid '101310299' '101310366' '101310211'
1) (integer) 0
2) (integer) 1
3) (integer) 1
bf.exists {key} {item}
bf.mexists {key} {item} [item…]
127.0.0.1:6379> bf.exists userid '101310299'
(integer) 1
127.0.0.1:6379> bf.mexists userid '101310299' '10saa' '101310211'
1) (integer) 1
2) (integer) 0
3) (integer) 1
java程序员可以通过RedisBloom类库提供的API实现高性能布隆过滤器
com.redislabs
jrebloom
1.0.1
redis.clients
jedis
3.0.0
public class RedisBloomDemo {
public static void main(String[] args) {
String userIdBloomKey = "userid";
// 创建客户端,jedis实例
Client client = new Client("localhost", 6378);
// 创建一个有初始值和出错率的过滤器
client.createFilter(userIdBloomKey,100000,0.01);
// 新增一个
boolean userid1 = client.add(userIdBloomKey,"101310222");
System.out.println("userid1 add " + userid1);
// 批量新增values
boolean[] booleans = client.addMulti(userIdBloomKey, "101310111", "101310222", "101310222");
System.out.println("add multi result " + booleans);
// 某个value是否存在
boolean exists = client.exists(userIdBloomKey, "101310111");
System.out.println("101310111 是否存在" + exists);
//某批value是否存在
boolean existsBoolean[] = client.existsMulti(userIdBloomKey, "101310111","101310222", "101310222","11111111");
System.out.println("某批value是否存在 " + existsBoolean);
}
}
jrebloom项目中使用的jedis是3.0.0-m1
,而自己项目中引入的jedis是2.9.0
。
而且发现3.0.0以上版本有些方法找不到了。例如set(String key, String value, String nxxx, String expx, long time)
。
因此如果要在项目中使用redisbloom,要注意jedis的版本信息。
参考文献:
https://oss.redislabs.com/redisbloom/Bloom_Commands/
https://github.com/RedisBloom/JReBloom
https://blog.csdn.net/zeb_perfect/article/details/54135506