本文主要研究一下redis的bitset数据结构的用场

相关命令

SETBIT

时间复杂度为O(1)

setbit login.20180906 102400000 0
setbit login.20180905 201400000 1
复制代码

GETBIT

时间复杂度为O(1)

getbit login.20180905 201400000
复制代码

BITOP

时间复杂度为O(N)

bitop or login.9m.week1or login.20180905 login.20180906
getbit login.9m.week1or 201400000
复制代码

主要做bitset的and、or、xor、not操作,结果存在新的bitset中,注意时间复杂度为O(N)

BITPOS

时间复杂度为O(N)

bitpos login.20180905 1
复制代码

返回指定bitset中在指定起始位置中第一个出现指定值的offset,不传start,end默认估计是0,-1

BITCOUNT

时间复杂度为O(N)

bitcount login.20180905
复制代码

统计bitset中出现1的个数

使用场景

假设有个签到的需求,要实现的功能如下:

  • 展示当天是否已经签到,签到了不能再签到了
  • 展示最近一周的或者最近一个月的签到情况/历史(可以只不详细记录到每天的签到时间,只记录每天是否签到)
  • 判断是否连续签到,若本周连续签到,则给予抽奖机会

这里我们就可以使用redis的bitset来实现:

签到

boolean originValue = redisTemplate.opsForValue().setBit(uidYearKey,dayIndx,true);
复制代码
  • 这里的key由uid,year构成,然后offset采用day的index
  • 每个uid每个year一个key的话,如果用户数过多可能造成redis的key太多

获取签到数据

  BitSet bitSet = fromByteArrayReverse(redisTemplate.opsForValue().get(uidYearKey).getBytes());public static BitSet fromByteArrayReverse(final byte[] bytes) {final BitSet bits = new BitSet();for (int i = 0; i < bytes.length * 8; i++) {if ((bytes[i / 8] & (1 << (7 - (i % 8)))) != 0) {bits.set(i);}}return bits;}
复制代码
  • 这里有个注意事项,java读取bytes从小到大是从右往左读(大端),而redis存储的bytes从小到大是从左往右(小端),因而这里读取bytes转为BitSet需要逆向一下

BitSet Range

public BitSet get(int fromIndex, int toIndex) {//......
}
复制代码
  • BitSet有个方法,可以根据index来进行range,之后就可以用新的BitSet进行相关统计,比如BitSet的cardinality

小结

  • 对于bitset来说,其优点就是节省内存,如果直接把用户id作为offset来存储相应的值,这个相比hash来说,节省了很多空间。类似统计最近N天连续登陆的人的个数这类场景就可以使用bitset来实现。
  • 对于bitset的操作要注意,各个操作的时间复杂度,如果是getbit、setbit则都是O(1),bitop、bitcount、bitpos等都是O(N),在N比较大的时候要注意,可能是潜在的慢查询

doc

  • setbit
  • getbit
  • bitop
  • bitpos
  • bitcount
  • Efficient analytics with Redis bitmaps
  • Be Careful With your Redis BitSets and Java
  • REDIS BITMAPS – FAST, EASY, REALTIME METRICS
  • Bitmaps vs. Sets to track Monthly Active Users in Redis
  • storing-hundreds-of-millions-of-simple-keys-in-282-mb-with-redis

redis的bitset实战相关推荐

  1. 《Redis核心技术与实战》学习总结(1)

    [Redis]| 总结/Edison Zhou 0写在开头 作为Key/Value键值数据库,Redis的应用非常广泛.在之前多年的工作生涯中,我也只是关注了零散的技术点,没有对Redis建立起一套整 ...

  2. 《Redis核心技术与实战》学习总结(2)

    [Redis]| 总结/Edison Zhou 1上一篇的遗留问题 上一篇总结了一个KV数据库的基本架构 和 Redis的底层数据结构概览,重点总结了Sorted Set的两个数据结构的切换,但没有介 ...

  3. 极客时间 Redis核心技术与实战 笔记(基础篇)

    Redis 概览 Redis 知识全景图 Redis 问题画像图 基础篇 基本架构 数据结构 数据类型和底层数据结构映射关系 全局哈希表 链式哈希解决哈希冲突 渐进式 rehash 不同数据结构查找操 ...

  4. 火影专场:Redis分布式锁实战

    火影专场:Redis分布式锁实战 我们学习 Java 都知道锁的概念,例如基于 JVM 实现的同步锁 synchronized,以及 jdk 提供的一套代码级别的锁机制 lock,我们在并发编程中会经 ...

  5. 网易有道 | REDIS 云原生实战

    REDIS 云原生实战 摘要 本次以Redis为范例,阐述了有道基础架构团队在基础设施容器化道路上的实践,主要将从声明式管理,Operator工作原理,容器编排,主从模式,集群模式,高可用策略,集群扩 ...

  6. Redis入门到实战

    redis入门与实战 一.Nosql概述 1.为什么要用Nosql 1.1 单机 MySQL 的美好时代 来源博客(https://www.cnblogs.com/lukelook/p/1113520 ...

  7. 四.redis的基础+实战

    四.redis的基础+实战 1.redis是什么? 2.redis常用于什么? 3.docker安装redis 4.java连接redis进行缓存 5.操作redis数据库的类 6.redis结合js ...

  8. Redis核心技术与实战-蒋德钧-课程笔记

    一.Redis知识全景图 二.Redis问题画像图 参考资料: 极客时间<Redis核心技术与实战>课程

  9. Redis学习笔记②实战篇_黑马点评项目

    若文章内容或图片失效,请留言反馈.部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 资料链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA( ...

最新文章

  1. linux下必看的60个命令
  2. 如何获取真实的执行计划
  3. 前端传数据到后台部分接收成功,部分接收失败
  4. 1-1:网络初识之了解什么是协议以及TCP/IP协议
  5. Java基础---File类,就是这么简单
  6. 用VBA下载google图片
  7. 9860计算机测量程序,卡西欧9860测量放样程序-绘星
  8. 目标检测中region proposal的作用?
  9. 输入一串字符串 字符串长度不超过100
  10. spring cloud gateway filters学习
  11. 计算机网络教室财产登记表,固定资产清查登记表-资产管理.DOC
  12. 一副好的平面设计作品,来自优秀的字体
  13. 传奇世界最好的版本:
  14. 接上一篇的正点原子战舰读取sd卡文本文件的主程序。
  15. js格式化时间(YYYY-MM-DD)
  16. 矿产行业智能采购管理系统开发,采购平台提升矿企核心竞争力
  17. 腾讯游戏助手运行闪退日志查看
  18. echarts saveAsImage提示字显示不全
  19. 基于SpringBoot实现文件上传功能(前端使用postman检查request)
  20. 友情链接作用与方法详解

热门文章

  1. 一步一步学习Bootstrap系列--表单布局
  2. [Android]动态加载/热部署框架汇总
  3. Delphi CxGrid 汇总(3)
  4. asp.net添加电子地图
  5. UVALive 4216 Pole Position
  6. 如何把单精度二进制数转换成十进制数?
  7. Unity的对象复用
  8. 通过 React Hooks 声明式地使用 setInterval
  9. select,InnoDB为啥会阻塞insert?
  10. OGG目标端复制Sequence时Hang住的问题