何保证Redis中的数据都是热点数据?延申:布隆过滤器;Lua脚本相关等等解决问题
发布时间: 2020-08-06 10:26:22文章作者: 网站编辑阅读量: 216
何保证Redis中的数据都是热点数据
A. 可以通过手工或者主动方式,去加载热点数据
B. Redis有其自己的数据淘汰策略:
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
延申:布隆过滤器
数据结构及算法篇 / 布隆过滤器
Redis 实现
redis 4.X 以上 提供 布隆过滤器插件
centos中安装redis插件bloom-filter:https://blog.csdn.net/u013030276/article/details/88350641
语法:[bf.add key options]
语法:[bf.exists key options]
注意: redis 布隆过滤器提供的是 最大内存512M,2亿数据,万分之一的误差率
Lua脚本相关
使用Lua脚本的好处:
减少网络开销。可以将多个请求通过脚本的形式一次发送,减少网络时延
原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件,无需使用事务
复用,客户端发送的脚本会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑
@RequestMapping("/testLua")
public String testLua () {
String key = "mylock";
String value = "xxxxxxxxxxxxxxx";
// if redis.call('get', KEYS[1]) == ARGV[1]
// then
// return redis.call('del', KEYS[1])
// else
// return 0
// end
// lua脚本,用来释放分布式锁 - 如果使用的较多,可以封装到文件中, 再进行调用
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
Object eval = jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
return eval.toString();
}
性能相关 - Redis慢查询分析
redis 命令会放在redis内置队列中,然后主线程一个个执行,因此 其中一个 命令执行时间过长,会造成成批量的阻塞
命令:slowlog get 获取慢查询记录
slowlog len 获取慢查询记录量
(慢查询队列是先进先出的,因此新的值在满载的时候,旧的会出去)
Redis 慢查询 -> 执行阶段耗时过长
conf文件设置:
slowlog-low-slower-than 10000 -> 10000微秒,10毫秒 (默认)
0 -> 记录所有命令
-1 -> 不记录命令
slow-max-len 存放的最大条数
慢查询导致原因: value 值过大,解决办法:
数据分段(更细颗粒度存放数据)
如何提高Redis处理效率? 基于Jedis 的批量操作 Pipelined
Jedis jedis = new Jedis("127.0.0.1", 6379);
Pipeline pipelined = jedis.pipelined();
for (String key : keys) {
pipelined.del(key);
}
pipelined.sync();
jedis.close();
// pipelined 实际是封装过一层的指令集 -> 实际应用的还是单条指令,但是节省了网络传输开销(服务端到Redis环境的网络开销)