redis位图命令
Posted float123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis位图命令相关的知识,希望对你有一定的参考价值。
概述
redis 的位图就是01的数据格式,redis 主要做有写入,读取和统计。位图相关的命令 :
其中set和get就是 read 和writer , bitcount 统计相关,bitop 是对bit进行操作01的,bitpos 获取某个范围内第一个值为 bit 的位置;bitfield 则是批量操作的命令
例子
写入的过程如下,以下是一个例子(来自参考资料)
127.0.0.1:6379> setbit s 1 1 (integer) 0 127.0.0.1:6379> setbit s 2 1 (integer) 0 127.0.0.1:6379> setbit s 4 1 (integer) 0 127.0.0.1:6379> setbit s 9 1 (integer) 0 127.0.0.1:6379> setbit s 10 1 (integer) 0 127.0.0.1:6379> setbit s 13 1 (integer) 0 127.0.0.1:6379> setbit s 15 1 (integer) 0 127.0.0.1:6379> get s "he"
read 和 write
127.0.0.1:6379> setbit w 1 1 (integer) 0
127.0.0.1:6379> getbit w 2 (integer) 1
统计和查找
统计和查找用到两个命令。
- bitcount : bitcount 用来统计指定位置范围内 1 的个数
- bitpos : 用来查找指定范围内出现的第一个 0 或 1,命令格式 : bitpos key bit [start] [end]
例子来自于参考资料
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitcount w (integer) 21 127.0.0.1:6379> bitcount w 0 0 # 第一个字符中 1 的位数 (integer) 3 127.0.0.1:6379> bitcount w 0 1 # 前两个字符中 1 的位数 (integer) 7 127.0.0.1:6379> bitpos w 0 # 第一个 0 位 (integer) 0 127.0.0.1:6379> bitpos w 1 # 第一个 1 位 (integer) 1 127.0.0.1:6379> bitpos w 1 1 1 # 从第二个字符算起,第一个 1 位 (integer) 9 127.0.0.1:6379> bitpos w 1 2 2 # 从第三个字符算起,第一个 1 位 (integer) 17
bitfield 命令
bitfield 用来作为批量写入或是读取。来自参考资料 bitfield 有三个子指令,分别是get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理 64 个连续的位,如果超过 64 位,就得使用多个子指令,bitfield 可以一次执行多个子指令。
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitfield w get u4 0 # 从第一个位开始取 4 个位,结果是无符号数 (u) (integer) 6 127.0.0.1:6379> bitfield w get u3 2 # 从第三个位开始取 3 个位,结果是无符号数 (u) (integer) 5 127.0.0.1:6379> bitfield w get i4 0 # 从第一个位开始取 4 个位,结果是有符号数 (i) 1) (integer) 6 127.0.0.1:6379> bitfield w get i3 2 # 从第三个位开始取 3 个位,结果是有符号数 (i) 1) (integer) -3
所谓有符号数是指获取的位数组中第一个位是符号位,剩下的才是值。如果第一位是1,那就是负数。无符号数表示非负数,没有符号位,获取的位数组全部都是值。有符号数最多可以获取 64 位,无符号数只能获取 63 位 (因为 Redis 协议中的 integer 是有符号数,最大 64 位,不能传递 64 位无符号值)。如果超出位数限制,Redis 就会告诉你参数错误。
补充
项目中使用了 RedisTemplate ,因为像 bitcount 命令是 spring-data-redis 新版本在代码中才集成的,那么怎么办呢?可以执行脚本的方式来执行该命令。
private static final String USER_READ_EVL = "return redis.call(\'bitcount\',KEYS[1])"; /** * 获取用户已读的进度 */ private Long getUserReadIndex(String userReadKey, Long userId) { List<String> keys = new ArrayList<>(); keys.add(userReadKey); List<String> args = new ArrayList<>(); RedisCallback<Long> callback = (connection) -> { Object nativeConnection = connection.getNativeConnection(); // 集群模式 if (nativeConnection instanceof JedisCluster) { return (Long) ((JedisCluster) nativeConnection).eval(USER_READ_EVL, keys, args); } // 单机模式 else if (nativeConnection instanceof Jedis) { return (Long) ((Jedis) nativeConnection).eval(USER_READ_EVL, keys, args); } return 0L; }; //key没创建的情况是 0 return mRedisTemplate.execute(callback); }
参考资料 :
- https://www.cnblogs.com/wuwuyong/p/11739495.html (推荐一看)
- https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis
- https://redis.io/commands/bitfield
- http://redisdoc.com/bitmap/bitfield.html (中文文档,推荐一看)
以上是关于redis位图命令的主要内容,如果未能解决你的问题,请参考以下文章
Redis 基础 -- 位图(bitmap)数据结构和 bitmap的常用命令(SETBITGETBITBITCOUNTBITPOSBITOPBITFIELD)