用Redis来做数据排重,效率提升还挺明显的,怎么操作比较实用
- 问答
- 2026-01-05 22:06:07
- 13
前几天在网上看一个程序员分享他的工作经验,他说“用Redis来做数据排重,效率提升还挺明显的”,这句话一下子就说到了点子上,我以前处理数据排重,老是依赖数据库的查询,比如先SELECT一下看看这条数据存不存在,不存在再INSERT进去,数据量小的时候还行,一旦数据多了,比如要处理几万甚至几十万条消息、URL或者用户ID的去重,数据库的压力就非常大,速度慢得像蜗牛。
那怎么用Redis来操作才比较实用呢?根据我自己的实践和看别人的分享,主要有两个简单又高效的法子,一个是直接用Set集合,另一个是用布隆过滤器。
第一个实用的法子:用Redis的Set集合
这个是最直接、最容易上手的,Redis的Set集合天生就是用来存唯一值的,它内部会自动帮我们保证元素的唯一性,你往里加重复的数据,它直接就忽略掉了,特别省心。
具体操作起来很简单,我现在要爬取一个网站的所有链接,确保每个链接只爬一次,我可以这样做:
- 每拿到一个新的链接,我不用先去查数据库,而是直接用一个Redis命令:
SADD key member,这个key可以叫crawled:urls,意思是已经爬取过的网址集合;member就是当前这个具体的网址。 - 关键看这个命令的返回值,如果返回
1,说明这个网址之前不在集合里,是新的,那我就可以放心地去爬取它,爬完之后再把其他需要的信息存到数据库。 - 如果返回
0,那就说明这个网址已经在集合里了,是重复的,直接跳过处理下一条就行了。
这个过程就这么简单,一两行代码的事,因为Redis的数据是放在内存里的,所以SADD和检查返回值的操作非常非常快,比去硬盘上读写的数据库查询快了几个数量级,这个方法特别适合处理那种数据量虽然不是天文数字,但对实时性要求比较高,需要快速判断是否重复的场景,防止用户重复提交表单、统计每天的独立访客数(UV),用Set都非常方便。

但是Set集合有个小缺点,就是如果数据量极其庞大,比如要排重的对象有好几亿个,那么把这个巨大的Set完全放在内存里,对机器内存的要求会比较高,成本就上去了,这时候,就可以考虑第二个更节省空间的法子。
第二个更省空间的法子:用布隆过滤器
布隆过滤器这个名字听起来有点高级,但其实原理不难理解,你可以把它想象成一个很大的位数组(就是一串由0和1组成的格子),一开始所有格子都是0,它用几个不同的哈希函数,把每个要判断的数据“映射”到这个位数组的几个不同位置上,并把对应位置设置为1。

当你要判断一个新数据是否存在时,同样用这几个哈希函数算出它在位数组中的位置,然后去看看这些位置是不是都是1:
- 如果有一个位置是0,那这个数据肯定不存在。
- 如果所有位置都是1,那这个数据很可能存在(注意,是“很可能”,不是100%确定)。
这里就有一个关键点:布隆过滤器可能会误判,就是把不存在的误判成存在的(假阳性),但绝不会把存在的说成不存在,这对于很多排重场景是可以接受的,推荐新闻时,用布隆过滤器判断用户是否读过某条新闻,万一极少数情况下误判了,最多就是把一条读过的新闻又推荐了一次,影响不大,但它带来的好处是极大地节省了空间,用很小的内存就能处理海量数据的排重。
在Redis里,我们可以用BF.ADD命令来向布隆过滤器添加元素,用BF.EXISTS命令来判断元素是否存在,操作起来和Set差不多,但背后节省的内存可是天差地别。
总结一下怎么操作比较实用:
- 如果你的数据量在可接受范围内(比如几百万以内),追求简单粗暴和绝对准确,直接用Redis的Set集合,简单命令
SADD根据返回值判断,清晰明了。 - 如果你的数据量超级大,比如上亿级别,并且可以接受极低的误判率来换取内存空间,那就用Redis的布隆过滤器。
BF.ADD和BF.EXISTS命令也能轻松搞定。
那个程序员说的“效率提升还挺明显的”,关键就在于把排重这个频繁又简单的操作,从沉重的数据库身上卸了下来,交给了内存级的Redis来处理,相当于给高速公路开了一条专用的ETC通道,车子(数据)自然就跑得快了,这两种方法都是经过实践检验的,非常实用。
本文由钊智敏于2026-01-05发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/75192.html
