Redis 位图BitMap

应用场景:

  1. 用户签到
  2. 用户在线状态
  3. 统计活跃用户
  4. 各种状态值
  5. 自定义布隆过滤器
  6. 点赞功能

说明:

用string类型作为底层数据结构实现的一种统计状态的数据类型。

位图本质是数组,它基于string数据类型的按位操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(可以成为一个索引或者位格)。Bitmap支持的最大位数是2^32位,它可以极大的节省存储空间,使用512M内存就可以存储42.9亿的字节信息(2^32=4294967296)

Redis 位图BitMap

举例:

拿签到功能举例,比如京东的签到,估算3000万签到用户,一天一条数据,一个月就是9亿条,存储在mysql会很恐怖。

如何解决这个痛点?

  1. 一条签到记录对应一条记录,会占据越来越大的空间。
  2. 一个月最多31天,刚好int类型是32位,这样一个int类型就可以搞定一个月,32位大于31天,当天签到了就是1,没签到就是0
  3. 一条数据直接存储一个月的记录,不再存储一天的签到记录。

按年去存储一个用户的签到情况,365天只需要365/8≈46byte,1000w用户量一年也只需要44MB足够。

假如是亿级的系统,每天使用1个1亿位的Bitmap约占12M的内存(10^8/8/1024/1024),10天Bitmap的内存开销约为120MB,内存压力不算太高。在实际使用时,最好对Bitmap设置过期时间,让redis自动删除后而不再需要的签到记录节省内存开销。

Redis 位图BitMap
//用户1,10月份第三天签到,设置为1
127.0.0.1:6379> setbit sign:u1:10 3 1
(integer) 0
127.0.0.1:6379> setbit sign:u1:10 30 1
(integer) 0
127.0.0.1:6379> getbit sign:u1:10 0 //获取10月份第一天,没签到返回0
(integer) 0
127.0.0.1:6379> getbit sign:u1:10 3
(integer) 1
127.0.0.1:6379> bitcount sign:u1:10 //签到总天数
(integer) 2
127.0.0.1:6379>

用户签到场景

每天的日期字符串作为一个key,用户Id作为offset,统计每天用户的签到情况,总的用户签到数

活跃用户数统计
用户日活、月活、留存率等均可以用redis位数组来存储,还是以每天的日期作为key,用户活跃了就写入offset为用户id的位值1。
同理月活也是如此。

用户是否在线以及总在线人数统计
同样是使用一个位数组,用户的id映射偏移量,在线标识为1,下线标识为0。即可实现用户上下线查询和总在线人数的统计
APP内用户的全局消息提示小红点
现在大多数的APP里都有站内信的功能,当有消息的时候,则提示一个小红点,代表用户有新的消息。

位图计数:
位图计数 的意思是统计bitmap中值为1的位的个数,位统计的效率时很高的。
redis中允许使用二进制的key和二进制的value,bitmap就是二进制的value。

点赞/取消点赞:
假设用户ID为100,对照片ID为100的照片进行点赞。首先根据照片ID生成数据存储的redis key,比如生成策略是like_photo:{photo_id},用户ID为1000的用户点赞只需将like_photo:100的第1000位设置为1即可(取消置为0)。
redis setbit操作的时间复杂度为O(1),所以这种点赞方式十分高效。
当前是否点赞:
用户打开图片的时候需要查询当前是否点赞过该照片,查询是否点赞可以通过redis getbit操作实现。

查询点赞总次数:
比如需要显示照片ID为1000的照片的获赞总次数,只需对like_photo:1000进行位图计数操作即可:bitcount。时间复杂度为O(N)。个人以为可以在照片表中加一个字段记录获赞总次数,这样就不用循环统计各个照片的获赞次数。

Original: https://www.cnblogs.com/yszr/p/16395781.html
Author: 御世制人
Title: Redis 位图BitMap

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529046/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux、Windows下Redis的安装即Redis的基本使用详解

    前言 什么是Redis Redis是一个基于 内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件,它是「 Remote Dictionary …

    Linux 2023年6月6日
    0112
  • PHP str_repeat()

    str_repeat str_repeat() 函数把字符串重复指定的次数。 示例: function strRepeat() { echo str_repeat("*&…

    Linux 2023年6月7日
    0178
  • centos7 设置开机启动任务

    环境:centos7 需求:前两天调通的DNS server(bind/named)设置开机自启动 操作: 修改 /etc/rc.local 注意这个 rc.local 文件默认是…

    Linux 2023年6月6日
    0100
  • sqlcmd执行含中文等字符的sql脚本时报错解决方案

    阅文时长 | 0.41分钟字数统计 | 668.8字符主要内容 | 1、问题说明 2、解决方案 3、常用的Code Page 4、声明与参考资料『sqlcmd执行含中文等字符的sq…

    Linux 2023年6月14日
    097
  • 真正的mybatis_redis二级缓存

    网上流传的代码缓存失效存在严重问题。 思路….以后再细说 目前的方案还不够完美,失效力度控制不够细。 主要代码 java;gutter:true; import jav…

    Linux 2023年5月28日
    0116
  • CentOS7.6下Oracle19C RAC集群詳細搭建步驟

    CentOS7.6搭建RAC 1.系统环境配置 1.1概述 ​ 搭建两个节点的rac集群,其每个节点均有两个网卡,public网卡和private网卡。两个节点的主机名分别为rac…

    Linux 2023年6月13日
    071
  • 数据库简单查询

    简单查询 语法句式如下: SELECT filed1,filed2 … filedn FROM tablename [WHERE CONDITION11] [GROUP BY …

    Linux 2023年6月7日
    0123
  • Feign 进行rpc 调用时使用ribbon负载均衡源码解析

    转载请注明出处: Feign客户端接口的动态代理生成是基于JDK的动态代理来实现的,那么在所有的方法调用的时候最终都会走InvocationHandler接口的实现,默认就是Ref…

    Linux 2023年6月14日
    068
  • JQ 实现对比两个文本的差异并高亮显示差异部分

    利用jq对比两段文本的差异,差异的内容用不同颜色表示出来。 在线参考demo:http://incaseofstairs.com/jsdiff/ 项目地址:https://gith…

    Linux 2023年6月7日
    0107
  • redis

    字符串:类似vector,有空闲的空间 capacity和len,当长度小于1M时,每次扩容加倍,大于1M,每次扩容1M,最大512M hash: 相当于c++ unordered…

    Linux 2023年5月28日
    086
  • Redis多线程原理详解

    从上图中可以看出只有以下3个地方用的是多线程,其他地方都是单线程: 1:接收请求参数 2:解析请求参数 3:请求响应,即将结果返回给client 很明显以上3点各个请求都是互相独立…

    Linux 2023年5月28日
    077
  • Android 图片设置圆角

    Android 开发中,经常需要对图片进行二次处理,比如添加圆角效果 或 显示圆形图片; 通过第三方框架 Glide 设置圆角效果; 写法1: RequestOptions opt…

    Linux 2023年6月13日
    077
  • docker相关命令杂理

    – 2020.11.16docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] #保存现有的镜像 # docker commit …

    Linux 2023年6月8日
    086
  • Tomcat启动乱码

    1、找到安装的tomcat的conf目录2、找到logging.properties配置文件3、在文件中找到 java.util.logging.ConsoleHandler.en…

    Linux 2023年6月7日
    092
  • redis中save和bgsave区别

    SAVE 和 BGSAVE 两个命令都会调用 rdbSave 函数,但它们调用的方式各有不同: SAVE 直接调用 rdbSave ,阻塞 Redis 主进程,直到保存完成为止。在…

    Linux 2023年5月28日
    065
  • VirtualBox网络模式 宿主机无法访问虚拟机问题记录

    问题背景 最近在公司使用VirtualBox虚拟机,使用虚拟的ubuntu系统,家里的路由能使用桥接模式,然后能双向ping通(宿主机 现在经常要打开虚拟Linux跑一些脚本和编译…

    Linux 2023年6月6日
    0101
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球