Bitmap在Redis中的应用(转)

原文:https://cloud.tencent.com/developer/news/387248

作者:一叶而不知秋

作为铺垫,我们先来介绍一些Bitmap的相关内容:

位图主要用于快速检索关键字状态,通常要求关键字是一个连续的序列(或者关键字是一个连续序列中的大部分), 最基本的情况,使用1bit标示一个关键字的状态(可标示两种状态),但根据需要也可以使用2bit(标示4种状态),3bit(标示8种状态)。 位图的主要应用场合:标示连续(或接近连续,即大部分会出现)的关键字序列的状态(状态数/关键字个数 越小越好)。

几种应用场景:

(1)磁盘空闲块的管理

很多文件系统采用bitmap管理磁盘空闲块,如果该块是空闲的,标为0,已使用则标为1; Ext3文件系统中使用位图来管理磁盘空闲块(空闲inode节点)。文件系统创建后,该文件系统拥有的块数以及inode节点数都是确定的,数据块区包含一系列连续的块(块号是连续的),于是可以用位图来标示数据块的分配状态(已分配、未分配两种状态,1bit即可标示)。

如下图,假设ext3的数据块从128开始,一直到1024,则需要1024-128 = 996bit = 128字节的位图空间。如下图,第1bit标示128号块已经被分配,第2bit标示129号块未被分配,依次类推。使用位图的高效性在于:1bit标示状态,节省存储空间,通过关键字来定位位图(偏移是固定的),效率高。

(2)区域服务器路由场景

腾讯的QQ号用一个数字标示,范围从0到20亿,每个QQ号都有可能出现,所有的QQ号被分散的存储北京、上海、深圳、武汉四个城市的服务器中,现在需要一个路由服务器快速的将登陆的QQ路由到正确的服务器,路由服务器可以读取四个QQ服务器的数据,并构建路由表(需全部存在内存中,内存限制1G),路由表该如何存储?

关键:QQ号从0-20亿,每个号码都有可能出现;服务器通过0、1、2、3标示,这四种状态可以用2bit来标示,于是可以考虑使用位图来描述路由表。

解法:从0~20亿,为每个QQ号分配2bit,路由服务器从QQ服务器中获取信息,并设置QQ于服务器号的对应关系。当QQ登录时,路由服务器根据QQ号定位到其对应的状态,并返回对应的服务器号。总的内存大小20亿 * 2 /8 = 5亿字节(约为0.5G)。

(3)大量数据的快速排序、查找、去重

关键:去掉电话号码的800后面就是7位的十进制整数,每个整数都有可能出现而且不会重复出现,可以采用各种排序算法对这些数据进行排序,但时间复杂度都在O(NlogN)及以上。

解法:因每个七位以内的整数都有可能出现,可以用1bit来标示电话号是否出现,遍历整个电话号序列,设置相应的位,遍历位图收集位被设置的号码即可,时间复杂度为O(N);

【去重】场景:2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。 关键:一个数字的状态只有三种,分别为不存在,只有一个,有重复。因此,我们只需要2bits就可以对一个数字的状态进行存储了,假设我们设定一个数字不存在为00,存在一次01,存在两次及其以上为11。那我们大概需要存储空间几十兆左右。

解法:遍历一次这2.5亿个数字,如果对应的状态位为00,则将其变为01;如果对应的状态位为01,则将其变为11;如果为11,,对应的状态位保持不变。 最后,我们将状态位为01的进行统计,就得到了不重复的数字个数,时间复杂度为O(n)。

Redis与Bitmap

因为redis的key和value本身就支持二进制的存储方式,所以bitmap只是一个独特的扩展,并不是新的数据类型。他的最大长度就是512M,即2^32个不同字节。

bitmap相关指令介绍:

getbit key offset //获取字符串类型键指定位置的二进制位的值

bitcount key [start] [end] //获取字符串类型键中为1的二进制位个数,start、end是字节的范围

bitpos key value start end //指定区间查询某个key的二进制位中首次出现0或1的位置(start和end是字节位置,不是bit位置)

bitop operation destkey key [key …] //bitop命令可以对多个字符串进行位运算,并将结果存储在destkey参数指定的键中。bitop支持的运算操作有AND、OR、XOP和NOT。

魔术指令 bitfield:

bitfield key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL] bitfield 有三个子指令,分别是 get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理 64 个连续的位,如果超过 64 位,就得使用多个子指令,bitfield 可以一次执行多个子指令。

示例:

应用场景:

(1)用户签到

Bitmap在Redis中的应用(转)

1个用户1年会占用大约:1bit*365/8=45.625字节;

如果使用普通的 key/value,每个用户要记录 365 个,当用户量巨大时,需要的存储空间是惊人的。

(2)用户在线状态

只需要一个key,用户ID为offset,如果在线就设置为1,不在线就设置为0,1000万用户只需要100000000bit/8*=1.2MB的空间;

Bitmap在Redis中的应用(转)

(3)统计活跃用户

使用时间作为cacheKey,然后用户ID为offset,如果当日活跃过就设置为1;

如果想计算某几天的活跃用户呢(暂且约定,统计时间内只要有一天在线就称为活跃);

Bitmap在Redis中的应用(转)

Original: https://www.cnblogs.com/ajianbeyourself/p/15682237.html
Author: 奋斗终生
Title: Bitmap在Redis中的应用(转)

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

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

(0)

大家都在看

  • MariaDB 安装和配置

    一、MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。 1、关闭selinux ①修改selinux的配置文件 [root@localh…

    Linux 2023年6月7日
    082
  • Ubuntu16.04部署django+nginx项目

    项目使用django+nginx部署。这个项目断断续续地部署4遍了。感觉每次部署都挺费时间的(找各种配置的资料),于是写一个博客总结一下。 安装vsftpd $ sudo apt-…

    Linux 2023年6月7日
    058
  • algorithm 头文件参考

    定义执行算法的 C++ 标准库容器模板函数。 该 <algorithm></algorithm> 库还使用该 #include <initialize…

    Linux 2023年6月7日
    091
  • 2021年1月-第02阶段-前端基础-HTML+CSS进阶-VS Code 软件

    软件安装 VSCode软件 能够安装 VS Code 能够熟练使用 VS Code 软件 能够安装 VS Code 最常用的插件 1. VS Code简介 1.1 VS Code …

    Linux 2023年6月8日
    075
  • [转]Redis cluster failover

    今天测试了redis cluster failover 功能,在切换过程中很快,但在failover时有force 与takeover 之分 [RHZYTEST_10:REDIS:…

    Linux 2023年5月28日
    069
  • (Java初学篇)IDEA项目新建流程和软件配置优化以及怎么彻底删除项目

    相信很多小伙伴们在初学 Java 时都会出现这样的情况,就是在网上一顿搜索加捣鼓终于把 JDK 和IDEA 这两款软件安装配置好,但是发现面对这个陌生的软件此时却无从下手,那么接下…

    Linux 2023年6月6日
    0118
  • ThinkPHP5 远程命令执行漏洞

    一、ThinkPHP介绍 轻量级框架,内部OOP和面向过程代码都存在,是国人自己开发的框架。ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,诞生于2006年初,…

    Linux 2023年6月14日
    067
  • stat命令的实现

    任务详情 学习使用stat(1),并用C语言实现 提交学习stat(1)的截图 man -k ,grep -r的使用 伪代码 产品代码 mystate.c,提交码云链接 测试代码,…

    Linux 2023年5月27日
    075
  • 文件漏洞上传

    一般危害:xss csrf ssrf获取后台登录 影响业务逻辑文件上传 严重级别漏洞,可以直接接管你的服务器 初级别: $target_path = DVWA_WEB_PAGE_T…

    Linux 2023年6月6日
    089
  • Shell 实现多线程(多任务)

    1.命令结尾添加:& 在命令的末尾加 & 符号,则命令将在后台执行,这样后面的命令不需要等待该命令执行完再开始执行。 2.解决主线程提前退出问题,添加 wait 3…

    Linux 2023年5月28日
    079
  • CentOS7为php7.2安装php-redis扩展

    先下载phpredis-develop 安装unzip、zip解压工具 解压后会多了个phpredis-develop的目录。进入目录 安装phpize模块 执行phpize 查找…

    Linux 2023年5月28日
    062
  • FastDFS安装和简介详细总结

    1、fastDFS简介 1 FastDFS是用c语言编写的一款开源的分布式文件系统。 2 FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用…

    Linux 2023年6月7日
    0113
  • ubuntu 20.04.1 安装 PHP+Nginx

    ubuntu 20.04.1 安装 PHP+Nginx 全流程 ubuntu 20.04.1 安装 PHP+Nginx 更新源 sudo apt-get update 安装环境包 …

    Linux 2023年6月7日
    0114
  • RHCSA阶段笔记

    命令终端字段含义介绍 [root@localhost ~]# 解释: root:当前登录系统用户名(root超级管理员) localhost :当前主机名 :当前用户所在目录( 为…

    Linux 2023年6月14日
    074
  • R语言-tidyr和dplyr

    一、安装和加载 1、安装并加载tidyr和dplyr包 install.packages("tidyr") library(tidyr) install.pac…

    Linux 2023年6月8日
    077
  • shell脚本echo打印错位

    问题描述 在脚本中使用curl命令请求Jenkins的API获取job的编号,随后将编号和其他字符串拼接后,使用echo命令打印出来,但打印后字符串错位了。 脚本大致如下: num…

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