BitMap算法应用:Redis队列滤重优化
2016-05-01 17:50
603 查看
工作中有用到Redis滤重队列。
原来的方法如下:
方法一
为了保证操作原子性,使用Redis执行Lua脚本。
在脚本中的逻辑是,如果队列不超过某个数值,进行一次lrem操作(队列使用list结构),然后将新元素入列。
优点:
简单,直观。
缺陷:
lrem的时间复杂度为O(N),N为队列中的元素个数;所以,性能一般。
因为防止队列内容过多,防止发生N级别的删除操作,限制了一个滤重的阀值,如果超过这个阀值就不能使用滤重功能。
方法二
为了解决以上痛点,新玩法为:
为了保证操作原子性,使用Redis执行Lua脚本。
同样使用Lua脚本,排重分为两步,使用了Redis自带的二进制数组进行维护是否存在重复的状态:
在入队之前,先从二进制数组中查询下这个key是否存在,即
在出队的时候,将出队的元素在二进制数组中设置为不存在,即,setbit key offset 0。
优点:
因为是bitmap算法,在查询是否存在执行的offset的时候,时间复杂度是O(1),并且与队列中元素个数无关。
优雅,如果算是优点的话,哈哈。
缺点:
最重要的一点是redis bitmap的offset必须是
因为入队和出队都进行了bitmap的数据维护,所以需要确保在编码的时候一定谨慎,足够健壮。
总结
从上面的分析来看,感觉方法二完胜方法一。其实不尽然,只能说各有不同的场景。
方法一比较通用,不论入队的内容是什么,都可能滤重,方法二依赖与Bitmap算法,意味key只能是数值型的元素。
在实际应用中,以上两种滤重方式一般是可以联合使用的。如果key是数值类型,没有超出int的取值范围,那么就直接使用方法二,如果超出了int的取值范围的数值就使用方法一。
扩展
还有一种滤重的算法叫:布隆过滤器,感兴趣的同学可以了解下:Bloom filter。如果不需要删除,不在乎误判率的话那应该是很合适的一个算法,空间和时间都很高效。
另外如果有人遇到过其他的一些坑或者有更好的建议,欢迎指点。
原来的方法如下:
方法一
为了保证操作原子性,使用Redis执行Lua脚本。
在脚本中的逻辑是,如果队列不超过某个数值,进行一次lrem操作(队列使用list结构),然后将新元素入列。
优点:
简单,直观。
缺陷:
lrem的时间复杂度为O(N),N为队列中的元素个数;所以,性能一般。
因为防止队列内容过多,防止发生N级别的删除操作,限制了一个滤重的阀值,如果超过这个阀值就不能使用滤重功能。
方法二
为了解决以上痛点,新玩法为:
为了保证操作原子性,使用Redis执行Lua脚本。
同样使用Lua脚本,排重分为两步,使用了Redis自带的二进制数组进行维护是否存在重复的状态:
在入队之前,先从二进制数组中查询下这个key是否存在,即
getbit key offset。如果存在说明队列中存在一个这个offset的值,就不需要进行入队操作,直接中断执行就好。
在出队的时候,将出队的元素在二进制数组中设置为不存在,即,setbit key offset 0。
优点:
因为是bitmap算法,在查询是否存在执行的offset的时候,时间复杂度是O(1),并且与队列中元素个数无关。
优雅,如果算是优点的话,哈哈。
缺点:
最重要的一点是redis bitmap的offset必须是
int,比如,long范围的offset是不存在的,这是一个很
重要的点,一定要注意(都是血泪史)。
因为入队和出队都进行了bitmap的数据维护,所以需要确保在编码的时候一定谨慎,足够健壮。
总结
从上面的分析来看,感觉方法二完胜方法一。其实不尽然,只能说各有不同的场景。
方法一比较通用,不论入队的内容是什么,都可能滤重,方法二依赖与Bitmap算法,意味key只能是数值型的元素。
在实际应用中,以上两种滤重方式一般是可以联合使用的。如果key是数值类型,没有超出int的取值范围,那么就直接使用方法二,如果超出了int的取值范围的数值就使用方法一。
扩展
还有一种滤重的算法叫:布隆过滤器,感兴趣的同学可以了解下:Bloom filter。如果不需要删除,不在乎误判率的话那应该是很合适的一个算法,空间和时间都很高效。
另外如果有人遇到过其他的一些坑或者有更好的建议,欢迎指点。
相关文章推荐
- redis在windows下安装和PHP中使用
- redis安装
- redis持久化RDB和AOF
- Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk"问题的解决
- (转)国内外三个不同领域巨头分享的Redis实战经验及使用场景
- Redis几个认识误区
- 利用redis做频率限制第一篇
- Tomcat集群+Nginx+Redis服务搭建
- Redis源码解析:17Resis主从复制之主节点的部分重同步流程及其他
- redis数据类型
- NoSQL之Redis(五)--- Redis测试以及其与Spring的集成
- redis安装
- Dubbo-redis3解决负载均衡Session共享
- 常用 redis 命令(for php)
- hadoop正式学习之redis---redis优化
- 用Redis bitmap统计活跃用户、留存
- 用Redis bitmap统计活跃用户、留存
- 虚拟内存的使用--Redis学习笔记九
- 3.Python操作Redis:字符串(String)
- 发布与订阅消息--Redis学习笔记八