如何对线上Redis进行数据清理

前言

在现今的互联网系统中,Redis以其优秀的性能和简洁的设计,被广泛使用,尤其是在分布式系统中;Redis最主要的应用场景在于为分布式系统提供公用内存服务,而在使用的过程中,尤其是线上的高可用环境,需要时刻注意其内存占用情况,一旦其内存吃紧,就会导致Redis性能下降,并引发服务不可用;此时除了硬件扩展,一个经常使用的手段就是线上数据清理

如何清理线上环境Redis数据

一般有正规运营团队的公司里,运营团队都会针对Redis出一套规范,这里面一般就包括:如无特殊情况,所有数据必须设置超时时间,以防数据无限堆积;即便如此,还是无法保证所有开发人员百分百遵守,同时即便遵守,理论上也还是有内存吃紧的情况,此时除了增加硬件资源外,常用的做法就是根据业务对Redis无用数据进行清理

另一方面,由于Redis是基于单线程事件模型(为什么是单线程,可以参照Redis FAQ),为了保持线上高可用,一般决不允许单一命令阻塞过长,如:KEYSSMEMBERS等命令就需要限制不能随便使用;此时如何对Redis的数据进行清理呢?针对这种情况,Redis给出了「迭代扫描」系列命令,先来看看Redis官方对该系列命令的描述:

The SCAN command and the closely related commands SSCAN, HSCAN and ZSCAN are used in order to incrementally iterate over a collection of elements.

  • SCAN iterates the set of keys in the currently selected Redis database.
  • SSCAN iterates elements of Sets types.
  • HSCAN iterates fields of Hash types and their associated values.
  • ZSCAN iterates elements of Sorted Set types and their associated scores.

Since these commands allow for incremental iteration, returning only a small number of elements per call, they can be used in production without the downside of commands like KEYS or SMEMBERS that may block the server for a long time (even several seconds) when called against big collections of keys or elements

大思就是SCAN系列命令主要包含四个:SCANSSCANHSCANZSCAN,分别针对不同的数据类型,它们的主要特点在于支持对数据进行迭代式扫描,每次只返回部分数据(返回多少可定制),这就有效屏蔽了全量扫描命令如KEYSSMEMBERS等单一命令执行时间过长造成的服务器阻塞

下面就如何利用HSCAN进行数据扫描并清理进行举例说明,实现语言为Java,其他语言逻辑大同小异,具体如下:

  /**
   * 迭代式删除Hash数据
   * @param hashKey, hash key
   * @param iterSize, 每次迭代元素数量,过大会可能会导致阻塞,过小会导致清理效率底下
   * @return
     */
  public int delHash(String hashKey, int iterSize) {
    int cursor = 0;

    ScanParams scanParams = new ScanParams().match("*").count(iterSize > 0 ? iterSize : 1000);
    ScanResult<Entry<String, String>> scanResult;
    List<Entry<String, String>> processList = new ArrayList<>();
    int delCount = 0;
    do {
      try {
        log.info("begin scan, cursor is {}", cursor);
        scanResult = jedis.hscan(hashKey, String.valueOf(cursor), scanParams);
        processList.addAll(scanResult.getResult());
        List<String> dList = processList.stream().map(Entry::getKey).collect(Collectors.toList());
        //批量删除
        jedis.hdel(hashKey, dList.toArray(new String[dList.size()]));
        delCount += processList.size();
        processList.clear();
        //获取游标位置,若大于0,则代表还有数据,需要继续迭代
        cursor = Integer.parseInt(scanResult.getStringCursor());
        log.info("scan next, cursor is {}", cursor);
      }catch (Exception e) {
        log.error(e.getLocalizedMessage(), e);
      }
    } while (cursor > 0);

    log.info("delete hash {} over, {} key be deleted", hashKey, delCount);

    return delCount;
  }

使用方式不复杂,如果使用过Java迭代器的同学应该对这种形式很熟悉,主要流程就是通过判断标识(Java Iterator 中的 hasNext()next())对整体数据进行切分并操作,如此循环,直至覆盖全部数据;这里有一个点需要注意的就是,每次迭代元素数量需要设置一个合适的值,过大会可能会导致阻塞,过小会导致处理效率底下,我在实际使用的时候发现每次处理1000个效率较高,当然,实际情况可能会根据硬件和带宽不同而有差异

总结

本文只从纯技术角度简单的阐述了Redis线上数据清理需要注意的点及如何操作,实际的过程中还需要有很多其他考虑,如:

  • 与业务团队沟通,哪些数据可以被清理,是否需要对相关数据做另行备份,以防万一误删
  • 与保障团队沟通,以防清理过程中出现问题,需要及时恢复

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容