上次说到Redis5提供六种数据类型来存储值:string字符串类型
、hash散列类型
、list列表类型
、set集合类型
、zset(SortedSet)有序集合类型
、stream流类型
。现在把这几种类型具体分析一下。
1. Redis的key
redis的key 值是二进制安全的(一种主要用于字符串操作函数相关的计算机编程术语),这意味着可以用任何二进制序列作为key值,从形如name
的简单字符串到一个JPEG文件的内容都可以,空字符串也是有效key值。redis建议使用字符串做为key的类型。key取值规范如下:
- 键值不需要太长,消耗内存,在数据中查找这类键值的计算成本较高
- 键值不宜过短,可读性较差,通常建议见名知意
2. string字符串
一种最基本的Redis值类型(字节数组)。Redis字符串是二进制安全的,一个Redis字符串能包含任意类型的数据。例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。一个字符串类型的值最多能存储512M字节的内容。
2.1 赋值 set
set key value
set name 张三
set name 张三 ex 10 # EX 设置过期时间,秒,等同于SETEX key seconds value
set name 张三 px 5000 # pX 设置过期时间,秒,等同于SETpX key seconds value
set name 张三 nx # name 不存在时,才能写入,等同于SETNX key value
set name 张三 xx # name 存在时,才能写入
mset name 张三 age 18 phone 1888888888 # 设置多个key-value键值对
msetnx name 张三 age 18 phone 1888888888 # 设置多个key-value键值对,原子操作,有一个不成功都不成功
2.2 取值 get
get key
127.0.0.1:6379> get name
张三
127.0.0.1:6379> mget name age phone
张三
18
1888888888
2.3 返回旧值并设置新值 getset
getset key value
127.0.0.1:6379> getset phone 16666666666
1888888888
2.4 向尾部追加值 append
APPEND key value
127.0.0.1:6379> append name 李四
12 # 返回值是追加后字符串的总长度
127.0.0.1:6379> get name
张三李四
127.0.0.1:6379>
2.5 字符串长度 strlen
strlen key
127.0.0.1:6379> strlen name
12
127.0.0.1:6379> strlen phone
11
127.0.0.1:6379>
2.6 数值增减
字符串值会被解释成64位有符号的十进制整数来操作,但输出结果依然转成字符串。string类型的,底层实现是int,实际上操作的还是数字。
- incr
127.0.0.1:6379> set id 1
OK
127.0.0.1:6379> incr id
2
127.0.0.1:6379> get id
2
127.0.0.1:6379> incr id
3
127.0.0.1:6379>
- incrby 增加指定的整数
127.0.0.1:6379> incrby id 3
6
127.0.0.1:6379> incrby id 2
8
127.0.0.1:6379>
- decr
127.0.0.1:6379> decr id
7
127.0.0.1:6379>
- decrby 减少指定的整数
127.0.0.1:6379> decrby id 2
5
127.0.0.1:6379>
注意事项:
- 当value为整数数据时,才能使用以下命令操作数值的增减
- 数值递增都是原子操作
- 可以做订单、商品的自增主键
2.7 截取字符串
getrange key start end
索引值从0开始,负数表示从字符串右边向左数起,-1表示最右一个字符,负号减轻复杂度。
127.0.0.1:6379> getrange name 0 -1 # 从开始到结尾
张三李四
127.0.0.1:6379> getrange phone 0 2
166
127.0.0.1:6379>
2.8 替换字符串
setrange key offset value
127.0.0.1:6379> setrange phone 2 x
11
127.0.0.1:6379> get phone
16x66666666
127.0.0.1:6379> setrange phone 3 ****
11
127.0.0.1:6379> get phone
16x****6666
127.0.0.1:6379>
2.9 位图bitmap - 字节数组
位图不是真正的数据类型,它是定义在字符串类型中的
- 赋值 setbit getbit
127.0.0.1:6379[1]> setbit k1 1 1 # 将二进制数向右偏移1位,并将此位的0设为1
(integer) 0
127.0.0.1:6379[1]> get k1
"@" # 二进制 0 1 0 0 0 0 0 0 对应的ASCII码是@
127.0.0.1:6379[1]>setbit k1 9 1
(integer) 0
127.0.0.1:6379[1]> get k1
"@@" # 二进制 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0对应的2个字节:8bit(位)= 1Byte(字节)
127.0.0.1:6379[1]> getbit k1 1
(integer) 1
127.0.0.1:6379[1]> getbit k1 2
(integer) 0
127.0.0.1:6379[1]> bitpos k1 1 # 查找 1 在k1中第一次出现的位置
(integer) 1
127.0.0.1:6379[1]> bitpos k1 0 # 查找 0 在k1中第一次出现的位置
(integer) 0
127.0.0.1:6379[1]> bitpos k1 1 0 # 查找 1 在k1的第1个字节中第一次出现的位置,注意最后的0表示下标是0的字节,现在k1只有2个字节(下标0、1),16位长度
(integer) 1
127.0.0.1:6379[1]> bitpos k1 1 1 # 查找 1 在k1的第2个字节中第一次出现的位置,注意最后的1表示下标是1的字节,现在k1只有2个字节(下标0、1),16位长度
(integer) 9
127.0.0.1:6379[1]>
- 位运算
127.0.0.1:6379[1]> setbit k2 1 1
(integer) 0
127.0.0.1:6379[1]> bitop and res1 k1 k2 # k1和k2二进制的逻辑与,结果保存到res1
(integer) 2
127.0.0.1:6379[1]> get res1
@
127.0.0.1:6379> bitop or res2 k1 k2 # k1和k2二进制的逻辑或,结果保存到res2
2
127.0.0.1:6379> get res2
A@
127.0.0.1:6379> bitop xor res3 k1 k2 # k1和k2二进制的逻辑异或,结果保存到res3
2
127.0.0.1:6379> get res3
@
127.0.0.1:6379> bitop not res4 k1 # k1二进制的逻辑非,结果保存到res4
2
127.0.0.1:6379>
注意:除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入,当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0,空的 key 也被看作是包含 0 的字符串序列
- 计数 BITCOUNT
统计二进制中1的个数
127.0.0.1:6379> bitcount k1 0 0 # 注意 0 0表示是字节下标从0到0的范围,也就是第1个字节(8位)中1的个数
2
127.0.0.1:6379> bitcount k1 0 1 # 表示下标0、1这2个字节中1的个数
3
127.0.0.1:6379> bitcount k1 1 1 #表示下标为1这个字节中1的个数
1
127.0.0.1:6379>
- bitmap应用
- 统计用户的活跃天数
用户ID为key,天作为offset,上线置为1
366天,1字节可以统计8天,只需46字节即可统计全年活跃天数
例:id为38的用户第15天上线:setbit id38 14 1
统计天数用:bitcount id38 0 -1
- 统计每天的活跃用户
日期作为key,用户ID为offset,上线置为1
假设1000 0000用户,只需 1250000 字节=1250KB=1.25MB就能统计1天的活跃用户
例:今天 第200个用户上线:setbit 20220315 199 1
若要统计连续3天的,先用bitop做逻辑或,然后再bitcount
- 统计用户的活跃天数
网友评论