前言

在使用缓存的时候,我们时不时会遇到这样一个需求,根据缓存键的规则去批量删除这些数据,比较常见的就是按前缀去删除。

举个简单的例子,Redis中现在有几百个商品的数据,这些数据的key值是有一定规律的,都是以product:id的形式存在的。

现在由于不得以为的原因要删除这几百个商品的数据,这个时候我们肯定就要把缓存键以product:开头的给全部删除掉。

其实这个需求在Redis中是可以很容易去实现的。

来看看几种常见的做法。

常见的几种做法

  1. 用Keys命令找到key之后执行删除操作
  2. 用Scan命令找到key之后执行删除操作(2.8.0版本之后)
  3. 添加缓存数据的时候,可以同时将key存放到一个SET中,然后依据这个SET来执行删除操作

对于Keys命令,网上有不少血的教训,对于生产环境还是要谨慎谨慎再谨慎!能不用就别用。

Scan命令的话是大部分人推荐的做法,是增量式迭代的一个命令。

存到SET中就相对繁琐一点,而且额外占用了一部分内存。而且在进行删除的时候还要从这里读取出相应的key,同时也要移除这部分key的数据。

下面来看看如何在.NET Core中来处理,主要还是针对SCAN的做法。

示例操作Redis用的是StackExchange.Redis

使用IServer.Keys

可能有人会有疑惑,不是说Keys命令尽量不要用吗?怎么你还用?

这个还真的要解释一下!

可能从方法上,我们找遍所有IServer和IDataBase接口都找不到纯粹的SCAN命令(SetScan,HashScan等除外)。

但是如果看过里面的实现,你就会知道是为什么了!

传送门:Keys

可以看看下图高亮的两行代码:

大致意思就是,如果你用的Redis的版本支持SCAN命令,走的就是SCAN,反之只能是KEYS了。

下面定义一个查找RedisKey的方法。

private static RedisKey[] SearchRedisKeys(IServer server, string pattern)
{
var keys = server.Keys(pattern: pattern).ToArray();
Console.WriteLine("Search Count-{0}",keys.Length);
return keys;
}

知道那些Key要删除,剩下的就比较简单了!

private static void KeysOrScanSolution(IServer server,IDatabase db, string pattern)
{
db.KeyDelete(SearchRedisKeys(server, pattern));
}

使用IDatabase.Execute

IServer.Keys可以说是隐式的调用了SCAN命令,那么我们自然也可以显式的去调用这个命令来完成这些。

private static RedisKey[] SearchRedisKeys(IDatabase db,string pattern)
{
var keys = new HashSet<RedisKey>(); int nextCursor = 0;
do
{
RedisResult redisResult = db.Execute("SCAN", nextCursor.ToString(), "MATCH", pattern, "COUNT", "1000");
var innerResult = (RedisResult[])redisResult; nextCursor = int.Parse((string)innerResult[0]); List<RedisKey> resultLines = ((RedisKey[])innerResult[1]).ToList(); keys.UnionWith(resultLines);
}
while (nextCursor != 0); return keys.ToArray();
}

删除的代码。

private static void ExecuteSolution(IDatabase db, string pattern)
{
db.KeyDelete(SearchRedisKeys(db, pattern));
}

当然还有一种做法是调用lua脚本去完成,这里就不细说了。

总结

虽然上面几种做法能比较简单的处理这个问题,但是在拿出这些Keys的时候,客户端的内存占用可能会比较大,尤其是有大量符合条件的缓存项的时候。

涉及缓存的诸多操作(包含根据前缀去删除缓存项),我也在EasyCaching中实现了相应的操作,后面也会不断的抽时间来完善这一项目,有兴趣的朋友可以关注一下。

文中的示例代码 RedisBatchRemoveSolution

谈谈使用Redis缓存时批量删除的几种实现的更多相关文章

  1. redis优雅的批量删除key

    redis优雅的批量删除key 近期在处理redis的故障中,发现需要删除大量的历史数据(也是bigkeys),好在符合正则表达式.要不然就很痛苦,这也体现了在设计key的时候遵循规范带来的维护好处之 ...

  2. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  3. 在Spring中使用Redis Lua脚本批量删除缓存

    背景 之前分享了一篇利用lua脚本批量删除redis的key的文章.现在项目中我打算使用spring的缓存,而Spring缓存以前我是用ehcache来做实现的.没发现什么问题..这次我换成redis ...

  4. memcache 缓存的批量删除方案(转)

    memcache 默认只支持使用delete(key)和 flush_all,这两种方法都太极端了,不能满足用户的特定需求,如:批量删除‘aaaaaaaa_’开头的所有缓存,这个时候该怎么办? 1 g ...

  5. Redis中的批量删除数据库中的Key

    本文参考:http://blog.csdn.net/spring21st/article/details/15771861 http://stackoverflow.com/questions/575 ...

  6. redis命令行批量删除匹配到的key

    执行命令如下 redis-cli -h 12.132.30.21 -p 6379 -a 2016 -n 4 keys "ecard*" | xargs redis-cli -h 1 ...

  7. redis 命令远程批量删除keys

    1.首先在电脑上装上 redis 客户端; https://www.cnblogs.com/feijl/p/6879929.html 2.安装成功后,进入 redis-cli 客户端目录; 连接 re ...

  8. redis通过命令批量删除key

    需求:想删除 notify_ 开头的所有key redis-cli KEYS "notify_*" | xargs redis-cli DEL 通过 notify_* 来匹配

  9. Redis批量删除缓存数据

    背景: 在使用redis中,经常会遇到批量删除缓存的情况,但是对于在客户端中,如果一个一个的删除key,则需要较长时间及相对麻烦,可以使用以下命令,批量删除缓存. 本地批量删除KEY: ./redis ...

随机推荐

  1. Python数据结构之一——list(列表)

    Python版本:3.6.2  操作系统:Windows   作者:SmallWZQ Python包含6种常见的内建序列.它们分别是列表.元祖.字符串.Unicode字符串.buffer(memory ...

  2. arm 异常处理结构

    概念:正常的程序执行过程中发生暂时的停止称为异常,如果发现异常情况,将会进行异常处理 作用:快速响应用户的行为,提高cpu的响应能力 异常类型: 异常处理的三个步骤: 1.保护现场: 工作模式保存:C ...

  3. javamail+ical4j发送会议提醒

    本篇讲述小编在使用ical4j时对其的理解与使用,留作笔记的同时希望能帮助到大家! 初学者可以先了解下ical4j的基本信息: iCalender编程基础,了解与使用ical4j:https://ww ...

  4. selenium2 python自动化测试实战(回归测试)

    selenium2 python自动化测试实战 最近接手商城的项目,针对后台测试,功能比较简单,但是流程比较繁多,涉及到前后台的交叉测试.在对整个项目进行第一轮测试完成之后,考虑以后回归测试任务比较重 ...

  5. Math Jax开源数学编辑器的使用

    首先,这是一个开源免费,同时也可以支持扩展的软件. 使用API文档: 中文网站(http://mathjax-chinese-doc.readthedocs.io/en/latest/index.ht ...

  6. centos7下安装apache服务器httpd的yum方式安装

    转自Clement-Xu的csdn博客 http://blog.csdn.net/clementad/article/details/41620631   Apache在Linux系统中,其实叫&qu ...

  7. python学习:简单的wc命令实现

    #!/usr/bin/python   import sys import os   try:     fn = sys.argv[1] except IndexError:     print &q ...

  8. C/C++语言的特点

    一.支持数据封装和数据隐藏 在C++中,类是支持数据封装的工具,对象则是数据封装的实现.C++通过建立用户定义类支持数据封装和数据隐藏. 在面向对象的程序设计中,将数据和对该数据进行合法操作的函数封装 ...

  9. 关于HTTP,你知道哪些?

    HTTP简介 HTTP 的全称是 Hypertext Transfer Protocol,超文本传输协议 规定客户端和服务器之间的数据传输格式 让客户端和服务器能有效地进行数据沟通 HTTP 协议是网 ...

  10. UVA - 11624 多点bfs [kuangbin带你飞]专题一

    题意:某人身陷火场,总有k个点着火,着火点可向四周扩散,问此人能否逃离. 思路:可能有多个着火点,以这些着火点作为起点进行bfs,得到整个火场的最短距离,然后又以人所在坐标作为起点进行bfs,得到该人 ...