什么是位图

位图bitmap是通过一个bit来表示某个元素对应的值或者状态,是由一组bit位组成,每个bit位对应0和1两个状态,虽然内部还是采用string类型进行存储,但是redis提供了直接操作位图的指令,可以把他看作是一个bit数组,数组的下标就是偏移量。

常用命令介绍

一、SETBIT key offset value

可用版本:>=2.20

时间复杂度:O(1)

作用

key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。

位的设置或清除取决于 value 参数,可以是 0 也可以是 1

key 不存在时,自动生成一个新的字符串值。

字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。

offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。

返回值

原来储存的位

示例

# 在key值为bitkey的偏移量0处,设置值为1
redis> setbit bitkey 0 1
# 返回原存储的值
(integer) 0
# 在key值为bitkey的偏移量0处,设置值为1
redis> setbit bitkey 0 0
# 返回原存储的值
(integer) 1

二、GETBIT key offset

可用版本:>=2.2.0

时间复杂度:O(1)

作用

key 所储存的字符串值,获取指定偏移量上的位(bit)。

offset 比字符串值的长度大,或者 key 不存在时,返回 0

返回值

字符串值指定偏移量上的位

示例

# 不存在的key
redis>getbit bitkey_0
(integer) 0
reids>setbit bitkey_0 0 0
(integer) 1
# 超过默认的偏移量(没有grown)
redis>getbit bitkey_0 10000
(integer) 0
redis>getbit bitkey_0 0
(integer) 1

三、 BITCOUNT key [start] [end]

可用版本:>=2.6.0

时间复杂度:O(N)

作用

计算给定字符串中,被设置为 1 的比特位的数量。

一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。

start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。

不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。

示例

redis>setbit key_count 0 1
(integer) 0
redis>setbit key_count 1 1
(integer) 0
redis>setbit key_count 2 0
(integer) 0
redis>bitcount key_count
(integer) 2

四、BITPOS key bit [start] [end]

可用版本:>= 2.8.7

时间复杂度:O(N),其中N为位图包含的二进制位数量

作用

返回位图中第一个值为bit的二进制的位置

在默认情况下,命令将检测整个位图,但用户也可以通过start和end参数来指定要检测的范围

返回值

整数返回

示例

redis>setbit key_pos 2 1
(integer) 0
redis>bitpos key_pos 0
(integer) 0
redis>bitpos key_pos 1
(integer) 2

五、BITOP operation destkey key [key …]

可用版本:>=2.6.0

时间复杂度:O(N)

作用

对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

operation 可以是 ANDORNOTXOR 这四种操作中的任意一种:

  • BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey
  • BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey
  • BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey
  • BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey

    除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。

返回值

保存到 destkey 的字符串的长度,和输入 key 中最长的字符串长度相等。

示例

# 先保存几组
# key_1:1001 key_2:1011
redis> setbit key_1 0 1
(integer) 0
redis> setbit key_1 3 1
(integer) 0
redis> setbit key_2 0 1
(integer) 0
reids> setbit key_2 2 1
(integer) 0
reids> setbit key_2 3 1
(integer) 0
# AND key求逻辑并
redis> bitop and key_and key_1 key_2 # 结果将是1001
(integer) 1
# OR key求逻辑或
redis> bitop or key_or key_1 key_2 # 1011
(integer) 1
# XOR key求逻辑异或
redis> bitop xor key_xor key_1 key_2 # 0100
(integer) 1
# NOT key求逻辑非
redis> bitop not key_not key_1 # 0110
(integer) 1

六、BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

可用版本:>= 3.2.0

时间复杂度:每个子命令的复杂度为 O(1)

作用

一次对多个位范围进行操作。bitfield 有三个子指令,分别是 get/set/incrby。每个指令都可以对指定片段做操作。

返回值

返回一个数组作为回复, 数组中的每个元素就是对应操作的执行结果。

案例

# 从第1位开始取4位,设值为5(有符号数)
redis> BITFIELD key SET i4 0 5
1) (integer) 0 # 从第1位开始取4位,结果为有符号数
redis> BITFIELD key GET i4 0
1) (integer) 5 # 从第1位取4位,结果为有符号数
# 从第5位取4位,设值为6,结果为无符号数
# 从第5位去4位,值增加1,结果为无符号数
redis> BITFIELD key GET i4 0 SET u4 4 6 INCRBY u4 4 1
1) (integer) 5
2) (integer) 0
3) (integer) 7

BITFIELD还提供了三种溢出策略:

  • WRAP(wrap around,回绕)。一个i8的整数,值为127,递增1会导致值变为-128;
  • SAT(saturation arithmetic,饱和计算)。一个i8的整数,值为120,递增10结果变为127(i8 类型所能储存的最大整数值);
  • FAIL。 发生溢出时,操作失败。并返回空值表示计算未被执行。
redis> BITFIELD tian_key SET i8 0 127 OVERFLOW WRAP INCRBY i8 0 1
1) (integer) 0
2) (integer) -128
redis> BITFIELD tian_key_2 SET i8 0 120 OVERFLOW SAT INCRBY i8 0 10
1) (integer) 0
2) (integer) 127
redis> BITFIELD tian_key_3 SET i8 0 127 OVERFLOW FAIL INCRBY i8 0 1
1) (integer) 0
2) (nil)

Redis学习与应用-位图的更多相关文章

  1. Redis学习笔记之位图

    目录 位图定义 应用场景 基本使用 查找统计 位图定义 位图并不是一种数据结构,其实就是一种普通的字符串,也可以说是byte数组.基本语法是setbit/getbit,刚才说了是一个byte数组,所以 ...

  2. redis 学习(1)-- redis 安装与启动

    redis 学习(1)-- redis 安装与启动 redis 特性 关于 redis 的介绍网上已经有很多信息了,这里我就不在详细说明了.介绍一下几个鲜明特性: 1.速度快 官方称可以达到10W的q ...

  3. Redis学习手册(目录)

    为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...

  4. redis 学习笔记(6)-cluster集群搭建

    上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...

  5. Redis——学习之路四(初识主从配置)

    首先我们配置一台master服务器,两台slave服务器.master服务器配置就是默认配置 端口为6379,添加就一个密码CeshiPassword,然后启动master服务器. 两台slave服务 ...

  6. Redis——学习之路三(初识redis config配置)

    我们先看看config 默认情况下系统是怎么配置的.在命令行中输入 config get *(如图) 默认情况下有61配置信息,每一个命令占两行,第一行为配置名称信息,第二行为配置的具体信息.     ...

  7. Redis——学习之路二(初识redis服务器命令)

    上一章我们已经知道了如果启动redis服务器,现在我们来学习一下,以及如何用客户端连接服务器.接下来我们来学习一下查看操作服务器的命令. 服务器命令: 1.info——当前redis服务器信息   s ...

  8. Redis学习笔记~目录

    回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...

  9. Redis学习笔记4-Redis配置详解

    在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...

随机推荐

  1. ajax的封装——jq简化版

    最近在复习ajax的知识,练习了下ajax的封装,此处做下笔记 废话不多说,直接代码 //发请求 //此处的url为请求地址,type为请求方式,success为请求成功的回调函数 myaxios({ ...

  2. Linux虚拟机-CentOS7常用命令

    1.查找虚拟机的ip地址:$ ifconfig ~inet 192.168.68.136

  3. Java刷题知识点总结

    1,方法的重写(override)两同两小一大原则: 方法名相同,参数类型相同 子类返回类型小于等于父类方法返回类型, 子类抛出异常小于等于父类方法抛出异常, 子类访问权限大于等于父类方法访问权限. ...

  4. js之for与forEach循环的区别

    回武汉打卡第四天,武汉加油,逆战必胜!今天咱们探讨一下for循环和forEach()循环的区别. 首先,for循环在最开始执行循环的时候,会建立一个循环变量i,之后每次循环都是操作这个变量,也就是说它 ...

  5. js定时器及定时器叠加问题

    回武汉隔离的第二天打卡,武汉加油,逆战必胜!今天想和大家简单聊一下js定时器的问题. 1.setTimeout 延时器 在指定时间后执行一次,注意只会执行一次 当然有的时候我们想用延时器做出定时器的效 ...

  6. D - Super Jumping! Jumping! Jumping!

    Nowadays, a kind of chess game called "Super Jumping! Jumping! Jumping!" is very popular i ...

  7. Vertica的这些事(八)——-Vertica-管理

    1.版本信息 dbadmin=> SELECT version(); version ------------------------------------ Vertica Analytic ...

  8. 并发——抽象队列同步器AQS的实现原理

    一.前言   这段时间在研究Java并发相关的内容,一段时间下来算是小有收获了.ReentrantLock是Java并发中的重要部分,所以也是我的首要研究对象,在学习它的过程中,我发现它是基于抽象队列 ...

  9. Light of future-凡事预则立

    目录 1.冲刺的时间计划安排 2.针对上一次作业同学.助教提出的问题的回答 3.针对前几次作业的不足的地方进行思考和总结 4.需要改进的团队分工 5.团队的代码规范 6.Github仓库链接 归属班级 ...

  10. C++动态内存new和delete(超详细)

    C++动态内存new和delete C++动态内存是C++灵活.炫酷的一种操作.学好它,能让自己编程逼格上一个level. 在学习动态内存之前,我们先要了解C++是怎么划分内存的: 栈:在函数内部声明 ...