1. 位与字节

  1个字节(byte)等于8个位(bit)。(计算机常识)。

2. string与bitmap

Redis里的bitmap是属于string这个数据类型里的。可以help进行查看bit相关api。

3. bitmap的api

3.1 setbit

稍微解释下,setbit 三个参数,第一个是key,第二个是偏移量,也就是在第几个位(从0开始)上写value,第三个是值(这个值只支持0和1,因为是位,二进制。如果你写了大于1的数或者小于0的数,会报错的,不信的自己尝试。)

get b1是个@符号,因为get取的不是位,所以不是0和1,而是ASCII码里的值,所以在ASCII码里对应的是@。(二进制转10进制,然后去ASCII码表里看,是@)

setbit b1 1 1其实对应的是(因为每个字节8个位):0 1 0 0 0 0 0 0

那我们在setbit b1 7 1,其实对应的就是:0 1 0 0 0 0 0 1,这时候gei b1就是A了,因为这个01000001在ASCII里对应的是大写A

那么继续setbit b1 9 1呢?每个字节等于8位,你这个9相当于第10位,一个字节放不下了,这时候就会开辟两个字节来存储,会变成如下

0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0

然后get b1就又是@了

3.2 Bitpos

含义:查找第start字节到end字节之间的值为bit(0/1)的偏移量(匹配到的位的下标,从0开始)。

bitpos 四个参数:key、要找的值(0/1)、从第几个字节(1个字节=8bit)开始找、到第几个字节结束

注意:最后两个参数是从第几个字节到第几个字节,这里是字节,可不是位。刚才b1来看,我们setbit了三次,分别是1 7 9,1和7在第一个字节上(因为1字节=8位),9在第二个字节上。所以可以写:bitpos b1 1 0 1,代表在b1这个key上找第一个字节到第二个字节之间第一次值为1的位的下标(也称偏移量)。

3.3 Bitcount

含义:统计start到end字节中二进制值为1的个数。

3.4 Bitop

3.4.1 概述

可以将多个bitmap进行按位与、按位或的操作,形成一个新的bit。

为了演示按位与和按位或,这里初始化两个bitmap

3.4.2 and

将b2和b3两个key进行按位与操作,结果存到andkey里

为什么andkey是个@?

b2:0100 0001

b3:0100 0010

b2 & b3:

0100 0000

换成10进制是64,在ASCII码表里这不就是@嘛??!!!

3.4.3 Or

将b2和b3两个key进行按位或操作,结果存到orkey里

跟上面按位与一样,自己算按位或后的二进制,在转换为10进制,得到67,ASCII码表里67是C

4. 利用bitmap完成需求

4.1 统计某用户登录天数

需求:统计出每个用户的登录天数,且支持随即查看哪天是否登录过。

需求分析:假设每年400天,1byte=8bit。那么每个字节能存8天的记录,400/8=50,也就是说50个字节就能记录某个人的一年登录状态。

具体实现:

假设zhangsan这个用户在第2、8、50、365天登录了,那么先setbit进去(假设zhangsan的用户id为123)

# 第2天
127.0.0.1:6380[2]> setbit 123 1 1
# 第8天
127.0.0.1:6380[2]> setbit 123 7 1
# 第50天
127.0.0.1:6380[2]> setbit 123 49 1
# 第364天
127.0.0.1:6380[2]> setbit 123 364 1

然后我们可以采取getbit来获取某一天是否登录。还可以利用bitcount来统计他今年登录了多少天。

# 查看123这个用户第50天是否登录
127.0.0.1:6380[2]> getbit 123 49
1
# 查看123这个用户到今年目前为止最后16天登录了几天。之所以-2 -1能管用是因为反向索引,string篇幅说了
127.0.0.1:6380[2]> bitcount 123 -2 -1
1
# 查看123这个用户今年前八天登录了几天
127.0.0.1:6380[2]> bitcount 123 0 0
2
# 查看123这个用户今年全年登录了多少天
127.0.0.1:6380[2]> bitcount 123
4

最后我们可以验证下到底用了多少byte存储的这个用户的全年记录,可以发现46字节而已。

4.2 查看活跃用户总数

  需求:比如要查看活跃用户,指定日期区间,在这区间登录过就算活跃。

需求分析:

假设xiaoming在20200320和20200321这两天登录了,而xiaohong只在20200321这一天登录了。那要怎么存储呢?首先这个是要以日期作为key,value需要是用户id所占的bit偏移量位置,比如这两个用户xiaoming占用字节里的第2位,也就是1,因为从0开始。再比如xiaohong占用字节里的第10位,也就是9。

PS:这个位怎么算都行,只要保证每个用户所占的字节偏移量不重复就行(也就是bit位置不重复就行),比如1000w个用户,那就每个用户id%1000w也能得到唯一的一个偏移量。

现在知道xiaoming在第2位,小红在第10位,也知道了他们哪天登录过,所以上代码

具体实现:

# xiaoming在20200320登录
127.0.0.1:6380[2]> setbit 20200320 1 1
# xiaoming在20200321登录
127.0.0.1:6380[2]> setbit 20200321 1 1
# xiaohong在20200321登录
127.0.0.1:6380[2]> setbit 20200321 9 1

需求是:在这两天的任意一天登录过就算活跃用户,soeay,直接bitop按或运算完事。然后bitcount统计出人数。

127.0.0.1:6380[2]> bitop or result 20200320 20200321
# 结果2人
127.0.0.1:6380[2]> bitcount result
2

疑问:连userid都没有我只统计人数有啥用?这需求不可能存在。

回复:搞促销,登录送礼品。数据库里10E用户,你准备多少礼品?10E份?亏大发。僵尸用户可能占用一大半。所以需要统计出活跃用户,然后根据活跃用户的数量在乘以一个比例算出合适的礼品数量。

转载:https://blog.csdn.net/ctwctw/article/details/105013817

Redis的bitmap从基础到业务的更多相关文章

  1. Redis(一)基础数据结构

    1.目录 Redis 基础数据结构 string (字符串) list (列表) hash (字典) set (集合) zset (集合) 容器型数据结构的通用规则 过期时间 2.Redis 基础数据 ...

  2. 基于Redis分布式BitMap的应用

    一.序言 在实际开发中常常遇到如下需求:判断当前元素是否存在于已知的集合中,将已知集合中的元素维护一个HashSet,使用时只需耗时O(1)的时间复杂度便可判断出结果,Java内部或者Redis均提供 ...

  3. Redis(一)-- 基础

    一.Redis 简介 Redis 是完全开源免费的,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内 ...

  4. Redis中bitmap的妙用

    BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间. Redis中的 ...

  5. 5、分布式缓存Redis之bitmap、setbit

    基本语法: 1)SETBIT redis 127.0.0.1:6379> setbit KEY_NAME OFFSET VALUE //该命令用于对 key 所储存的字符串值,设置或清除指定偏移 ...

  6. 生产消费者模式与python+redis实例运用(基础篇)

    根据这个图,我们举个简单的例子:假如你去某个餐厅吃饭,点了很多菜,厨师要一个一个菜的做,一个厨师不可能同时做出所有你点的菜,于是你有两个选择:第一个,厨师把所有菜都上齐了,你才开始吃:还有一个选择,做 ...

  7. redis的bitmap

    BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间. Redis中的 ...

  8. redis发布订阅实现各类定时业务(优惠券过期,商品不支付自动撤单,自动收货等)

    修改redis配置文件找到机器上redis配置文件conf/redis.conf,新增一行  notify-keyspace-events Ex 最后的Ex代表 监听失效的键值 修改后效果如下图 代码 ...

  9. springboot配置redis+jedis,支持基础redis,并实现jedis GEO地图功能

    Springboot配置redis+jedis,已在项目中测试并成功运行,支持基础redis操作,并通过jedis做了redis GEO地图的java实现,GEO支持存储地理位置信息来实现诸如附近的人 ...

随机推荐

  1. C#·JSON的处理和解析

    阅文时长 | 0.34分钟 字数统计 | 309.6字符 主要内容 | 1.引言&背景 2.声明与参考资料 『C#·JSON的处理和解析』 编写人 | SCscHero 编写时间 | 2021 ...

  2. Spring Cloud 升级之路 - 2020.0.x - 5. 理解 NamedContextFactory

    spring-cloud-commons 中参考了 spring-cloud-netflix 的设计,引入了 NamedContextFactory 机制,一般用于对于不同微服务的客户端模块使用不同的 ...

  3. MySQL优化|一分钟带你了解单表优化

    在开始前,分享给大家我看过觉得讲数据库讲的算是很不错的,也在B站拥有百万播放量的教程. 这个MySQL视频是动力节点的老杜讲解,个人也很喜欢老杜的教学风格,老杜真的是从MySQL基础一点点带我入门,基 ...

  4. Win10屏幕亮度不能调节,调节无效怎么办?

    Win10屏幕亮度不能调节,调节无效怎么办? 听语音 浏览:1027 | 更新:2019-11-22 11:43 1 2 3 4 5 6 7 分步阅读 一些用户在使用win10系统之后,出现了电脑屏幕 ...

  5. shell中 -eq,-ne,-gt,-lt,-ge,-le数字比较符

    使用说明:     -eq //equals等于    -ne //no equals不等于    -gt //greater than 大于    -lt //less than小于    -ge ...

  6. C++知识点案例 笔记-4

    1.纯虚函数 2.抽象类 3.内部类 4.运算符重载 5.类的函数重载 6.友元的函数重载 1.纯虚函数 ==纯虚函数== //有时基类中无法给出函数的具体体现,定义纯虚函数可以为派生函数保留一个函数 ...

  7. 040.Python进程和Join

    一  进程相关介绍 1.1 进程的概念(process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位 资源分配:分配的是cpu和内存等物理资源 进程号是程的唯标识 同-个程序执行两次之 ...

  8. Node.js入门(含NVM、NPM、NVM的安装)-(转载)

    Node.js的介绍 引擎 引擎的特性: JS的内核即引擎.因为引擎有以下特性: (1)转化的作用: 汽油柴油等等->动能 模板+数据--->页面 js引擎:js 代码--->机器码 ...

  9. VMWare虚拟机显示模块“Disk”启动失败

    找到启动虚拟机的目录: 在此路径中找到.vmx文件,在文件中查找(Ctrl+F快速查找)vmci0.present,此时会看到"vmci0.present = "TRUE" ...

  10. 用 Python 写个贪吃蛇,保姆级教程!

    本文基于 Windows 环境开发,适合 Python 新手 本文作者:HelloGitHub-Anthony HelloGitHub 推出的<讲解开源项目>系列,本期介绍 Python ...