游戏开发工具

bitfield 类型

上一节:geospatial地理位置下一节:Stream 类型

bitfield命令

redis3.2后新增了一个bitfield命令,可以一次对多个位进行操作.这个指令有三个子指令,get,set,incrby,都可以对指定位片段进行读写,但最多只能处理64个连续的位,如超过64位,则要使用多个子指令,bitfield可以一次执行多个子指令。

Redis位字段允许您设置、递增和获取任意位长度的整数值。例如,您可以操作无符号1位整数到有符号63位整数的任何整数。

这些值是使用二进制编码的Redis字符串存储的。位字段支持原子读、写和增量操作,是管理计数器和类似数值的好选择。

127.0.0.1:6379> set w hello
OK


以上代码存储的位数据为:

字母数值二进制(高位<-低位)
h1040110 1000 
e1010110 0101
l1080110 1100
l1080110 1100
o1110110 1111
127.0.0.1:6379> bitfield w get u4 0    #从w的第一个位开始取4个位(0110),结果为无符号数(u)
1) (integer) 6
127.0.0.1:6379> bitfield w get u3 2    #从w的第三个位开始取3个位(101),结果为无符号数(u)
1) (integer) 5
127.0.0.1:6379> bitfield w get i4 0   #从w的第一个位开始取4个位(0110),结果为有符号数(i)
1) (integer) 6
127.0.0.1:6379> bitfield w get i3 2   #从w的第三个位开始取3个位(101),结果为有符号数(i)
1) (integer) -3


从上可知,有符号数最多可以取64位,无符号数只能取63位.( redis 协议中的integer是有符号数,最大64位).

也可以一次执行多个子指令:

127.0.0.1:6379> bitfield w get u4 0 get u3 2 get i4 0 get i3 2
1) (integer) 6
2) (integer) 5
3) (integer) 6
4) (integer) -3


也可以用set修改字符:

127.0.0.1:6379> bitfield w set u8 8 97  #从第9个位开始,将接下来8个位用无符号数97 ( 字母a) 替换
1) (integer) 101
127.0.0.1:6379> get w
"hallo"


incrby对指定范围的位进行自增操作,如操作后有数据溢出,redis的处理是折返,即将益处的符号位丢掉,比如:8位的无符号数255,加1后变为0,而8位的有符号数127,加1后成-128.

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w incrby u4 2 1 #从第3个位开始,对接下来的4位无符号数+1
1) (integer) 11
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield w incrby u4 2 1 #溢出折返了
1) (integer) 0


也可以选择溢出行为,还可以选择 失败(fail,报错不执行), 折返( wrap ), 饱和截断(sat, 超过了范围就停留在最大或最小值). 

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 11
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1  #保持了最大值


bitfield类型使用

1、bitfield key [get type offset]

127.0.0.1:6379> get k1
"hello"
127.0.0.1:6379> bitfield k1 get i8 0
1) (integer) 104
127.0.0.1:6379> bitfield k1 get i8 8
1) (integer) 101
127.0.0.1:6379> bitfield k1 get i8 16
1) (integer) 108

 

2、bitfield key [set type offset value]

127.0.0.1:6379> get k1
"hello"
127.0.0.1:6379> bitfield k1 set i8 8 120
1) (integer) 101
127.0.0.1:6379> get k1
"hxllo"


3、bitfield key [incrby type offset increment]

127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 11
127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield k1 incrby u4 2 1
1) (integer) 0


 这里默认incrby使用wrap参数


4、overflow[wrap][sat][fall]

wrap:使用回绕(wrap around)方法处理有符号整数和无符号整数的溢出情况。

sat:使用饱和计算(saturation arithmetic)方法处理溢出,下溢计算结果为最小的整数值,而上溢计算的结果为最大的整数值。

127.0.0.1:6379> bitfield k1 overflow sat set i8 0 145
1) (integer) -122
127.0.0.1:6379> bitfield k1 get i8 0 
1) (integer) 127

fail:命令将拒绝执行那些会导致上溢或下溢情况出现的计算,并向用户返回空值表示计算未被执行。

 127.0.0.1:6379> bitfield k1 overflow fail set i8 0 230
1) (nil)


例子

假设你正在跟踪一个网络游戏中的活动。你需要为每个玩家保留两个关键的指标:黄金总量和被杀死的怪物数量。因为你的游戏很容易上瘾,所以这些计数器应该至少有32位宽。

您可以为每个玩家用一个位字段来表示这些计数器。

1、新玩家以1000黄金开始(计数器偏移量为0)

> BITFIELD player:1:stats SET u32 #0 1000
1) (integer) 0


2、杀死俘虏王子的妖精后,加上赚取的50黄金,并增加“被杀”计数器(偏移1)

> BITFIELD player:1:stats INCRBY u32 #0 50 INCRBY u32 #1 1
1) (integer) 1050
2) (integer) 1


3、付给铁匠999黄金,买一把传说中的锈迹斑斑的匕首

> BITFIELD player:1:stats INCRBY u32 #0 -999
1) (integer) 51


4、获取玩家的统计数据

> BITFIELD player:1:stats GET u32 #0 GET u32 #1
1) (integer) 51
2) (integer) 1


基本命令

BITFIELD以原子方式设置、递增和读取一个或多个值。

BITFIELD_RO是BITFIELD的只读变体。

性能

BITFIELD复杂度是O(n),其中n是访问的计数器数。



上一节:geospatial地理位置下一节:Stream 类型