因为历史原因,在某个同步菜单操作的方法中先清除缓存,然后在初始化缓存。本来很正常的逻辑,但是这个清除是db查询获取所有的菜单 然后循环一条条删除 然后在db查询有效的菜单操作 在循环一条条**去 经统计这个菜单操作大概有个7千个 执行 耗时过久 大概50s -60s 不等
因为一些体验问题 也自然而然 想到优化
第一种 使用并行 插入或者删除
使用到stream的parallelStream 来并行执行 由于redis本身的单线程执行限制 时间来到了 10-15秒左右 体验效果还不是很好
第二种 使用pipeline 来批量执行命令
由于并行执行 提升的效果有限,我们换个思路来解决问题,减少与redis的交互 将命令批量执行 这样就会大大减少执行耗时 时间来到了 1- 2秒这个优化效果还是比较理想的 但是也发现了新的问题
虽然执行效果很快 但是在初始化缓存的时候 发现并没有成功初始化缓存
先看下 示例代码
讯享网
期间以为和使用pipelined的set方法 String 入参有关 于是更换为支持byte的方法 未果
后续还以为使用用法不对,经查询多方资料后 发现用法没问题
省略其他的尝试步骤。。。。。
最后将把expire 的设置注释掉 果然可以了
讯享网
最后问题定位到 是因为 pipelined1.expire(key,-1) 命令执行导致数据无法存入redis
讯享网
于是找到redis client 执行了命令 发现也很快失效

于是猜测 -1 这个过期时间会被设置 可能失效时间很短 有可能是 1毫秒 或者1 毫秒
带着问题 去找了下官方文档 看到这样一句描述

好像只写到了 会将过期时间戳存储为 绝对值 至于传入的时间 为负数 该如何处理并未说明
讯享网
看了代码后 思路也清晰了, 这个设置时间过期的逻辑 我们简单梳理下
这个当执行过期时间命令时,我们会传入 key 以及 过期时间(单位秒 或者 毫秒值) 以及 flag 参数 例如 nx xx 等等
核心的逻辑
- 判断时间参数
- 计算过期时间 = 当前时间戳 + 传入的过期时间参数 (单位秒/毫秒)
- 执行 flag参数 逻辑
- 执行 checkAlreadyExpired 判断时间是否已经过期 只有在 只有在非加载数据和非从实例的情况下,当 when 小于等于当前时间戳时,checkAlreadyExpired 函数才会返回 true 就会走到删除key的逻辑 并返回
- 没过期则进行设置新的过期时间 并返回
回到我们的执行操作中,我们执行expire 命令传入的时间参数为-1, 那过期时间就设置为当前时间戳 - 1000 。最后又因为设置的过期时间满足过期条件 (when 小于等于当前时间戳 非加载数据和非从实例),所以我们key 立刻会被删除 。这就导致了虽然我们方法执行完成,但是缓存却没有。
当需要设置一个没有过期时间的key的话 无需要调用expire方法 因为默认没有设置过期时间的话 就是永久不失效

参考官方文档: 官方文档地址: https://redis.io/docs/latest/commands/expire/
good day !!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/152478.html