基本语法:

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的更多相关文章

  1. 一个技术汪的开源梦 —— 公共组件缓存之分布式缓存 Redis 实现篇

    Redis 安装 & 配置 本测试环境将在 CentOS 7 x64 上安装最新版本的 Redis. 1. 运行以下命令安装 Redis $ wget http://download.redi ...

  2. 企业项目开发--分布式缓存Redis

    第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis ...

  3. .NET分布式缓存Redis从入门到实战

    一.课程介绍 今天阿笨给大家带来一堂NOSQL的课程,本期的主角是Redis.希望大家学完本次分享课程后对redis有一个基本的了解和认识,并且熟悉和掌握 Redis在.NET中的使用. 本次分享课程 ...

  4. 第十章 企业项目开发--分布式缓存Redis(2)

    注意:本章代码是在上一章的基础上进行添加修改,上一章链接<第九章 企业项目开发--分布式缓存Redis(1)> 上一章说了ShardedJedisPool的创建过程,以及redis五种数据 ...

  5. 三点须知:当我们在开发过程中需要用到分布式缓存Redis的时候

    当我们在开发过程中需要用到分布式缓存Redis的时候,我们首先要明白缓存在系统中用来做什么? 1. 少量数据存储,高速读写访问.通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的 ...

  6. 分布式缓存Redis应用场景解析

    Redis的应用场景非常广泛.虽然Redis是一个key-value的内存数据库,但在实际场景中,Redis经常被作为缓存来使用,如面对数据高并发的读写.海量数据的读写等. 举个例子,A网站首页一天有 ...

  7. ASP.Net Core使用分布式缓存Redis从入门到实战演练

    一.课程介绍 人生苦短,我用.NET Core!缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力.  所以经常要用到且不会频繁改变且被用户共享的 ...

  8. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_37、分布式缓存Redis介绍

    笔记 1.分布式缓存Redis介绍      简介:讲解为什么要用缓存和介绍什么是Redis,新手练习工具          1.redis官网 https://redis.io/download   ...

  9. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

随机推荐

  1. 最新版本汉化-PowerDesigner 16.6 汉化并河蟹

    更新日志: 2019-03-14 V1.1 1.支持反复多次汉化: 2.修复少许bug. 最新的16.6版本已经在汉化中了,基本上所有的菜单均已汉化完成,部分窗体还没有编译通过. 不过,不影响尝鲜使用 ...

  2. Delphi7连接MySql数据库-DBGrid控件显示数据

    一个简单的Delphi7小程序,使用MySql数据库做简单查询,用DBGrid控件显示结果,实现过程如下: (1)在MySql中新建demouser表,插入记录用于测试. (2)在Delphi7中新建 ...

  3. [C# 基础知识系列]专题七: 泛型深入理解(一) (转载)

    引言: 在上一个专题中介绍了C#2.0 中引入泛型的原因以及有了泛型后所带来的好处,然而上一专题相当于是介绍了泛型的一些基本知识的,对于泛型的性能为什么会比非泛型的性能高却没有给出理由,所以在这个专题 ...

  4. 使用vue-cli搭建项目

    在使用vue-cli搭建项目前提: 1.node.js环境 2.npm镜像 开始. 1.cmd打开命令行, npm install -g vue-cli 进行全局安装  (vue-V可以查看其版本) ...

  5. 关于html2canvas跨域设置

    最近在做js生成图片的功能,因为有的商户logo图片在阿里云oss存储的,所以遇到了跨域的问题.跨域的话可以在服务器端设置header, 跨域的话目前的解决方案是服务端设置,Access-Contro ...

  6. 遇到短信轰炸,别人换ip调你的短信接口怎么办

    前端开发者很容易暴露自己的请求地址和参数,我们都知道,一个h5页面,按 F12 是可以看到页面的源码的,所以经常很多人会利用这一点恶意调取别人的接口. 我们公司出现了好多次短信接口被大量调用,导致一天 ...

  7. hbuilder中的wap2app (将M站快速转换成App的开发框架)使用过程有关原生标题的关闭

    首先,我最近在做有关将M站快速转换成App的项目,在网上看了很多,最终结合同学的推荐,我选择了hbuilder,有关于hbuilder的下载还有具体使用方法,官网都有详细的说明,我就不介绍了,我重点介 ...

  8. SOCKET.IO 的用法 系统API,

    原文:http://www.cnblogs.com/xiezhengcai/p/3956401.html 1. 服务端 io.on('connection',function(socket)); 监听 ...

  9. c# excel xls保存

    public HSSFWorkbook Excel_Export(DataTable query,string title,int[] rowweight,string[] rowtitle) { H ...

  10. servlet_1

    HttpServlet超类在java构建路径中没有找到 https://jingyan.baidu.com/article/6c67b1d69a37a02787bb1ee2.html ======== ...