• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

redis删除key

武飞扬头像
寂寞旅行
帮助1

redis的key删除的时候,是一个阻塞操作;
为什么会阻塞呢,是在删除key的时候,首先要寻找的key,然后进行删除,然而当key已经过期了,或者被他人删除之后,在删除的时候,就找不到这个key,那么它就一直寻找,新版的redis 有最大重试次数(以前的版本直接死循环),那么就会导致一直阻塞.这对于一线上项目来说,阻塞的这段时间可能是致命的;

如何避免??
1 删除普通key,删除key的时候,可以提前判断是否存在,在的时候再进行删除,这样就可以很大概率减少此类事件发生,例如这样:

  1.  
    if (redisTemplate.hasKey(RedisConstant.CASCADE_CHECK_COUNT cascadeDownTask.getId())) {
  2.  
    redisTemplate.delete(RedisConstant.CASCADE_CHECK_COUNT cascadeDownTask.getId());
  3.  
    }

不要直接删除
2 其实还有一种情况,删除的这个key为大 key,什么是大key,不是key有多大,而是key对应的value 很大,例如 redis有五种数据类型,有四个是集合,那么当key对应的集合 非常大的时候,此key 就叫做大key,那么删除的时候,也会导致阻塞问题;

我们可以利用类如 分段处理的方式去处理,例如: 目前redis中对应的数据类型是hash,然后hash中有大量 hk ,我们可以分段去删除,然后每次删除休眠一下,这样可以有效减少redis的压力

  1.  
    @SpringBootTest
  2.  
    @Slf4j
  3.  
    class AreaDemoControllerTest {
  4.  
     
  5.  
     
  6.  
    // @Autowired
  7.  
    // IAreaDemoService areaDemoService;
  8.  
    //
  9.  
    // @Autowired
  10.  
    // AreaDemoMapper areaDemoMapper;
  11.  
     
  12.  
    // @Test
  13.  
    // public void aaa(){
  14.  
    // List<AreaDemo> list = areaDemoService.list();
  15.  
    //
  16.  
    // List<AreaDemo> areaDemos1 = list.subList(0, 10);
  17.  
    // areaDemos1.forEach(demo -> demo.setId(null));
  18.  
    // areaDemoMapper.updateBatch(areaDemos1);
  19.  
    // }
  20.  
     
  21.  
     
  22.  
    @Autowired
  23.  
    RedisTemplate redisTemplate;
  24.  
     
  25.  
     
  26.  
    /**
  27.  
    * @Description 模拟批量删除大key
  28.  
    * @Author FL
  29.  
    * @Date 11:08 2022/5/12
  30.  
    * @Param []
  31.  
    **/
  32.  
    @Test
  33.  
    public void tetsts() {
  34.  
    String key = "mapKey";
  35.  
     
  36.  
    redisTemplate.opsForHash().put(key, "NAME", "小明");
  37.  
    redisTemplate.opsForHash().put(key, "age", "32");
  38.  
    redisTemplate.opsForHash().put(key, "add", "西湖");
  39.  
    redisTemplate.opsForHash().put(key, "tianqi", "晴朗");
  40.  
    redisTemplate.opsForHash().put(key, "heart", "nice");
  41.  
    redisTemplate.opsForHash().put(key, "shoot", "nike");
  42.  
    redisTemplate.opsForHash().put(key, "sex", "男");
  43.  
     
  44.  
    Cursor scan = redisTemplate.opsForHash().scan(key, ScanOptions.NONE);
  45.  
    int i = 0;
  46.  
    while (scan.hasNext()) {
  47.  
    Object next = scan.next();
  48.  
    System.out.println( i);
  49.  
    }
  50.  
    // redisTemplate.opsForHash().delete(key);
  51.  
    removeBigKey(key, 2, 100);// 每次删除两个 休眠100ms
  52.  
    }
  53.  
     
  54.  
    public void removeBigKey(String key, int scanCount, long intervalMills) throws CacheException {
  55.  
    final ScanOptions scanOptions = ScanOptions.scanOptions().count(scanCount).build();
  56.  
    // 避免内存泄漏
  57.  
    // 执行循环删除
  58.  
    List<String> fieldKeyList = new ArrayList<>();
  59.  
    try {
  60.  
    Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(key, scanOptions);
  61.  
    if (ObjectUtil.isNotNull(cursor)) {
  62.  
    while (cursor.hasNext()) {
  63.  
    String fieldKey = String.valueOf(cursor.next().getKey());
  64.  
    fieldKeyList.add(fieldKey);
  65.  
    if (fieldKeyList.size() >= scanCount) {
  66.  
    // 批量删除
  67.  
    Object[] fields = fieldKeyList.toArray();
  68.  
    redisTemplate.opsForHash().delete(key, fields);
  69.  
    log.info("[Big key] remove key: {}, fields size: {}", key, fields.length);
  70.  
    // 清空列表,重置操作
  71.  
    fieldKeyList.clear();
  72.  
    // 沉睡等待,避免对 redis 压力太大
  73.  
    // DateUtil.sleepInterval(intervalMills, TimeUnit.MILLISECONDS);
  74.  
    Thread.sleep(intervalMills);
  75.  
    }
  76.  
    }
  77.  
    }
  78.  
    // 最后 fieldKeyList 中可能还有剩余,不过一般数量不大,直接删除速度不会很慢
  79.  
    // 执行 key 本身的删除
  80.  
    // redisTemplate.opsForHash().delete(key,fieldKeyList);
  81.  
    redisTemplate.opsForHash().delete(key, fieldKeyList.toArray());
  82.  
    } catch (Exception e) {
  83.  
    // log.error();
  84.  
    }
  85.  
    }
  86.  
     
  87.  
     
  88.  
    }
学新通

代码均在 test中

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakkbg
系列文章
更多 icon
同类精品
更多 icon
继续加载