3天时间,我是如何解决redis bigkey 删除问题的?( 四 )

  • 构建的 key
/** * 获取对应的 keys 信息 * @param list 列表 * @return 结果 */private String[] getFieldsKeyArray(List list) { String[] strings = new String[list.size()]; for(int i = 0; i < list.size(); i++) {strings[i] = list.get(i).getKey(); } return strings;}针对 redisTemplate 的写法语法估计是 redis 进行了一次封装 , 发现还是存在很多坑 。
语法如下:
/** * 获取集合的游标 。 通过游标可以遍历整个集合 。* ScanOptions 这个类中使用了构造者 工厂方法 单例 。通过它可以配置返回的元素 * 个数 count与正则匹配元素 match. 不过count设置后不代表一定返回的就是count个 。 这个只是参考 * 意义 * * @param key * @param options* @return * @since 1.4 */Cursor scan(K key, ScanOptions options);注意的坑实际上这个方法存在很多需要注意的坑:
(1)cursor 要关闭 , 否则会内存泄漏
(2)cursor 不要重复关闭 , 或者会报错
(3)cursor 经测试 , 直接指定的 count 设置后 , 返回的结果其实是全部 , 所以需要自己额外处理
参考代码如下:
  • 声明
@Autowiredprivate StringRedisTemplate template;
  • 核心代码
public void removeBigKey(String key, int scanCount, long intervalMills) throws CacheException {final ScanOptions scanOptions = ScanOptions.scanOptions().count(scanCount).build();//TRW 避免内存泄漏 try(Cursor> cursor =template.opsForHash().scan(key, scanOptions)) {if(ObjectUtil.isNotNull(cursor)) {// 执行循环删除List fieldKeyList = new ArrayList<>();while (cursor.hasNext()) {String fieldKey = String.valueOf(cursor.next().getKey());fieldKeyList.add(fieldKey);if(fieldKeyList.size() >= scanCount) {// 批量删除Object[] fields = fieldKeyList.toArray();template.opsForHash().delete(key, fields);logger.info("[Big key] remove key: {}, fields size: {}",key, fields.length);// 清空列表 , 重置操作fieldKeyList.clear();// 沉睡等待 , 避免对 redis 压力太大DateUtil.sleepInterval(intervalMills, TimeUnit.MILLISECONDS);}}}// 最后 fieldKeyList 中可能还有剩余 , 不过一般数量不大 , 直接删除速度不会很慢// 执行 key 本身的删除this.opsForValueDelete(key); } catch (Exception e) {// log.error(); }}这里我们使用 TRW 保证 cursor 被关闭 , 自己实现 scanCount 一次进行删除 , 避免 1 个 1 个删除网络交互较多 。
使用睡眠保证对 Redis 压力不要过大 。
测试验证当然上线之前需要测试充分的验证 , 这里我是自己做了自测 , 然后让测试帮我做了回归 。
确认不影响功能 , 删除性能等方面都没有问题之后 , 才进行了上线发布 。
上线之后做了连续3天的观察 , 一切稳定 , 这个问题也算是告一段落 。
小结redis 作为一个高性能的缓存服务 , 使用的时候确实会存在各种各样的问题 。
有时候是我们自己使用不留意 , 有时候是前人埋下的坑 。 (比如我这个)
遇到这种问题 , 找到原因 , 并且找到合适的解决方案 , 才是最重要的 。
这个 redis bigkey 我前后分析+编码+自测+上线 , 差不多共计 3 天左右 , 还算顺利 。 其中两条是分析原因+讨论解决方案 , 编码测试反倒比较简单 。
希望对你有帮助 。
感兴趣的可以关注一下 , 便于实时接收最新内容 。
觉得本文对你有帮助的话 , 欢迎点赞评论收藏转发一波 。 你的鼓励 , 是我最大的动力~


推荐阅读