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集合,然后求交集就可以了。

原文地址:https://www.cnblogs.com/Pibaosi/p/10583256.html

时间: 2024-10-19 23:46:52

5、分布式缓存Redis之bitmap、setbit的相关文章

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

第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis 1.1.为什么用分布式缓存(或者说本地缓存存在的问题)? 见<第八章 企业项目开发--分布式缓存memcached> 1.2.有了memcached,为什么还要用redis? 见<第一章 常用的缓存技术> 2.代码实现 2.1.ssmm0 pom.xml 只在dev环境下添加了以下代码

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

注意:本章代码是在上一章的基础上进行添加修改,上一章链接<第九章 企业项目开发--分布式缓存Redis(1)> 上一章说了ShardedJedisPool的创建过程,以及redis五种数据结构的第一种String类型的常用缓存操作方法.下面说余下的四种: list(有序列表) set(无序集合) sorted set(有序集合) hash 1.ssmm0-cache 1.1.RedisListUtil(有序列表工具类) 1 package com.xxx.cache.redis; 2 3 im

分布式缓存Redis Centos下单节点安装

摘要: Redis官网:http://redis.io 独立缓存服务器:IP:xxx.xxx.xxx.xxx 安装环境:CentOS 6.6 Redis 版本:redis-3.0 (因为 Redis3.0 在集群和性能提升方面的特性,rc 版为正式版的候选版,请在安装时去官网选用最新版) 用户:root 安装目录:/usr/local/redis 声明: 网上关于分布式缓存Redis的学习资料很多,大家可以去网上找些资料去学习.另外 JEESZ框架面向企业的大型互联网分布式企业架构,分布式缓存是

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

一.课程介绍 今天阿笨给大家带来一堂NOSQL的课程,本期的主角是Redis.希望大家学完本次分享课程后对redis有一个基本的了解和认识,并且熟悉和掌握 Redis在.NET中的使用.本次分享课程包含以下知识点: 1.StackExchange.Redis (简称:SE)驱动在C#中Redis几种数据结构学习和使用. 2.ServiceStack.Redis ( 简称: SS) 驱动在C#中Redis几种数据结构学习和使用. 3.Redis主从集群服务器搭建和学习. 4.在ASP.NET中Re

分布式缓存Redis

分布式缓存Redis参考文档http://doc.redisfans.com#######################################################Memcache与Redis对比 Memcached Redis不支持持久化 持久化纯set get性能好 不如memcached开发都会用 开发都知道简单易用 易用支持类型单一 支持多种数据类型依赖magent 集群没有验证 有基础验证session 购物车(登录前方cookis,等于后写入)tomcat-se

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

Redis的应用场景非常广泛.虽然Redis是一个key-value的内存数据库,但在实际场景中,Redis经常被作为缓存来使用,如面对数据高并发的读写.海量数据的读写等.举个例子,A网站首页一天有100万人访问,其中有一个"积分商城"的板块,要直接从数据库查询,那么一天就要多消耗100万次数据库请求.如果将这些数据储存到Redis(内存)中,要用的时候,直接从内存调取,不仅可以大大节省系统直接读取磁盘来获得数据的IO开销,提高服务器的资源利用率,还能极大地提升速度.随着日益增长的用户

C# Azure 分布式缓存Redis的新建与配置

1. 介绍 Redis 是一款开源的,基于 BSD 许可的,高级键值 (key-value) 缓存 (cache) 和存储 (store) 系统.由于 Redis 的键包括 string,hash,list,set,sorted set,bitmap 和 hyperloglog,所以常常被称为数据结构服务器.你可以在这些类型上面运行原子操作,例如,追加字符串,增加哈希中的值,加入一个元素到列表,计算集合的交集.并集和差集,或者是从有序集合中获取最高排名的元素. 为了满足高性能,Redis 采用内

分布式缓存Redis使用心得

一.缓存在系统中用来做什么 1. 少量数据存储,高速读写访问.通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景. 2. 海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除.Redis3.0以后开始支持集群,实现了半自动化的数据分片,不过需要smart-client的支持. 二.从不同的角度来详细介绍redis 网络模型:Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现

第九章 企业项目开发--分布式缓存Redis(1)

注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis 1.1.为什么用分布式缓存(或者说本地缓存存在的问题)? 见<第八章 企业项目开发--分布式缓存memcached> 1.2.有了memcached,为什么还要用redis? 见<第一章 常用的缓存技术> 2.代码实现 2.1.ssmm0 pom.xml 只在dev环境下添加了以下代码: <!-- redis:多台服务器支架用什么