3. redis 十大数据类型
3.1 十大数据类型及命令介绍
3.1.1 redis字符串(String)
- string是redis最基本的类型,一个key对应一个value。
- string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
- string类型是redis最基本的数据类型,一个redis中字符串value最多可以是512M。
-
SET
该
SET
命令支持一组修改其行为的选项:x 1SET key value [NX | XX] [GET] [EX seconds | PX milliseconds |2 EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]
-
EX
秒 --以秒为单位设置指定的过期时间。(秒)127.0.0.1:6379> set k1 v1 ex 10 OK 127.0.0.1:6379> ttl k1 (integer) 8 127.0.0.1:6379> ttl k1 (integer) 7
-
PX
毫秒 --设置指定的过期时间,以毫秒为单位。127.0.0.1:6379> set k1 v1 px 8000 OK 127.0.0.1:6379> ttl k1 (integer) 6
-
EXAT
timestamp-seconds --设置密钥将过期的指定Unix时间,以秒为单位。获得设置指定的Key过期的Unix时间,单位为秒:
System.out.println(Long.toString(System.currentTimeMillis()/1000L))
127.0.0.1:6379> set k1 v1 exat 1681559200 OK 127.0.0.1:6379> ttl k1 (integer) 57 127.0.0.1:6379> ttl k1 (integer) 54
-
PXAT
timestamp-milliseconds --设置密钥将过期的指定Unix时间,以毫秒为单位。 -
NX
--仅在密钥不存在时设置该密钥。 -
XX
--仅在密钥已经存在时设置该密钥。127.0.0.1:6379> set k1 v1 nx OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> set k1 v1 nx (nil) 127.0.0.1:6379> set k1 v1xx xx OK
-
KEEPTTL
--保留与密钥关联的生存时间。127.0.0.1:6379> set k1 v1 ex 60 OK 127.0.0.1:6379> ttl k1 (integer) 58 127.0.0.1:6379> set k1 v1keepttl keepttl OK 127.0.0.1:6379> ttl k1 (integer) 37
-
GET
--返回key处存储的旧字符串,如果key不存在则返回nil。将返回一个错误SET
如果key处存储的值不是字符串,则中止。127.0.0.1:6379> set k1 v1 get "v1xx" 127.0.0.1:6379> get k1 "v1"
-
MSET , MGET , MSETNX
同时设置获取多个键值
mset
,mget
,msetnx
:127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> set k2 v2 OK 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379> mget k1 k2 k3 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379> MSETNX k1 v1 k4 v4 (integer) 0 127.0.0.1:6379> MSETNX k5 v5 k6 v6 (integer) 1 27.0.0.1:6379> mget k1 k2 k3 k5 1) "v1" 2) "v2" 3) "v3" 4) "v5"
-
GETRANGE, SETRANGE
获取指定区间范围内的值:
127.0.0.1:6379> set k1 abcd1234 OK 127.0.0.1:6379> GETRANGE k1 0 -1 "abcd1234" 127.0.0.1:6379> GETRANGE k1 0 3 "abcd" 127.0.0.1:6379> SETRANGE k1 1 xxyy (integer) 8 127.0.0.1:6379> get k1 "axxyy234"
-
INCR, INCRBY, DECR, DECRBY
数值增减(一定是数字才能进行加减):
-
增加数字
127.0.0.1:6379> set k1 100 OK 127.0.0.1:6379> get k1 "100" 127.0.0.1:6379> INCR k1 (integer) 101 127.0.0.1:6379> INCR k1 (integer) 102 127.0.0.1:6379> INCR k1 (integer) 103 127.0.0.1:6379> INCR k1 (integer) 104
-
增加指定的整数
127.0.0.1:6379> INCRBY k1 3 (integer) 107 127.0.0.1:6379> INCRBY k1 3 (integer) 110 127.0.0.1:6379> INCRBY k1 3 (integer) 113
-
递减数值
127.0.0.1:6379> DECR k1 (integer) 112 127.0.0.1:6379> DECR k1 (integer) 111 127.0.0.1:6379> DECR k1 (integer) 110
-
减少指定的整数
127.0.0.1:6379> DECRBY k1 3 (integer) 107 127.0.0.1:6379> DECRBY k1 3 (integer) 104 127.0.0.1:6379> DECRBY k1 3 (integer) 101
-
SERLEN,APPEND
获取字符串长度和内容追加:
127.0.0.1:6379> set k1 abcd OK 127.0.0.1:6379> STRLEN k1 (integer) 4 127.0.0.1:6379> append k1 xxxx (integer) 8 127.0.0.1:6379> get k1 "abcdxxxx"
-
分布式锁
127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> EXPIRE k1 10 (integer) 1 127.0.0.1:6379> ttl k1 (integer) 7 127.0.0.1:6379> SETEX k1 10 v1 OK 127.0.0.1:6379> ttl k1 (integer) 6 127.0.0.1:6379> SETNX k1 v11 (integer) 1 127.0.0.1:6379> get k1 "v11" 127.0.0.1:6379> SETNX k1 v11 (integer) 0
-
GETSET(先
get再
set)
127.0.0.1:6379> GETSET k1 haha "v11" 127.0.0.1:6379> get k1 "haha" 127.0.0.1:6379> set k1 v1 get "haha" 127.0.0.1:6379> get k1 "v1"
应用场景:
-
抖音无限点赞某个视频或商品,点一下加一次
-
是否喜欢的文章
3.1.2 redis列表(List)
- Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际是个
双端列表
。 - 最多可包含2^32-1个元素。
- 主要功能有push/pop等,一般用在栈、队列、消息队列等场景。
常用:
-
lpush/rpush/lrange
127.0.0.1:6379> lpush list 1 2 3 4 5 (integer) 5 127.0.0.1:6379> rpush list2 11 22 33 44 55 (integer) 5 127.0.0.1:6379> TYPE list list 127.0.0.1:6379> LRANGE list 0 -1 1) "5" 2) "4" 3) "3" 4) "2" 5) "1" 127.0.0.1:6379> LRANGE list2 0 -1 1) "11" 2) "22" 3) "33" 4) "44" 5) "55"
-
lpop/rpop
127.0.0.1:6379> LPOP list "5" 127.0.0.1:6379> RPOP list "1"
-
lindex
按照索引下标获得元素(从上到下)
127.0.0.1:6379> LINDEX list 0 "4" 127.0.0.1:6379> LINDEX list 2 "2"
-
llen
获取列表中元素个数
127.0.0.1:6379> LLEN list (integer) 3 127.0.0.1:6379> LLEN list2 (integer) 5
-
lrem
删除N个值等于
V1
的元素127.0.0.1:6379> LRANGE list 0 -1 1) "5" 2) "4" 3) "3" 4) "3" 5) "2" 6) "2" 7) "2" 8) "1" 9) "1" 10) "1" 11) "1" 12) "4" 13) "3" 14) "2" 127.0.0.1:6379> LREM list 3 1 (integer) 3 127.0.0.1:6379> LRANGE list 0 -1 1) "5" 2) "4" 3) "3" 4) "3" 5) "2" 6) "2" 7) "2" 8) "1" 9) "4" 10) "3" 11) "2"
-
ltrim
截取指定范围的值后再赋值给key
127.0.0.1:6379> LTRIM list 4 7 OK 127.0.0.1:6379> LRANGE list 0 -1 1) "2" 2) "2" 3) "2" 4) "1"
-
rpoplpush
127.0.0.1:6379> LRANGE list 0 -1 1) "2" 2) "2" 3) "2" 4) "1" 127.0.0.1:6379> LRANGE list2 0 -1 1) "11" 2) "22" 3) "33" 4) "44" 5) "55" 127.0.0.1:6379> RPOPLPUSH list list2 "1" 127.0.0.1:6379> LRANGE list 0 -1 1) "2" 2) "2" 3) "2" 127.0.0.1:6379> LRANGE list2 0 -1 1) "1" 2) "11" 3) "22" 4) "33" 5) "44" 6) "55"
-
lset
127.0.0.1:6379> LSET list 1 mysql OK 127.0.0.1:6379> LRANGE list 0 -1 1) "2" 2) "mysql" 3) "2"
-
linsert key before/after 已有值 插入的新值
127.0.0.1:6379> LINSERT list before mysql java (integer) 4 127.0.0.1:6379> LRANGE list 0 -1 1) "2" 2) "java" 3) "mysql" 4) "2"
应用场景:
- 微信公众号订阅的消息
3.1.3 redis哈希表(Hash)
- Redis hash 是一个 string 类型的 field(字段)和value(值)的映射表,hash特别适合用于存储对象。
- 可以存储2^32-1键值对。
常用:
-
HSET
设置散列上一个或多个字段的值。 -
HGET
返回给定字段的值。 -
HMGET
返回一个或多个给定字段的值。 -
HMGET/HGETALL/HDEL
127.0.0.1:6379> HSET user:001 id 11 name zs age 25 (integer) 3 127.0.0.1:6379> HGET user:001 id "11" 127.0.0.1:6379> HGET user:001 name "zs" 127.0.0.1:6379> HMSET user:001 id 12 name 1s age 26 OK 127.0.0.1:6379> HMGET user:001 id name age 1) "12" 2) "1s" 3) "26" 127.0.0.1:6379> HGETALL user:001 1) "id" 2) "12" 3) "name" 4) "1s" 5) "age" 6) "26" 127.0.0.1:6379> HDEL user:001 age (integer) 1 127.0.0.1:6379> HGETALL user:001 1) "id" 2) "12" 3) "name" 4) "1s"
-
hlen
127.0.0.1:6379> HLEN user:001 (integer) 2
-
hexists key
在key里面的某个值的key
127.0.0.1:6379> HEXISTS user:001 name (integer) 1 127.0.0.1:6379> HEXISTS user:001 age (integer) 0
-
hkeys/hvals
127.0.0.1:6379> HKEYS user:001 1) "id" 2) "name" 127.0.0.1:6379> HVALS user:001 1) "12" 2) "1s"
-
HINCRBY/hincrbyfloat
按提供的整数递增给定字段的值。127.0.0.1:6379> HSET user:001 age 25 score 99.5 (integer) 2 127.0.0.1:6379> HGETALL user:001 1) "id" 2) "12" 3) "name" 4) "1s" 5) "age" 6) "25" 7) "score" 8) "99.5" 127.0.0.1:6379> HINCRBYFLOAT user:001 score 0.5 "100" 127.0.0.1:6379> HINCRBYFLOAT user:001 score 0.5 "100.5" 127.0.0.1:6379> HINCRBYFLOAT user:001 score 0.5 "101" 127.0.0.1:6379> HINCRBY user:001 age 1 (integer) 26 127.0.0.1:6379> HINCRBY user:001 age 1 (integer) 27
-
hsetnx
不存在赋值,存在无效
127.0.0.1:6379> HSETNX user:001 email zzyybs@126.com (integer) 1 127.0.0.1:6379> HSETNX user:001 email zzyybs@126.com (integer) 0
应用场景:
- JD购物车早期设计,目前不再采用,当前小中厂可用。
3.1.4 redis集合(Set)
- Redis 的 Set 是 String 类型的
无序集合
。集合成员是唯一的,这意味着集合中不能出现重复的数据。集合对象的编码可以是 intset 或者 hashtable。 - Redis 的 Set 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
- 集合的最大成员数为2^32-1。
-
sadd key member[member...]
:添加元素127.0.0.1:6379> SADD set1 1 1 1 2 2 2 3 3 4 4 5 (integer) 5
-
smembers key
:遍历集合中所有元素127.0.0.1:6379> SMEMBERS set1 1) "1" 2) "2" 3) "3" 4) "4" 5) "5"
-
sismember key member
:判断元素是否在集合中127.0.0.1:6379> SISMEMBER set1 1 (integer) 1 127.0.0.1:6379> SISMEMBER set1 0 (integer) 0
-
scard
:获取集合里元素个数127.0.0.1:6379> SREM set1 y (integer) 0 127.0.0.1:6379> SREM set1 1 (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "2" 2) "3" 3) "4" 4) "5" 127.0.0.1:6379> SCARD set1 (integer) 4
-
srandmember key[数字]
:从集合里随机展现设置的数字个数,元素不删除127.0.0.1:6379> SRANDMEMBER set1 1 1) "6" 127.0.0.1:6379> SRANDMEMBER set1 3 1) "4" 2) "8" 3) "5" 127.0.0.1:6379> SMEMBERS set1 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 6) "6" 7) "7" 8) "8"
-
spop 数字
:从集合中随机弹出一个元素,出一个删一个127.0.0.1:6379> SPOP set1 1 1) "3" 127.0.0.1:6379> SPOP set1 2 1) "7" 2) "4" 127.0.0.1:6379> SMEMBERS set1 1) "1" 2) "2" 3) "5" 4) "6" 5) "8"
-
smove key1 key2
: 将key1
里存在的某个值赋给key2
127.0.0.1:6379> SMOVE set1 stet2 5 (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "1" 2) "2" 3) "6" 4) "8" 127.0.0.1:6379> SMEMBERS stet2 1) "5"
-
集合运算:差集、并集、交集
127.0.0.1:6379> SADD set1 a b c 1 2 (integer) 5 127.0.0.1:6379> SADD set2 1 2 3 a x (integer) 5 127.0.0.1:6379> SDIFF set1 set2 1) "b" 2) "c" 127.0.0.1:6379> SDIFF set2 set1 1) "x" 2) "3" 127.0.0.1:6379> SUNION set1 set2 1) "c" 2) "2" 3) "3" 4) "a" 5) "1" 6) "b" 7) "x" 127.0.0.1:6379> SINTER set1 set2 1) "2" 2) "a" 3) "1" 127.0.0.1:6379> SINTERCARD 2 set1 set2 (integer) 3
应用场景:
- 微信抽奖小程序
- 微信朋友圈点赞查看同赞朋友
- QQ内推可能认识的人
3.1.5 redis有序集合(ZSet)
Redis zset
和set
一样也是string
类型元素的集合,且不容许重复的成员。- 不同的是每个成员都会关联一个double类型的分数,
redis
正是通过分数来为集合中的成员进行从小到大排序。 zset
成员是为一个的,但分数(score)却可以重复。zset
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。- 集合的最大成员数为2^32-1。
- 在 set 基础上,每个 val 值前加一个 score 分数值。之前的 set 是
k1 v1 v2 v3
,现在zset
是k1 score1 v1 score2 v2
-
zadd key score member[score member...]
:向有序集合中加入一个元素和该元素的分数127.0.0.1:6379> ZADD zset1 60 v1 70 v2 80 v3 90 v4 100 v5 (integer) 5
-
zrange key start stop [withscores]
:按照分数从小到大的顺序返回索引从start
到stop
之间所有元素127.0.0.1:6379> ZRANGE zset1 0 -1 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "v5" 127.0.0.1:6379> ZRANGE zset1 0 -1 withscores 1) "v1" 2) "60" 3) "v2" 4) "70" 5) "v3" 6) "80" 7) "v4" 8) "90" 9) "v5" 10) "100"
-
zrevrange
127.0.0.1:6379> ZREVRANGE zset1 0 -1 withscores 1) "v5" 2) "100" 3) "v4" 4) "90" 5) "v3" 6) "80" 7) "v2" 8) "70" 9) "v1" 10) "60"
-
zrangebyscore key min max [withscores] [limit offset count]
:获取指定分数范围的元素127.0.0.1:6379> ZRANGEBYSCORE zset1 60 90 1) "v1" 2) "v2" 3) "v3" 4) "v4" 127.0.0.1:6379> ZRANGEBYSCORE zset1 60 90 withscores 1) "v1" 2) "60" 3) "v2" 4) "70" 5) "v3" 6) "80" 7) "v4" 8) "90" 127.0.0.1:6379> ZRANGEBYSCORE zset1 (60 90 withscores 1) "v2" 2) "70" 3) "v3" 4) "80" 5) "v4" 6) "90" 127.0.0.1:6379> ZRANGEBYSCORE zset1 (60 90 withscores limit 0 1 1) "v2" 2) "70" 127.0.0.1:6379> ZRANGEBYSCORE zset1 (60 90 withscores limit 0 2 1) "v2" 2) "70" 3) "v3" 4) "80"
-
zscore key member
:获取元素的分数127.0.0.1:6379> ZSCORE zset1 v5 "100"
-
zcard key
:获取集合中元素的数量127.0.0.1:6379> ZCOUNT zset1 60 100 (integer) 4 127.0.0.1:6379> ZCOUNT zset1 65 79 (integer) 1
-
zrem key
:某score
下对应的value
值,作用是删除元素127.0.0.1:6379> ZREM zset1 v5 (integer) 1 127.0.0.1:6379> ZREM zset1 v5 (integer) 0 127.0.0.1:6379> ZRANGE zset1 0 -1 withscores 1) "v1" 2) "60" 3) "v2" 4) "70" 5) "v3" 6) "80" 7) "v4" 8) "90"
-
zincrby key increment member
:增加某个元素分数127.0.0.1:6379> ZINCRBY zset1 3 v1 "63" 127.0.0.1:6379> ZRANGE zset1 0 -1 withscores 1) "v1" 2) "63" 3) "v2" 4) "70" 5) "v3" 6) "80" 7) "v4" 8) "90"
-
zmpop
:从键名列表中第一个非空排列集中弹出一个或多个元素,它们是成员分数对127.0.0.1:6379> ZMPOP 1 zset1 min count 1 1) "zset1" 2) 1) 1) "v1" 2) "63"
-
zrank
:获取下标值127.0.0.1:6379> ZRANK zset1 v2 (integer) 0
-
zrevrank
: 逆序获取下标值127.0.0.1:6379> ZREVRANK zset1 v2 (integer) 2
对应场景:
- 根据商品销售对商品进行排序显示
3.1.6 redis地理空间(GEO)
- 经纬度
-
geoadd
127.0.0.1:6379> GEOADD city 116.403963 39.915119 "天安门" 116.403414 39.924091 "故宫" 116.024067 40.362639 "长城" (integer) 3 127.0.0.1:6379> type city zset 127.0.0.1:6379> ZRANGE city 0 -1 1) "\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8" 2) "\xe6\x95\x85\xe5\xae\xab" 3) "\xe9\x95\xbf\xe5\x9f\x8e" 127.0.0.1:6379> quit [root@hadoop100 myredis]# redis-cli -a www.123.com --raw Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> ZRANGE city 0 -1 天安门 故宫 长城
-
geopos
127.0.0.1:6379> GEOPOS city 天安门 故宫 长城 116.40396326780319214 39.91511970338637383 116.40341609716415405 39.92409008156928252 116.02406591176986694 40.36263993239462167
-
geohash
:算法生成的base32
编码值,3维变维变1维(经纬度坐标)127.0.0.1:6379> GEOHASH city 天安门 故宫 长城 wx4g0f6f2v0 wx4g0gfqsj0 wx4t85y1kt0
-
geodist
:(两个位置间距离)127.0.0.1:6379> GEODIST city 天安门 故宫 km 0.9988 127.0.0.1:6379> GEODIST city 天安门 故宫 m 998.8332
-
georadius
:以半径为中心查找附近的xxx127.0.0.1:6379> GEORADIUS city 116.418017 39.914402 10 km withdist withcoord withhash count 10 desc 故宫 1.6470 4069885568908290 116.40341609716415405 39.92409008156928252 天安门 1.2016 4069885555089531 116.40396326780319214 39.91511970338637383
3.1.7 redis基数统计(HyperLogLog)
-
统计某个网站的UV,统计某个文章的UV(Unique Visitor,独立访客,一般理解为客户端
IP
)。 -
HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
-
在redis里,每个hyperLogLog键只需要花费12KB内存,就可以计算接近2^64个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
-
但是,因为HyperLogLog只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog不能像集合那样,返回输入的各个元素。
-
pfadd key element[element...]
:添加指定元素到HyperLogLog
中127.0.0.1:6379> PFADD hll01 1 3 5 7 9 (integer) 1 127.0.0.1:6379> PFADD hll02 1 2 4 4 4 5 9 10 (integer) 1
-
pfcount key
:返回给定HyperLogLog
的基数估算值127.0.0.1:6379> PFCOUNT hll01 (integer) 5 127.0.0.1:6379> PFCOUNT hll02 (integer) 6
-
pfmerge destkey sourcekey [sourcekey]
:将多个HyperLogLog
合并为一个HyperLogLog
127.0.0.1:6379> PFMERGE hllresult hll01 hll02 OK 127.0.0.1:6379> PFCOUNT hllresult (integer) 8
3.1.8 redis位图(bitmap)
- 由0和1状态表现的二进制位的bit数组。
- (能干什么)用于状态记录
- 偏移量从0开始
-
setbit key offset val
:给指定key
的值的第offset
赋值val
,时间复杂度O(1).127.0.0.1:6379> SETBIT k1 1 1 (integer) 1 127.0.0.1:6379> SETBIT k1 2 1 (integer) 1 127.0.0.1:6379> SETBIT k1 3 0 (integer) 1 127.0.0.1:6379> type k1 string
-
getbit key offset
:获取指定key
的第offset
位,时间复杂度O().127.0.0.1:6379> GETBIT k1 0 (integer) 0 127.0.0.1:6379> GETBIT k1 1 (integer) 1 127.0.0.1:6379> GETBIT k1 2 (integer) 1 127.0.0.1:6379> GETBIT k1 3 (integer) 0
-
strlen
:统计字节数占多少不是字符串长度,而是所占字节,超过8位后,按照8位一组一byte再扩充。
127.0.0.1:6379> SETBIT k2 0 1 (integer) 0 127.0.0.1:6379> SETBIT k2 7 1 (integer) 0 127.0.0.1:6379> STRLEN k2 (integer) 1 127.0.0.1:6379> SETBIT k2 8 1 (integer) 0 127.0.0.1:6379> STRLEN k2 (integer) 2
-
bitcount key start end
:返回指定key
中的[start, end]中为1 的数量,时间复杂度O(n).127.0.0.1:6379> SETBIT uid:login123 1 1 (integer) 0 127.0.0.1:6379> SETBIT uid:login123 2 1 (integer) 0 127.0.0.1:6379> SETBIT uid:login123 3 1 (integer) 0 127.0.0.1:6379> BITCOUNT uid:login123 (integer) 3
-
bitop operation destkey key
:对不同的二进制存储数据进行位运算(AND\OR\NOT\XOR
),时间复杂度O(n).127.0.0.1:6379> HSET uid:map 0 uid-092iok-lkj (integer) 1 127.0.0.1:6379> HSET uid:map 1 uid-7388c-xxx (integer) 1 127.0.0.1:6379> HGETALL uid:map 1) "0" 2) "uid-092iok-lkj" 3) "1" 4) "uid-7388c-xxx" 127.0.0.1:6379> SETBIT 20230420 0 1 (integer) 0 127.0.0.1:6379> SETBIT 20230420 1 1 (integer) 0 127.0.0.1:6379> GETBIT 20230420 0 (integer) 1 127.0.0.1:6379> SETBIT 20230420 2 1 (integer) 0 127.0.0.1:6379> SETBIT 20230420 3 1 (integer) 0 127.0.0.1:6379> SETBIT 20230421 0 1 (integer) 0 127.0.0.1:6379> SETBIT 20230421 2 1 (integer) 0 127.0.0.1:6379> BITCOUNT 20230420 (integer) 4 127.0.0.1:6379> BITCOUNT 20230421 (integer) 2 127.0.0.1:6379> BITOP and k3 20230420 20230421 (integer) 1 127.0.0.1:6379> BITCOUNT k3 (integer) 2
应用场景:
- 用户登录多少天(签到、打卡)
3.1.9 redis位域(bitfield
)
- 通过
bitfield
命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。 - 通过
bitfield
命令我们可以一次性对多个比特位域进行操作。
-
bitfield key [get type offset]
127.0.0.1:6379> set fieldkey hello OK 127.0.0.1:6379> BITFIELD fieldkey get i8 0 104 127.0.0.1:6379> BITFIELD fieldkey get i8 8 101 127.0.0.1:6379> BITFIELD fieldkey get i8 16 108
-
bitfield key [set type offset value]
127.0.0.1:6379> BITFIELD fieldkey set i8 8 120 101 127.0.0.1:6379> get fieldkey hxllo
-
bitfield key [incrby type offset increment]
127.0.0.1:6379> set fieldkey hello OK 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 #从第2位开始,对接下来4位无符号数+1 11 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 12 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 13 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 14 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 15 127.0.0.1:6379> BITFIELD fieldkey incrby u4 2 1 #默认overflow为wrap,即循环溢出 0
-
溢出控制
overflow [wrap|sat|fail]
wrap
:使用回绕(wrap around
)方法处理有符号整数和无符号整数的溢出情况。sat
:使用饱和计算(saturation arithmetic
)方法处理溢出,下溢计算结果为最小的整数值,而上溢的计算结果为最大的整数值。fail
:命令将拒绝执行那些会导致上溢或者下溢情况出现的计算,并向用户返回空值表示计算未执行。
127.0.0.1:6379> set test a #ascii码97 OK 127.0.0.1:6379> BITFIELD test get i8 0 #i8表示有符号的8位二进制数,范围(-128-127) 97 127.0.0.1:6379> BITFIELD test set i8 0 127 97 127.0.0.1:6379> BITFIELD test get i8 0 127 127.0.0.1:6379> get test 127.0.0.1:6379> BITFIELD test set i8 0 138 #默认overflow为wrap,即循环溢出 127 127.0.0.1:6379> BITFIELD test get i8 0 -118 127.0.0.1:6379> BITFIELD test overflow sat set i8 0 128 #上溢 -118 127.0.0.1:6379> BITFIELD test get i8 0 127 127.0.0.1:6379> BITFIELD test overflow fail set i8 0 888 (nil)
3.1.10 redis流(Stream)
- Redis Stream 是 Redis 5.0 版本增加的数据结构。
- Redis Stream 主要用于消息队列(
MQ,Message Queue
),Redis本身是有一个Redis发布订阅(pub/sub)来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis宕机等,消息就会被丢弃。 - 简单来说发布订阅(pub/sub)可以分发消息,但无法记录历史消息。
- 而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻数据,并且记住每一个客户端的访问位置,还能保证消息不丢失。
队列相关指令:
-
XADD
向流中添加新条目,如果指定Stream队列不存在,则该命令执行时会创建一个Stream队列。- 消息ID必须比上个ID大
- 默认用*号表示自动生成规矩
- *用于XADD命令中,让系统自动生成ID
127.0.0.1:6379> XADD mystream * id 11 cname zs 1681991364460-0 127.0.0.1:6379> XADD mystream * id 22 cname ls 1681991376583-0 127.0.0.1:6379> XADD mystream * k1 v1 k2 v2 k3 v3 1681991401445-0 #生成的消息ID有两部分组成,毫秒时间戳-该毫秒内产生的第一条消息 127.0.0.1:6379> XADD mystream 1681991401445-0 k1 v1 k2 v2 k3 v3 ERR The ID specified in XADD is equal or smaller than the target stream top item 127.0.0.1:6379> type mystream stream
-
XREAD
读取一个或多个条目,从给定的位置开始并在时间上向前移动。-
用于获取消息(阻塞/非阻塞),只会返回大于指定ID的消息
-
非阻塞(BLOCK是否以阻塞的方式读取消息,默认不阻塞,如果,milliseconds设置为0,表示永远阻塞)
-
阻塞
127.0.0.1:6379> XREAD count 1 block 0 streams mystream $ mystream 1681994552433-0 k9 v9
新开一个终端
127.0.0.1:6379> XADD mystream * k9 v9 "1681994552433-0"
-
$
代表特殊ID,表示以当前Stream已经存储的最大的ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil
127.0.0.1:6379> XREAD count 2 streams mystream $
-
0-0
代表从最小的ID开始获取Stream的消息,当不指定count,将会返回Stream中的所有消息,注意也可以使用0(00/000)也都是可以的。127.0.0.1:6379> XREAD count 2 streams mystream 0-0 mystream 1681992655414-0 k2 v2 1681993110007-0 k3 v3 k4 v4 k5 v5 127.0.0.1:6379> XREAD count 2 streams mystream 000 mystream 1681992655414-0 k2 v2 1681993110007-0 k3 v3 k4 v4 k5 v5
-
-
XRANGE
返回两个提供的条目ID之间的条目范围。127.0.0.1:6379> XRANGE mystream - + 1681991364460-0 id 11 cname zs 1681991376583-0 id 22 cname ls 1681991401445-0 k1 v1 k2 v2 k3 v3
127.0.0.1:6379> XRANGE mystream - + count 1 1681991364460-0 id 11 cname zs
-
xrevrange
127.0.0.1:6379> XREVRANGE mystream + 1 1681991401445-0 k1 v1 k2 v2 k3 v3 1681991376583-0 id 22 cname ls 1681991364460-0 id 11 cname zs
-
XLEN
返回流的长度。127.0.0.1:6379> XLEN mystream 2
-
xdel
127.0.0.1:6379> XDEL mystream 1681991401445-0 1
-
xtrim
127.0.0.1:6379> XADD mystream * k1 v1 1681992648764-0 127.0.0.1:6379> XADD mystream * k2 v2 1681992655414-0 127.0.0.1:6379> XRANGE mystream - + 1681991364460-0 id 11 cname zs 1681991376583-0 id 22 cname ls 1681992648764-0 k1 v1 1681992655414-0 k2 v2
-
用于对Stream的长度进行截取,如超长会进行截取
-
MAXLEN
允许的最大长度,对流进行修剪限制长度127.0.0.1:6379> XTRIM mystream maxlen 2 2 127.0.0.1:6379> XRANGE mystream - + 1681992648764-0 k1 v1 1681992655414-0 k2 v2
-
允许的最小id,从某个id值开始比该id值小的将会抛弃
127.0.0.1:6379> XTRIM mystream minid 1681992648764-0 0 127.0.0.1:6379> XTRIM mystream minid 1681992655414-0 1 127.0.0.1:6379> XRANGE mystream - + 1681992655414-0 k2 v2
-
消费组相关指令:
-
xgroup create
:用于创建消费者组$
表示从Stream尾部开始消费0
表示从Stream头部开始消费
127.0.0.1:6379> XGROUP create mystream groupX $ OK 127.0.0.1:6379> XGROUP create mystream groupA 0 OK
-
xreadgroup group
-
>
表示从第一条尚未被消费的消息开始读取127.0.0.1:6379> XGROUP create mystream groupb 0 OK 127.0.0.1:6379> XREADGROUP group groupA consumer1 streams mystream > 1) 1) "mystream" 2) 1) 1) "1681992655414-0" 2) 1) "k2" 2) "v2" 2) 1) "1681993110007-0" 2) 1) "k3" 2) "v3" 3) "k4" 4) "v4" 5) "k5" 6) "v5" 3) 1) "1681993142483-0" 2) 1) "k6" 2) "v6" 4) 1) "1681993282122-0" 2) 1) "k7" 2) "v7" 5) 1) "1681993288147-0" 2) 1) "k8" 2) "v8" 6) 1) "1681994552433-0" 2) 1) "k9" 2) "v9"
-
消费组
groupA
内的消费者consumer1
从mystream
消息队列中读取所有消息127.0.0.1:6379> XREADGROUP group groupA consumer2 streams mystream > (nil)
-
但是,不同消费组的消费者可以消费同一条消息
127.0.0.1:6379> XREADGROUP group groupb consumer1 streams mystream > 1) 1) "mystream" 2) 1) 1) "1681992655414-0" 2) 1) "k2" 2) "v2" 2) 1) "1681993110007-0" 2) 1) "k3" 2) "v3" 3) "k4" 4) "v4" 5) "k5" 6) "v5" 3) 1) "1681993142483-0" 2) 1) "k6" 2) "v6" 4) 1) "1681993282122-0" 2) 1) "k7" 2) "v7" 5) 1) "1681993288147-0" 2) 1) "k8" 2) "v8" 6) 1) "1681994552433-0" 2) 1) "k9" 2) "v9" 127.0.0.1:6379> XREADGROUP group groupb consumer2 streams mystream > (nil)
-
消费组的目的:让组内的多个消费者共同分担读取信息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的。
127.0.0.1:6379> XGROUP create mystream groupc 0 OK 127.0.0.1:6379> XREADGROUP group groupc consumer1 count 2 streams mystream > 1) 1) "mystream" 2) 1) 1) "1681992655414-0" 2) 1) "k2" 2) "v2" 2) 1) "1681993110007-0" 2) 1) "k3" 2) "v3" 3) "k4" 4) "v4" 5) "k5" 6) "v5" 127.0.0.1:6379> XREADGROUP group groupc consumer2 count 2 streams mystream > 1) 1) "mystream" 2) 1) 1) "1681993142483-0" 2) 1) "k6" 2) "v6" 2) 1) "1681993282122-0" 2) 1) "k7" 2) "v7" 127.0.0.1:6379> XREADGROUP group groupc consumer3 count 2 streams mystream > 1) 1) "mystream" 2) 1) 1) "1681993288147-0" 2) 1) "k8" 2) "v8" 2) 1) "1681994552433-0" 2) 1) "k9" 2) "v9" 127.0.0.1:6379> XREADGROUP group groupc consumer4 count 2 streams mystream > (nil)
-
-
重点问题:
基于Stream实现消息队列,如何保证消费者在发生故障或者宕机再次重启后,仍然可以读取未处理完的消息?
- Streams会自动使用内部队列(也称为
PENDING List
)留存消费组里每个消费者读取的消息保底措施,直到消费者使用XACK命令通知Streams消息已经处理完成。 - 消息确认增加了消息的可靠性,一般在业务处理完成之后,需要执行
XACK
命令确认消息已经被完成。
- Streams会自动使用内部队列(也称为
-
xpending
127.0.0.1:6379> XPENDING mystream groupc 1) (integer) 6 2) "1681992655414-0" 3) "1681994552433-0" 4) 1) 1) "consumer1" 2) "2" 2) 1) "consumer2" 2) "2" 3) 1) "consumer3" 2) "2" 127.0.0.1:6379> XPENDING mystream groupA 1) (integer) 6 2) "1681992655414-0" 3) "1681994552433-0" 4) 1) 1) "consumer1" 2) "6"
-
xack
127.0.0.1:6379> XPENDING mystream groupc - + 10 consumer2 #ack签收之前2条 1) 1) "1681993142483-0" 2) "consumer2" 3) (integer) 936115 4) (integer) 1 2) 1) "1681993282122-0" 2) "consumer2" 3) (integer) 936115 4) (integer) 1 127.0.0.1:6379> XACK mystream groupc 1681993142483-0 #ack成功确认返回1 (integer) 1 127.0.0.1:6379> XPENDING mystream groupc - + 10 consumer2 #ack签收过后一条 1) 1) "1681993282122-0" 2) "consumer2" 3) (integer) 989652 4) (integer) 1
-
xinfo
用于打印stream \consumer\group
的详细信息127.0.0.1:6379> XINFO stream mystream 1) "length" 2) (integer) 6 3) "radix-tree-keys" 4) (integer) 1 5) "radix-tree-nodes" 6) (integer) 2 7) "last-generated-id" 8) "1681994552433-0" 9) "max-deleted-entry-id" 10) "1681991401445-0" 11) "entries-added" 12) (integer) 10 13) "recorded-first-entry-id" 14) "1681992655414-0" 15) "groups" 16) (integer) 4 17) "first-entry" 18) 1) "1681992655414-0" 2) 1) "k2" 2) "v2" 19) "last-entry" 20) 1) "1681994552433-0" 2) 1) "k9" 2) "v9"
使用建议:
- Stream还是不能100%等价于
Kafka、RabbitMQ
来使用的,生产案例少,慎用。
3.2 命令查阅
3.3 Redis键(key)
命令不区分大小写,key
区分大小写.
帮助命令@类型:help @string
key*
查看当前库所有的keyexists key
判断某个key是否存在type key
查看你的key是什么类型del key
删除指定的key数据unlike key
非阻塞删除,仅仅将key从keyspqce
元数据中删除ttl key
查看还有多少秒过期,-1表示永不过期,-2表示已过期expire key 秒钟
为给定的key设置过期时间move key dbindex[0-15]
将当前数据的key移动到给定的数据库db
127.0.0.1:6379> set key1 hello
OK
127.0.0.1:6379> get key1
"hello"
127.0.0.1:6379> get Key1
(nil)