Redis常见五种数据类型
String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。
- String 类型的应用场景:缓存对象、常规计数、分布式锁、共享session信息等。
- List 类型的应用场景:消息队列(有两个问题:1. 生产者需要自行实现全局唯一 ID;2. 不能以消费组形式消费数据)等。
- Hash 类型:缓存对象、购物车等。
- Set 类型:聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等。
- Zset 类型:排序场景,比如排行榜、电话和姓名排序等。
1.String
key-value结构。
常用命令:
# 设置 key-value 类型的值
> SET name lin
OK
# 根据 key 获得对应的 value
> GET name
"lin"
# 判断某个 key 是否存在
> EXISTS name
(integer) 1
# 返回 key 所储存的字符串值的长度
> STRLEN name
(integer) 3
# 删除某个 key 对应的值
> DEL name
(integer) 1
应用场景:
1.计数器,用于加减粉丝数,点赞数,访问数
# 设置 key-value 类型的值
> SET number 0
OK
# 将 key 中储存的数字值增一
> INCR number
(integer) 1
# 将key中存储的数字值加 10
> INCRBY number 10
(integer) 11
# 将 key 中储存的数字值减一
> DECR number
(integer) 10
# 将key中存储的数字值减 10
> DECRBY number 10
(integer) 0
2.根据key设置缓存的过期时间
# 设置 key 在 60 秒后过期(该方法是针对已经存在的key设置过期时间)
> EXPIRE name 60
(integer) 1
# 查看数据还有多久过期
> TTL name
(integer) 51
#设置 key-value 类型的值,并设置该key的过期时间为 60 秒
> SET key value EX 60
OK
> SETEX key 60 value
OK
3.共享用户登录信息
比如用户登录后会保存登录信息在服务端,如果有多个服务器,分布式系统每次会把请求随机分配到不同的服务器,信息不共享,用户会重复登录。所以需要借助 Redis 对这些登录信息进行统一的存储和管理,这样无论请求发送到那台服务器,服务器都会去同一个 Redis 获取相关的登录信息,这样就解决了分布式系统下登录存储的问题。
4.实现分布式锁
SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁:
- 如果 key 不存在,则显示插入成功,可以用来表示加锁成功;
- 如果 key 存在,则会显示插入失败,可以用来表示加锁失败。
一般而言,还会对分布式锁加上过期时间,分布式锁的命令如下:
SET lock_key unique_value NX PX 10000
- lock_key 就是 key 键;
- unique_value 是客户端生成的唯一的标识;
- NX 代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;
- PX 10000 表示设置 lock_key 的过期时间为 10s,这是为了避免客户端发生异常而无法释放锁。
而解锁的过程就是将 lock_key 键删除,但不能乱删,要保证执行操作的客户端就是加锁的客户端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客户端,是的话,才将 lock_key 键删除。
2.List
底层是双向链表
常用命令:
# 将一个或多个值value插入到key列表的表头(最左边),最后的值在最前面
LPUSH key value [value ...]
# 将一个或多个值value插入到key列表的表尾(最右边)
RPUSH key value [value ...]
# 移除并返回key列表的头元素
LPOP key
# 移除并返回key列表的尾元素
RPOP key
# 返回列表key中指定区间内的元素,区间以偏移量start和stop指定,从0开始
LRANGE key start stop
# 从key列表表头弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BLPOP key [key ...] timeout
# 从key列表表尾弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BRPOP key [key ...] timeout
应用场景:
- 消息队列:利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。
- 消息排队,消息队列(Lpush、Rpop)、栈(Lpush、Lpop)
- 使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。
3.Hash
Hash 是一个键值对(key - value)集合,其中 value 的形式如: value=[{field1,value1},...{fieldN,valueN}]。Hash 特别适合用于存储对象。
常用命令:
# 存储一个哈希表key的键值
HSET key field value
# 获取哈希表key对应的field键值
HGET key field
# 在一个哈希表key中存储多个键值对
HMSET key field value [field value...]
# 批量获取哈希表key中多个field键值
HMGET key field [field ...]
# 删除哈希表key中的field键值
HDEL key field [field ...]
# 返回哈希表key中field的数量
HLEN key
# 返回哈希表key中所有的键值
HGETALL key
# 为哈希表key中field键的值加上增量n
HINCRBY key field n
应用场景:
1.缓存对象
# 存储一个哈希表uid:1的键值
> HMSET uid:1 name Tom age 15
2
# 存储一个哈希表uid:2的键值
> HMSET uid:2 name Jerry age 13
2
# 获取哈希表用户id为1中所有的键值
> HGETALL uid:1
1) "name"
2) "Tom"
3) "age"
4) "15"
注意:String+json 也可以缓存对象,区别如下:
-
String类型:
- 存储单个值:String类型适合存储单个值,通常用于缓存简单的字符串、数字或序列化后的对象。
- 简单的键值对:String类型使用一个键对应一个值的简单键值对结构。
- 灵活性:String类型提供了一些操作命令,如设置值、获取值、增减数值等,适合对单个值进行快速读写操作。
- 存储空间:String类型存储的是完整的值,无论是字符串还是序列化的对象,因此在存储大对象时可能会占用较多的内存空间。
-
Hash类型:
- 存储多个字段值:Hash类型适合存储具有多个字段的对象,每个字段都有一个对应的值。比如缓存用户对象,可以使用Hash类型存储用户名、年龄、邮箱等字段及其对应的值。
- 结构化数据:Hash类型使用一个键对应一个哈希表,哈希表中包含多个字段-值对。
- 灵活查询:Hash类型提供了一些操作命令,如设置字段值、获取字段值、删除字段等,适合对特定字段进行读写操作。
- 存储空间:Hash类型存储的是字段-值对,相比于String类型,可以更节省存储空间。因为Hash类型可以将多个字段值存储在同一个键下,避免了重复存储键。
选择使用String类型还是Hash类型取决于具体的使用场景和需求。如果需要存储简单的值或对象,并且对整个对象进行读写操作,可以选择String类型。如果需要存储具有多个字段的结构化对象,并且需要对特定字段进行读写操作,可以选择Hash类型。
4. Set(集合):
-
特点:Set是一个无序的、不重复的字符串集合。
-
操作:Set允许添加、删除和判断元素是否存在的操作,这些操作的时间复杂度都是O(1)。
适用场景:
- 存储唯一值:Set适合存储需要保持唯一性的元素,如用户标签、商品标签等。
- 集合运算:Set支持交集、并集、差集等操作,可以用于求共同关注、共同好友等场景。
- 去重:Set可以用来去除重复的元素,如过滤重复的日志、统计独立IP数量等。
5. Zset(有序集合):
-
特点:Zset是一个有序的、不重复的字符串集合,每个元素关联一个浮点数类型的分数,通过分数进行排序。
-
操作:Zset允许添加、删除、更新和查询元素的操作,这些操作的时间复杂度都是O(logN)。
适用场景:
- 排行榜:Zset的有序性和分数排序功能使其非常适合实现排行榜功能,如用户积分排名、音乐榜单等。
- 优先级队列:Zset可以作为优先级队列使用,根据分数来确定元素的优先级,如任务调度、消息队列等。
- 范围查询:Zset支持按照分数范围进行查询,可以用于统计某个时间段内的数据,如活跃用户、销售额等。