redis一般用哪些数据类型(Redis的8种数据类型什么场景使用)
Redis是一个KV存储系统,使用C语言编写的我们的key是字符串类型,是唯一的,value的数据类型如下,下面我们就来说一说关于redis一般用哪些数据类型?我们一起去了解并探讨一下这个问题吧!
redis一般用哪些数据类型
Redis是一个KV存储系统,使用C语言编写的。我们的key是字符串类型,是唯一的,value的数据类型如下
5种常用的
- string字符串类型
- list列表类型
- set集合类型
- sortedset(zset)有序集合类型
- hash类型
2种不常用的
- bitmap位图类型
- geo地理位置类型
1种redis5.0新增的
- stream类型
既然key是字符串类型,那么key有没有一些约定俗成的一些规则,或者说一些建议的规则呢?
redis key如何设计?
- 一般使用冒号分隔
- 一般会把表名或者表名的缩写作为key的前缀
- 比如:认证系统的用户表的id为001的key, auth:user:001
- 命名要具有一定的识别性,一看就知道是什么意思
- key要尽量短一点,短key的效率比长key好一些,后面会讲到
Redis的string能存储3种值的类型:字符串,整数,浮点数
1.1、应用场景key和value都是字符串类型的应用场景极为广泛
- 普通的赋值操作
- 所有的kv存储都可以转换为value为字符串的存储,通过序列化转string,或者普通类型转string. 所以这种场景是最多的。
- incr可以加上watch监听,实现乐观锁
incr实现的是数字递增
- setnx可以实现分布式锁
- value不存在时,可以用于分布式锁,最终可以一个会设置成功,设置成功的就是抢到锁资源的
命令行罗列
命令 |
帮助 |
描述 |
set |
set key value |
赋值 |
get |
get key |
取值 |
getset |
getset key value |
取值赋值 |
setnx |
setnx key value |
当key不存在时才赋值成功,存在时赋值失败 set key value NX PX 3000 原子操作,可用于分布式锁,px 设置毫秒数 |
append |
append key value |
向尾部追加值 |
strlen |
strlen key |
获取字符串长度 |
incr |
incr key |
递增数字 |
incrby |
incrby key increment |
增加指定的整数 |
decr |
decr key |
递减数字 |
decrby |
decrby key decrement |
减少指定的整数 |
命令行实际操作
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> getset age 20
(nil)
127.0.0.1:6379> get age
"20"
127.0.0.1:6379> setnx lock_01 1001
(integer) 1
127.0.0.1:6379> setnx lock_01 1001
(integer) 0
127.0.0.1:6379> setnx lock_01 1002
(integer) 0
127.0.0.1:6379> append name 1
(integer) 9
127.0.0.1:6379> get name
"zhangsan1"
127.0.0.1:6379> strlen name
(integer) 9
127.0.0.1:6379> incr myid
(integer) 1
127.0.0.1:6379> incrby myid 2
(integer) 3
127.0.0.1:6379> decr myid
(integer) 2
127.0.0.1:6379> decrby myid 2
(integer) 0
# 设置分布式锁后的值,有效期20s
127.0.0.1:6379> set lock_02 1002 NX PX 30000
OK
# 30s内重新设置值失败
127.0.0.1:6379> set lock_02 1002 NX
(nil)
# 30s内获取值成功
127.0.0.1:6379> get lock_02
"1002"
# 30s后获取值为空
127.0.0.1:6379> get lock_02
(nil)
# 重新设置值成功
127.0.0.1:6379> set lock_02 1003 NX PX 30000
OK
127.0.0.1:6379> get lock_02
"1003"
127.0.0.1:6379>
list列表可以存储有序并且可以重复的元素。
- 获取头部或尾部的数据极快
- 列表最多存储2^32 -1个元素,大概40亿
看下面的命令,我们就知道这是一个双向列表。左进右出可以作为队列,左进左出可以作为栈使用。其实就是先进先出队列,后进先出为栈。
可以存储各种各样的列表数据。比如用户列表
2.2、list列表命令命令罗列
命令 |
帮助 |
描述 |
lpush |
lpush key v1 v2 n3 ... vn |
从左侧插入列表 |
lpop |
lpop key |
从列表左侧取出 |
rpush |
rpush key v1 v2 n3 ... vn |
从右侧插入列表 |
rpop |
rpop key |
从列表右侧取出 |
lpushx |
lpushx key value |
将值插入到列表头部 |
rpushx |
rpushx key value |
将值插入到列表尾部 |
blpop |
blpop key timeout |
从列表左侧取出,如果为空阻塞,timeout最大阻塞时间(s) |
brpop |
brpop key timeout |
从列表右侧取出,如果为空阻塞,timeout最大阻塞时间(s) |
llen |
llen key |
获得列表中元素个数 |
lindex |
lindex key index |
获得列表中下标为index的元素 index从0开始 |
lrange |
lrange key start end |
返回列表中指定区间的元素,区间通过start和end指定 |
lrem |
lrem key count value |
删除列表中与value相等的元素 当count>0时, lrem会从列表左边开始删除;当count<0时, lrem会从列表后边开始删除;当count=0时, lrem删除所有值为value的元素 |
lset |
lset key index value |
将列表index位置的元素设置成value的值 |
ltrim |
ltrim key start end |
对列表进行修剪,只保留start到end区间 |
rpoplpush |
rpoplpush key1 key2 |
从key1列表右侧弹出并插入到key2列表左侧 |
brpoplpush |
brpoplpush key1 key2 |
从key1列表右侧弹出并插入到key2列表左侧,会阻塞 |
linsert |
linsert key BEFORE/AFTER pivot value |
将value插入到列表,且位于值pivot之前或之后 |
命令执行
127.0.0.1:6379> lpush name2 zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> lpop name2
"wangwu"
127.0.0.1:6379> rpush name3 zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> rpop name3
"wangwu"
127.0.0.1:6379> lpushx name2 niuqi
(integer) 3
127.0.0.1:6379> lrange name2 0 5
1) "niuqi"
2) "lisi"
3) "zhangsan"
127.0.0.1:6379> rpushx name3 niuqi
(integer) 3
127.0.0.1:6379> lrange name3 0 5
1) "zhangsan"
2) "lisi"
3) "niuqi"
127.0.0.1:6379> blpop name2 1
1) "name2"
2) "niuqi"
127.0.0.1:6379> brpop name3 1
1) "name3"
2) "niuqi"
127.0.0.1:6379> llen name2
(integer) 2
127.0.0.1:6379> lindex name2 0
"lisi"
127.0.0.1:6379> lindex name2 1
"zhangsan"
Set集合,就是表示value唯一,并且无需的集合。
存储各种不需要顺序的数据集合。比如用户随机随机抽奖
3.2、Set集合命令命令罗列
命令 |
帮助 |
描述 |
sadd |
sadd key v1 v2 n3 ... vn |
为集合添加新成员 |
srem |
srem key mem1 mem2 ...memn |
删除集合中指定成员 |
smembers |
rsmembers key |
从获得集合中所有元素 |
spop |
spop key |
返回集合中一个随机元素,并将该元素删除 |
srandmember |
srandmember key |
将返回集合中一个随机元素,不会删除该元素 |
scard |
scard key |
获得集合中元素的数量 |
sismember |
sismember key member |
判断元素是否在集合内 |
sinter |
sinter key1 key2 key3 |
求多集合的交集 |
sdiff |
sdiffff key1 key2 key3 |
求多集合的差集 |
sunion |
sunion key1 key2 key3 |
求多集合的并集 |
命令操作
127.0.0.1:6379> sadd name4 zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> srem zhangsan
(error) ERR wrong number of arguments for 'srem' command
127.0.0.1:6379> srem name4 zhangsan
(integer) 1
127.0.0.1:6379> smembers name4
1) "lisi"
2) "wangwu"
127.0.0.1:6379> spop name4
"lisi"
127.0.0.1:6379> srandmember name4
"wangwu"
127.0.0.1:6379> scard name4
(integer) 1
127.0.0.1:6379> sismember name4 wangwu
(integer) 1
127.0.0.1:6379> sismember name4 wangwu
(integer) 1
# 定义两个集合 求交集,差集,并集
127.0.0.1:6379> sadd name5 zhangsan lisi
(integer) 2
127.0.0.1:6379> sadd name6 lisi wangwu
(integer) 2
127.0.0.1:6379> sinter name5 name6
1) "lisi"
127.0.0.1:6379> sdiff name5 name6
1) "zhangsan"
127.0.0.1:6379> sunion name5 name6
1) "lisi"
2) "wangwu"
3) "zhangsan"
sortedset是一个有序集合,元素本身跟set一样,是不重复的,为每一个元素添加了一个分数(score)根据分数的不同可以进行排序。分数可以重复。
有序列表被广泛使用在各种排行榜业务上:比如销量排行,用户点击率排行等
4.2、sortedset命令命令罗列
命令 |
帮助 |
描述 |
zadd |
zadd key score1 v1 score2 v2 score1v3 ... scoren vn |
为有序集合添加新成员 |
zrem |
zrem key mem1 mem2 ...memn |
删除有序集合中指定成员 |
zcard |
zcard key |
获得有序集合中的元素数量 |
zcount |
zcount key min max |
返回集合中score值在[min,max]区间的元素数量 |
zincrby |
zincrby key increment member |
在集合的member分值上加increment |
zscore |
zscore key member |
获得集合中member的分值 |
zrank |
zrank key member |
获得集合中member的排名(按分值从小到大) |
zrevrank |
zrevrank key member |
获得集合中member的排名(按分值从大到小) |
zrange |
zrange key start end |
获得集合中指定区间成员,按分数递增排序 |
zrevrange |
zrevrange key start end |
获得集合中指定区间成员,按分数递减排序 |
命令操作
127.0.0.1:6379> zadd test:001 20 zhangsan 50 lisi 30 wangwu 90 niuqi
(integer) 4
127.0.0.1:6379> zcount test:001 0 2
(integer) 0
127.0.0.1:6379> zcount test:001 20 30
(integer) 2
127.0.0.1:6379> zcard test:001
(integer) 4
127.0.0.1:6379> zrem test:001 wangwu
(integer) 1
127.0.0.1:6379> zincrby test:001 10 zhangsan
"30"
127.0.0.1:6379> zscore test:001 zhangsan
"30"
127.0.0.1:6379> zrank test:001 zhangsan
(integer) 0
127.0.0.1:6379> zrank test:001 niuqi
(integer) 2
127.0.0.1:6379> zrevrank test:001 niuqi
(integer) 0
127.0.0.1:6379> zrevrank test:001 zhangsan
(integer) 2
127.0.0.1:6379> zrange test:001 0 5
1) "zhangsan"
2) "lisi"
3) "niuqi"
127.0.0.1:6379> zrevrange test:001 0 5
1) "niuqi"
2) "lisi"
3) "zhangsan"
hash就是要存储一个key对应多个值。比如以key的用户ID,value为用户整个对象的缓存为例,这种数据就很适合使用hash存储。
5.2、hash命令命令罗列
命令 |
帮助 |
描述 |
hset |
hset key field value |
赋值,不区别新增或修改 |
hmset |
hmset key field1 value1 field2 value2 |
批量赋值 |
hsetnx |
hsetnx key field value |
获得有序集合中的元素数量 |
hexists |
hexists key filed |
查看某个field是否存在 |
hget |
hget key field |
获取一个字段值 |
hmget |
hmget key field1 field2 ... |
获取所有 |
hgetall |
hgetall key |
获得集合中member的排名(按分值从小到大) |
hdel |
hdel key field1 field2 |
删除指定字段 |
hincrby |
hincrby key field increment |
指定字段自增increment |
hlen |
hlen key |
获得字段数量 |
命令操作
# 其实直接使用hset多个key value也是可以的
127.0.0.1:6379> hset user:001 id 001 name zhangsan
(integer) 2
127.0.0.1:6379> hget user:001 id
"001"
127.0.0.1:6379> hget user:001 name
"zhangsan"
127.0.0.1:6379> hmset user:001 age 20 sex 1
OK
127.0.0.1:6379> hsetnx user:001 age 30
(integer) 0
127.0.0.1:6379> hexists user:001 age
(integer) 1
127.0.0.1:6379> hget user:001 age
"20"
# 使用hget多个就会报错
127.0.0.1:6379> hget user:001 age name
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hmget user:001 age name
1) "20"
2) "zhangsan"
127.0.0.1:6379> hgetall user
(empty list or set)
127.0.0.1:6379> hgetall user:001
1) "id"
2) "001"
3) "name"
4) "zhangsan"
5) "age"
6) "20"
7) "sex"
8) "1"
bitmap是进行按位操作的,可以极大的节省空间,如果需要小空间存储大量值的时候可以使用它,并且存储的值很简单,就是1bit即可存储。
比如:用户每月签到,客户以用户id为key, 日期作为偏移量,1 表示签到
命令罗列
命令 |
帮助 |
描述 |
setbit |
setbit key offffset value |
设置key在offffset处的bit值(只能是0或者1)。 |
getbit |
getbit key offffset |
获得key在offffset处的bit值 |
bitcount |
bitcount key |
获得key的bit位为1的个数 |
bitpos |
bitpos key value |
返回第一个被设置为bit值的索引值 |
bitop |
bitop and[or/xor/not] destkey key [key …] |
对多个key 进行逻辑运算后存入destkey中 |
命令操作
# 本月用户签到了四天
127.0.0.1:6379> setbit user:sign:001 20220801 1
(integer) 0
127.0.0.1:6379> setbit user:sign:001 20220803 1
(integer) 0
127.0.0.1:6379> setbit user:sign:001 20220809 1
(integer) 0
127.0.0.1:6379> setbit user:sign:001 20220820 1
(integer) 0
# 查看20220801是否签到了 1表示签到了 0表示没有签到
127.0.0.1:6379> getbit user:sign:001 20220801
(integer) 1
127.0.0.1:6379> getbit user:sign:001 20220802
(integer) 0
# 统计用户签到的次数
127.0.0.1:6379> bitcount user:sign:001
(integer) 4
# 查看第一次签到的时间
127.0.0.1:6379> bitpos user:sign:001 1
(integer) 20220801
geo是Redis用来处理位置信息的。在Redis3.2中正式使用。
应用场景:
- 记录地理位置
- 计算距离
- 查找"附近的人"
命令罗列
命令 |
帮助 |
描述 |
geoadd |
geoadd key 经度 纬度 成员名称1 经度1 纬度1 成员名称2 |
添加地理坐标 |
geohash |
geohash key 成员名称1 成员名称2 |
返回标准的geohash串 |
geopos |
geopos key 成员名称1 成员名称2 |
返回成员经纬度 |
geodist |
geodist key 成员1 成员2 单位 |
计算成员间距离 |
georadiusbymember |
georadiusbymember key 成员 值单位 count 数asc[desc] |
根据成员查找附近的成员 |
# 添加坐标
127.0.0.1:6379> geoadd user:addr 116.21 40.00 zhangsan 116.23 49.9 lisi
(integer) 2
# 获取坐标的hash
127.0.0.1:6379> geohash user:addr zhangsan lisi
1) "wx4es3v8ck0"
2) "y8feuuh0e60"
# 获取坐标的经纬度
127.0.0.1:6379> geopos user:addr zhangsan
1) 1) "116.21000200510025024"
2) "39.99999991084916218"
# 计算两个用户的距离 单位米
127.0.0.1:6379> geodist user:addr zhangsan lisi
"1101141.4665"
# 计算两个用户的距离 单位千米
127.0.0.1:6379> geodist user:addr zhangsan lisi km
"1101.1415"
# 计算张三1200km之内的人的经纬度,距离,由近到远排出顺序
127.0.0.1:6379> georadiusbymember user:addr zhangsan 1200 km withcoord withdist count 3 asc
1) 1) "zhangsan"
2) "0.0000"
3) 1) "116.21000200510025024"
2) "39.99999991084916218"
2) 1) "lisi"
2) "1101.1415"
3) 1) "116.23000055551528931"
2) "49.89999975254306719"
stream是Redis5.0后新增的数据结构,用于可持久化的消息队列。
应用场景,没有使用第三方消息队列,但是使用了redis,redis实现了消息队列功能,但是没有专门左中间件的成熟。所以需要谨慎选择。学习一下还是不错的。
8.2、stream类型命令命令罗列
命令 |
帮助 |
描述 |
xadd |
xadd key id <*> field1 value1 |
将指定消息数据追加到指定队列(key)中,*表示最新生成的id(当前时间 序列号) |
xread |
xread [COUNT count] [BLOCKmilliseconds] STREAMS key[key ...] ID [ID ...] |
从消息队列中读取,COUNT:读取条数,BLOCK:阻塞读(默认不阻塞)key:队列名称 id:消息id |
xrange |
xrange key start end [COUNT] |
读取队列中给定ID范围的消息 COUNT:返回消息条数(消息id从小到大) |
xrevrange |
xrevrange key start end [COUNT] |
读取队列中给定ID范围的消息 COUNT:返回消息条数(消息id从大小到大) |
xdel |
xdel key id |
删除队列的消息 |
xgroup |
xgroup create key groupname id |
创建一个新的消费组 |
xgroup |
xgroup destory key groupname |
删除指定消费组 |
xgroup |
xgroup delconsumer key groupname cname |
删除指定消费组中的某个消费者 |
xgroup |
xgroup setid key id |
修改指定消息的最大id |
xreadgroup |
xreadgroup group groupname consumer COUNT streams key |
从队列中的消费组中创建消费者并消费数据(consumer不存在则创建) |
命令操作
# 创建消息
127.0.0.1:6379> xadd topic:001 * name zhangsan age 20
"1661008860267-0"
127.0.0.1:6379> xadd topic:001 * name wangwu age 24 name lisi age 35
"1661008909085-0"
# 查看消息
127.0.0.1:6379> xrange topic:001 -
1) 1) "1661008860267-0"
2) 1) "name"
2) "zhangsan"
3) "age"
4) "20"
2) 1) "1661008909085-0"
2) 1) "name"
2) "wangwu"
3) "age"
4) "24"
5) "name"
6) "lisi"
7) "age"
8) "35"
# 读取一个消息
127.0.0.1:6379> xread count 1 streams topic:001 0
1) 1) "topic:001"
2) 1) 1) "1661008860267-0"
2) 1) "name"
2) "zhangsan"
3) "age"
4) "20"
# 创建一个消费组
127.0.0.1:6379> xgroup create topic:001 group1 0
OK
# 使用消费组消费数据
127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
1) 1) "topic:001"
2) 1) 1) "1661008860267-0"
2) 1) "name"
2) "zhangsan"
3) "age"
4) "20"
# 使用消费组消费数据 继续消费 总共两条
127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
1) 1) "topic:001"
2) 1) 1) "1661008909085-0"
2) 1) "name"
2) "wangwu"
3) "age"
4) "24"
5) "name"
6) "lisi"
7) "age"
8) "35"
# 消费完了,没有啦
127.0.0.1:6379> xreadgroup group group1 user1 count 1 streams topic:001 >
(nil)
redis的功能之所以这么强大,也与它的各种数据类型有关,不同的业务场景可以使用不同的数据类型,从而更加高效的实现需求。
10、相关文章本人还写了Redis的其他相关文章,有兴趣的可以点击查看!
- <<Redis弱事务性与Lua脚本原子性分析>>
- <<Redis持久化机制分析>>
- <<Redis的事件处理机制分析>>
- <<Redis客户端和服务端如何通信?>>
- <<Redis的淘汰机制分析>>
- <<Redis的底层数据结构分析>>
- <<Redis的8种数据类型,什么场景使用?>>
- <<缓存是什么?缓存有哪些分类?使用它的代价是什么?>>
- <<缓存的6种常见的使用场景>>
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com