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的生成方式比较原始但是够用,它并没有给这样的系统带来问题和瓶颈,所以这种情况下我们并没有对此给予太多 ...
随机推荐
- php导出EXCEL方法
// 将数据表导出成 csv 格式文件并下载 // @param string $data:要导出的数据 // @param array $del:不导出的字段名,指定的字段数据不被导出 // @pa ...
- IEnumerable,IQueryable之前世今生
来自于:http://www.cnblogs.com/chengxiaohui/articles/2088967.html IEnumerable<T>在.Net2.0中我们已经很熟悉了. ...
- SQL/LINQ/Lamda 写法[转发]
SQL LINQ Lambda SELECT * FROM HumanResources.Employee from e in Employees select e Employees .Sele ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 大型软件系统客户端数据同步的问题解决
作为一个完整的整体信息化解决方案需要有足够强大的各种功能,这些功能相对独立,又互相依存.当有需要这样的功能时可以随时拿出来用,适当修改一下就可以满足要求.只有这样才能快速开发各种信息化系统,才能满足各 ...
- Dump中查看dictionary信息的方法
In order to dump the contents of a dictionary, you need to start with either the MethodTable or the ...
- 当泛型方法推断,扩展方法遇到泛型类型in/out时。。。
说到泛型方法,这个是.net 2.0的时候引入的一个重要功能,c#2.0也对此作了非常好的支持,可以不需要显试的声明泛型类型,让编译器自动推断,例如: void F<T>(T value) ...
- centos7 安装jdk1.8
安装之前下熟悉以下连个文件 (1)/etc/profile 全局(公有)配置,不管是哪个用户,登录时都会读取该文件. (2)~/.bashrc: 该文件包含专用于你的bash shell的bas ...
- Sunny-ngrok 解决外网访问内网问题
该博文已过时 请参考官网 http://www.ngrok.cc/ 一 .进入 网址 往下拉找到: 下载不同的版本. 二. 平台登陆地址:http://www.ngrok. ...
- 解决:Windows 开机弹出AotuIt ERROR 错误
AutoIt是个脚本语言,常被用于自动化安装.网络上有些系统镜像里含有AutoIt脚本,用于系统的自动配置.出现这种问题往往有两种可能的原因: 1)做系统的时候没搞好.这种情况就需要换一个镜像文件. ...
- hbase-0.94 Java API
Hierarchy For Package org.apache.hadoop.hbase Package Hierarchies: All Packages Class Hierarchy java ...