BitMap算法应用:Redis队列滤重优化
工作中有用到Redis滤重队列。
原来的方法如下:
方法一
- 为了保证操作原子性,使用Redis执行Lua脚本。
- 在脚本中的逻辑是,如果队列不超过某个数值,进行一次lrem操作(队列使用list结构),然后将新元素入列。
优点:
简单,直观。
缺陷:
- lrem的时间复杂度为O(N),N为队列中的元素个数;所以,性能一般。
- 因为防止队列内容过多,防止发生N级别的删除操作,限制了一个滤重的阀值,如果超过这个阀值就不能使用滤重功能。
方法二
为了解决以上痛点,新玩法为:
- 为了保证操作原子性,使用Redis执行Lua脚本。
- 同样使用Lua脚本,排重分为两步,使用了Redis自带的二进制数组进行维护是否存在重复的状态:
- 在入队之前,先从二进制数组中查询下这个key是否存在,即
getbit key offset
。如果存在说明队列中存在一个这个offset的值,就不需要进行入队操作,直接中断执行就好。 - 在出队的时候,将出队的元素在二进制数组中设置为不存在,即,setbit key offset 0。
- 在入队之前,先从二进制数组中查询下这个key是否存在,即
优点:
- 因为是bitmap算法,在查询是否存在执行的offset的时候,时间复杂度是O(1),并且与队列中元素个数无关。
- 优雅,如果算是优点的话,哈哈。
缺点:
- 最重要的一点是redis bitmap的offset必须是
int
,比如,long范围的offset是不存在的,这是一个很重要
的点,一定要注意(都是血泪史)。 - 因为入队和出队都进行了bitmap的数据维护,所以需要确保在编码的时候一定谨慎,足够健壮。
总结
从上面的分析来看,感觉方法二完胜方法一。其实不尽然,只能说各有不同的场景。
方法一比较通用,不论入队的内容是什么,都可能滤重,方法二依赖与Bitmap算法,意味key只能是数值型的元素。
在实际应用中,以上两种滤重方式一般是可以联合使用的。如果key是数值类型,没有超出int的取值范围,那么就直接使用方法二,如果超出了int的取值范围的数值就使用方法一。
扩展
还有一种滤重的算法叫:布隆过滤器,感兴趣的同学可以了解下:Bloom filter。如果不需要删除,不在乎误判率的话那应该是很合适的一个算法,空间和时间都很高效。
另外如果有人遇到过其他的一些坑或者有更好的建议,欢迎指点。
BitMap算法应用:Redis队列滤重优化的更多相关文章
- RabbitMQ、Memcache、Redis(队列、缓存)
RabbitMQ 一.解释 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消 ...
- Redis从出门到高可用--Redis复制原理与优化
Redis从出门到高可用–Redis复制原理与优化 单机有什么问题? 1.单机故障; 2.单机容量有瓶颈 3.单机有QPS瓶颈 主从复制:主机数据更新后根据配置和策略,自动同步到备机的master/s ...
- 经典算法题每日演练——第十一题 Bitmap算法
原文:经典算法题每日演练--第十一题 Bitmap算法 在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场 ...
- 【算法与数据结构专场】BitMap算法基本操作代码实现
上篇我们讲了BitMap是如何对数据进行存储的,没看过的可以看一下[算法与数据结构专场]BitMap算法介绍 这篇我们来讲一下BitMap这个数据结构的代码实现. 回顾下数据的存储原理 一个二进制位对 ...
- 海量数据处理-BitMap算法
一.概述 本文将讲述Bit-Map算法的相关原理,Bit-Map算法的一些利用场景,例如BitMap解决海量数据寻找重复.判断个别元素是否在海量数据当中等问题.最后说说BitMap的特点已经在各个场景 ...
- .NET 环境中使用RabbitMQ RabbitMQ与Redis队列对比 RabbitMQ入门与使用篇
.NET 环境中使用RabbitMQ 在企业应用系统领域,会面对不同系统之间的通信.集成与整合,尤其当面临异构系统时,这种分布式的调用与通信变得越发重要.其次,系统中一般会有很多对实时性要求不高的 ...
- 大数据排序算法:外部排序,bitmap算法;大数据去重算法:hash算法,bitmap算法
外部排序算法相关:主要用到归并排序,堆排序,桶排序,重点是先分成不同的块,然后从每个块中找到最小值写入磁盘,分析过程可以看看http://blog.csdn.net/jeason29/article/ ...
- .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用
环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...
- 分布式系统ID的生成方法之UUID、数据库、算法、Redis、Leaf方案
一般单机或者单数据库的项目可能规模比较小,适应的场景也比较有限,平台的访问量和业务量都较小,业务ID的生成方式比较原始但是够用,它并没有给这样的系统带来问题和瓶颈,所以这种情况下我们并没有对此给予太多 ...
随机推荐
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- C++系统预定义4个用于标准数据流对象
C++系统预定义4个用于标准数据流对象 cin cout cerr clog C++里关于cerr,clog,cout三者的区别: cerr(无缓冲标准错误)-----没有缓冲,发送给它的 ...
- 用extract-text-webpack-plugin提取出来的css文件中背景图片url的不正确的问题
在一个main.js中require一个scss文件,scss文件中用了背景图片,图片url是用的相对路径,用extract-text-webpack-plugin插件提取出的css文件背景图片路径不 ...
- 微信小程序之使用weui.wxss(八)
[未经作者本人同意,请勿以任何形式转载] 什么是WeUI? WeUI是在遵守微信视觉设计规范下,由官方设计团队为小程序量身定制的基础样式库. 这里把WeUI放到基础篇里,是因为WeUI是官方出品,并且 ...
- 解决:sudo: 无法解析主机:dinphy-500-310cn: 连接超时
出现这种问题是hosts文件没有配置好所导致的,linux无法解析到您的主机地址,解决方案如下: sudo vim /etc/hosts 其中vim是你的文本编辑器的命令,你如果电脑中没有vim,用g ...
- Codeforces Round #342 (Div. 2) A. Guest From the Past(贪心)
传送门 Description Kolya Gerasimov loves kefir very much. He lives in year 1984 and knows all the detai ...
- Oracle数据库开发
Oracle数据库开发之PL/SQL基础实战视频课程 1 PL/SQL 简介 2 入门实例(一) 3 入门实例(二) 4 PL/SQL 变量和常量 5 PL/SQL数据类型(一) 6 PL/SQL数据 ...
- Google 地图 API V3 之控件
Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...
- thinkphp3.2与phpexcel基础生成
public function ff(){ import("Org.Util.PHPExcel"); import("Org.Util.PHPExcel.Workshee ...
- js实现文本框中内容的放大显示
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...