Redis基础篇17 — bitfield特殊数据类型

bitfield 概述

bitfields(位域):位域是计算机中的术语,也称 位段,它是指信息在存储时,并不需要占用一个完整的字节,而只需占用一个或几个二进制位,这样做的目的是为了节约存储空间。

在 C 编程语言中,除了基本的数据类型(char、short、int、、long、float、double)外,还有一些特殊的数据类型,如下图所示:

Q:结构体是什么?

因为基本的数据类型没办法和现实生活中的对象一 一对应。比如说 student 这个对象,在没有结构体之前,你需要这样定义这个对象的属性:

char name[20];
int age;
float score;

在代码层面,无法知道它们之间的关联性,于是,C 语言提供了一种解决办法——用户自定义需要的任何类型并结合起来的一个整体,即结构体,定义结构体的代码如下:

struct Student
{
        char name[20];
        int age;
        float score;
};

struct 是关键字;Student 是标志(标签),可自定义;包含的则是结构体的三个成员。

数组:相同数据类型的元素按一定顺序排列的集合。在内存当中,数组的元素被保存在一块连续的内存当中。
结构体:不同数据类型的成员组合成的一个整体。理论上来说,结构体的成员被保存在一块连续的内存当中,但是由于编译器的实现不同,为了内存对齐(字节对齐),各个成员之间在内存当中可能会存在「缝隙」。

位域属于一种特殊的结构体,在成员名称后面加上冒号,代码层面形如这样的:

struct Bit
{
        char a:2;
        char b:4;
        char c:2;
};

冒号后面定义成员所占的 bit 数。

众所周知,char 在 C 语言当中需要占用 1 Byte,而在位域当中,成员只需要占用一个或几个 bit。

|<-----     1Byte         ----->|

 --- --- --- --- --- --- --- ---
|   |   |   |   |   |   |   |   |
 --- --- --- --- --- --- --- ---

|<- a ->|

        | <---- b ----> |

                        |<- c ->|

Redis 中的位域

这种数据类型是 string 数据类型的拓展,你可以将一个字符串看作是由 bit 组成的数组,并对数组中的任意偏移进行访问,从而高效地使用内存。

# 比如说,使用 string 数据类型:
192.168.100.3:6379> select 7
OK
192.168.100.3:6379[7]> keys *
(empty array)
192.168.100.3:6379[7]> set k1 hello

Q:如果我要修改 k1 的 value,应该怎么操作?

很简单啊!直接用 set 命令更新已经存在的 key 的值;或者使用 setrange 命令。

192.168.100.3:6379[7]> exists  k1
(integer) 1
192.168.100.3:6379[7]> set k1 HELLO XX
OK
192.168.100.3:6379[7]> get k1
"HELLO"

192.168.100.3:6379[7]> setrange k1 0 hello
(integer) 5
192.168.100.3:6379[7]> get k1
"hello"

string 数据类型的修改是基于字符串或字符这个级别,但是 bitfield 可以将这个级别下调到 bit 级别。

字符 ASCII 码(二进制) ASCII 码(十进制)
h 01101000 104
e 01100101 101
l 01101100 108
l 01101100 108
o 01101111 111

比如我要将 hello 字符串变更为 HELLO,只需要修改相应的 bit 即可:

字符 ASCII 码(二进制) ASCII 码(十进制)
H 01001000 72
E 01000101 69
L 01001100 76
L 01001100 76
O 01001111 79

相关命令

只有一个 bitfiled 命令,但是相关的参数非常多,用法为:

查看

192.168.100.3:6379[7]> get k1
"hello"

# i8 表示有符号的 8 bit,偏移量为 0
## 返回104, 即字符 h
192.168.100.3:6379[7]> bitfield k1 get i8 0
1) (integer) 104

# 返回101, 即字符 e
192.168.100.3:6379[7]> bitfield k1 get i8 8
1) (integer) 101

修改单个字符

# 将 e 字符修改为大写的 E
## 69 即 ASCII 的 E
## 返回的是旧 ASCII 
192.168.100.3:6379[7]> bitfield k1 set i8 8 69
1) (integer) 101
192.168.100.3:6379[7]> get k1
"hEllo"

自增/自减

# 从第二个 bit 开始,兑接下来的 3 个 bit 自增 1,u 表示是无符号的
## 3 bit 无符号,意味着它的范围为 [0,7]
192.168.100.3:6379[7]> bitfield k1 incrby u3 2 1
1) (integer) 6
192.168.100.3:6379[7]> bitfield k1 incrby u3 2 1
1) (integer) 7

# 超过了范围并返回 0,即碰到了向上溢出,默认执行 WARP 行为
192.168.100.3:6379[7]> bitfield k1 incrby u3 2 1
1) (integer) 0
192.168.100.3:6379[7]> get k1
"@Ello"

# 还原为 h
192.168.100.3:6379[7]>  bitfield k1 set i8 0 104
1) (integer) 64
192.168.100.3:6379[7]> get k1
"hEllo"

当碰到向上溢出(overflow)或者向下溢出(underflow)情况时会采取一些行为,也就是所谓的 溢出控制

  • WARP(默认)
  • SAT
  • FAIL

这个 bitfield 基本了解就可以了,因为实际情况下也使用得极少。

用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇