5、分布式缓存Redis之bitmap、setbit
基本语法:
1)SETBIT
redis 127.0.0.1:6379> setbit KEY_NAME OFFSET VALUE //该命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。时间复杂度O(1)
1
在redis中,存储的字符串都是以二进制的形式存在的。比如:设置一个key-value,键的名字叫“andy” ,值为字符’a’,‘a’ 的ASCII码是97。转换为二进制是:01100001。offset的学名叫做“偏移” ,二进制中的每一位就是offset值,比如在这里offset 0 等于 ‘0’ ,offset 1等于’1’ ,offset2等于’1’,offset 6 等于’1’ ,没错,offset是从左往右计数的,也就是从高位往低位。
那如何通过SETBIT命令将 andy中的 ‘a’ 变成 ‘b’ 呢?即将 01100001 变成 01100010(b的ASCII码是98),其实就是将’a’中的offset 6从0变成1,将offset 7从1变成0。
这里写图片描述
每次SETBIT完毕之后,有一个(integer) 0或者(integer)1的返回值,这个是在你进行SETBIT 之前,该offset位的比特值。最后通过get andy得到的结果变成了 ‘b’ 。
2)BITCOUNT
redis 127.0.0.1:6379> bitcount andy //该命令统计字符串(字节)被设置为1的bit数
1
经过setbit操作之后,andy代表的01100010(b的ASCII码是98),共有3个1。
这里写图片描述
这里需要注意一点的是!!!!!!!!
bitcount 统计的是1的个数, bitcount test 0 -1 就是所有的, bitcount 0 0 那么就应该是第一个字节中1的数量的,注意是字节 第一个字节也就是 0 1 2 3 4 5 6 7 这八个位置上。见下面的测试样例,setbit单位是bit,bitcount是以byte为间隔统计的
3)GETBIT
redis 127.0.0.1:6379> getbit andy offset //返回key对应的string在offset处的bit值
1
4)BITOP
redis 127.0.0.1:6379> bitop operation destkey key [key...] //对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上
1
BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数:
BITOP AND destkey srckey1 … srckeyN ,对一个或多个 key 求逻辑与,并将结果保存到 destkey
BITOP OR destkey srckey1 … srckeyN,对一个或多个 key 求逻辑或,并将结果保存到 destkey
BITOP XOR destkey srckey1 … srckeyN,对一个或多个 key 求逻辑异或,并将结果保存到 destkey
BITOP NOT destkey srckey,对给定 key 求逻辑非,并将结果保存到 destkey
按位与运算符(&)
参加运算的两个数据,按二进制位进行“与”运算。
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两位同时为“1”,结果才为“1”,否则为0
按位或运算符(|)
参加运算的两个对象,按二进制位进行“或”运算。
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象只要有一个为1,其值为1。
异或运算符(^)
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0
除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入,执行结果将始终保持到destkey里面。
当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
这里写图片描述
应用举例:
setbit 可以理解是一个位数组,至于这个数组有多大,redis中bit映射被限制在512MB之内,所以最大是2^32。也就是在这样一个位数组上存0或者是1 ,可以结合bloomFilter的应用场景理解位数组的用法,将字符串使用一种合适哈希函数映射到不同的bit位上(2^32足够的大,可以满足需求)
使用 bitmap 实现用户上线次数统计、统计活跃用户
假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT 和 BITCOUNT 来实现。
比如说,通过将一个用户的id对应value上的一位,通过对活跃用户对应的位进行置位,就能够用一个value记录所有活跃用户的信息。如图bitmap有9个位被置为1,表示这9个位上对应的用户是今天的活跃用户。其中第15位表示uid为15的用户,第一位表示uid为0的用户。(如果你的uid不是从1开始的,比如从100000开始,实际上你也可以相应的用uid减去初始值来表示其位数,比如1000000用户对应到bitmap的第一位)
这里写图片描述
因为日活跃用户每天都变化,所以需要每天创建一个新的bitmap。我们简单地把日期添加到key后面,实现了这个功能。例如,要统计某一天有多少个用户至少听了一个音乐app中的一首歌曲,可以把这个bitmap的redis key设计
redis.setbit(play:yyyy-mm-dd, user_id, 1)
1
这样一次记录的复杂度是O(1),在Redis中速度非常快。而我们通过每天换用一个不同的key来将每天的活跃用户状态记录分开存。比如我们通过对3天(周一周三周四)的活跃用户记录取AND操作,就能得出这3天都活跃的用户列表。
这里写图片描述
通过上图中的测试样例可以发现:
节约空间,统计一亿人每天的登录情况,用一亿bit,约1200WByte,约10M的字符就能表示(因为bitop命令的返回值是保存到 time中的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。即1亿除以8bit=1250万Byte);
计算方便。
性能:
如果你的 bitmap 数据非常大,那么可以考虑使用以下两种方法:
● 将一个大的 bitmap 分散到不同的 key 中,作为小的 bitmap 来处理。使用 Lua 脚本可以很方便地完成这一工作。
● 使用 BITCOUNT 的 start 和 end 参数,每次只对所需的部分位进行计算,将位的累积工作(accumulating)放到客户端进行,并且对结果进行缓存 (caching)。
何时使用:
如果活跃用户在百万级别,使用Redis BitMap很划算。
如果活跃用户很少,而用户id都是10位以上的int。那就很浪费内存了,还不如使用set集合,然后求交集就可以了。
5、分布式缓存Redis之bitmap、setbit的更多相关文章
- 一个技术汪的开源梦 —— 公共组件缓存之分布式缓存 Redis 实现篇
Redis 安装 & 配置 本测试环境将在 CentOS 7 x64 上安装最新版本的 Redis. 1. 运行以下命令安装 Redis $ wget http://download.redi ...
- 企业项目开发--分布式缓存Redis
第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis ...
- .NET分布式缓存Redis从入门到实战
一.课程介绍 今天阿笨给大家带来一堂NOSQL的课程,本期的主角是Redis.希望大家学完本次分享课程后对redis有一个基本的了解和认识,并且熟悉和掌握 Redis在.NET中的使用. 本次分享课程 ...
- 第十章 企业项目开发--分布式缓存Redis(2)
注意:本章代码是在上一章的基础上进行添加修改,上一章链接<第九章 企业项目开发--分布式缓存Redis(1)> 上一章说了ShardedJedisPool的创建过程,以及redis五种数据 ...
- 三点须知:当我们在开发过程中需要用到分布式缓存Redis的时候
当我们在开发过程中需要用到分布式缓存Redis的时候,我们首先要明白缓存在系统中用来做什么? 1. 少量数据存储,高速读写访问.通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的 ...
- 分布式缓存Redis应用场景解析
Redis的应用场景非常广泛.虽然Redis是一个key-value的内存数据库,但在实际场景中,Redis经常被作为缓存来使用,如面对数据高并发的读写.海量数据的读写等. 举个例子,A网站首页一天有 ...
- ASP.Net Core使用分布式缓存Redis从入门到实战演练
一.课程介绍 人生苦短,我用.NET Core!缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力. 所以经常要用到且不会频繁改变且被用户共享的 ...
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_37、分布式缓存Redis介绍
笔记 1.分布式缓存Redis介绍 简介:讲解为什么要用缓存和介绍什么是Redis,新手练习工具 1.redis官网 https://redis.io/download ...
- 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
随机推荐
- Excel 常用属性的一小部分
1.由于工作需要,最近积累了一些Excel中的相关知识,特此记录 Workbooks xlbooks = xlApp.Workbooks; Workbook xlbook = xlbooks.Add( ...
- 大数据 - hadoop三台linux虚拟服务器 - 初始化部署
搭建hadoop环境 1.解压Hadoop的安装包,解压到modules文件夹中.(安装包下载地址:http://archive.apache.org/dist/hadoop/core/hadoop- ...
- Python--错误SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
Refer to:https://www.cnblogs.com/cyiner/archive/2011/09/18/2180729.html 用Python打开文件: fo=open("C ...
- Python 安装第三方库中常见问题总结
1.安装某个库时,例如 pip install tinify 出现Permission denied时,在安装命令的最前面添加sudo 例如: sudo pip install tinify 即可. ...
- SpringJPA主键生成采用自定义ID,自定义ID采用年月日时间格式
自定义主键生成策略 在entity类上添加注解 @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "custom ...
- [转]如何正确学习JavaScript
原文:How to Learn JavaScript Properly(2014-2-7) 学习时长:6-8周 学习前提:中学水平,无需编程经验 更新(2014-1-7) 在Reddit上创建了一个学 ...
- TrustManagerService.java
/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Versi ...
- Git入门(安装及基础命令行操作)
一.安装 1.Mac 在Mac中安装Git的方法不止一种.最简单的要数通过Xcode命令行工具.对于Mavericks(10.9)或更高版本的操作系统,当你第一次尝试在终端执行git命令时,系统会自动 ...
- vue 数字随机滚动(数字递增)
html: <span v-for="i in numArr">{{i}}</span> data: numArr: [], methods: perN ...
- 1.YAF 的安装
1.环境 UBUNTU16.04 PHP7.0 2.安装 2.1先安装PHPIZE sudo apt install php7.0-dev 2.2 A;下载源码包 并解压 安装 sudo w ...