Redis深度解析:核心数据类型之hash、list、set

简介: Redis深度解析:核心数据类型之hash、list、set

hash

1.设置指定键的单个属性

语法:hset key field value

例如:设置键 user:1的属性namexiaoming

127.0.0.1:6379> hset user:1 name xiaoming   # user:1 没有的key会自动创建,并因为使用hset,所以是一个hash数据类型
(integer) 1
127.0.0.1:6379> hset user:1 name xiaohong  # user:1中重复的属性name会被修改,返回值为0,是因为没有新增属性。
(integer) 0
127.0.0.1:6379> hset user:1 age 16    # user:1中没有的属性会被新增
(integer) 1
127.0.0.1:6379> hset user:1 sex 1 classmate 301   # hset可以一次性增加多个成员。
# 注意:在redis旧版本中,设置多成员可以使用hmset,新版本没有hmset
(integer) 2

2.获取指定键的域/属性的值

获取hash的所有成员
语法:hgetall key

例如:获取user:3的所有成员

127.0.0.1:6379> hgetall user:3
1) "name"
2) "xiaohong"
3) "age"
4) "17"
5) "sex"
6) "1"

例如:获取指定键所有的域/属性

hkeys key

例如:获取键user的所有域/属性

127.0.0.1:6379> hkeys user:1
1) "name"
2) "age"
3) "sex"
4) "classmate"

127.0.0.1:6379> hkeys user:3
1) "name"
2) "age"
3) "sex"

3.删除指定键的域/属性

语法:hdel key field1 field2 ...

例如:删除键user:1的属性classmate/age,当键中的hash数据没有任何属性,则当前键会被redis删除

127.0.0.1:6379> hdel user:1 classmate age
(integer) 2

4.判断指定属性/域是否存在于当前hash中

语法:hexists key field

例如:判断user:3中是否存在age属性或classmate属性

127.0.0.1:6379> hexists user:3 age
(integer) 1
127.0.0.1:6379> hexists user:3 classmate
(integer) 0

5.属性值自增自减

语法:hincrby key field number

例如:给user:3的age属性在age现有值的基础上-2

# 按指定数值自增
127.0.0.1:6379> hincrby user:3 age 2
(integer) 19
127.0.0.1:6379> hincrby user:3 age 2
(integer) 21

# 按指定数值自减
127.0.0.1:6379> hincrby user:3 age -2
(integer) 19
127.0.0.1:6379> hincrby user:3 age -2
(integer) 17

6.获取hash的成员数量

语法:hlen key

例如:获取hash的成员数量

127.0.0.1:6379> hlen user:3
(integer) 3

list

    列表,有顺序的数据结构,其子成员类型为string,可以是重复的成员。

1.添加子成员

  • 在左侧(上方,前面)添加一条或多条数据
    • lpush key value1 value2 ...
  • 在右侧(上方,后面)添加一条或多条数据
    • rpush key value1 value2 ...
  • 指定元素的左边(前免,上方)/右边(后面,下方)插入一个或多个数据
    • linsert key before 指定元素 value1 value2 ....
    • linsert key after 指定元素 value1 value2 ....

例如:从键为team:1的列表左侧添加一个或多个数据xiaoming、xiaohong、xiaohei、xiaobai

# brother这个key如果不存在,则表示新建列表
lpush team:1 xiaoming
(integer) 1

# 如果brother这个key存在了,则表示给已有列表左侧添加成员
127.0.0.1:6379> lpush team:1 xiaohong
(integer) 2

# lpush还支持一次性左侧添加多个成员
127.0.0.1:6379> lpush team:1 xiaohei xiaobai
(integer) 4

2.设置指定索引位置成员的值

  • redis的列表也有索引,从左往右,从0开始,逐一递增,第1个元素下标为0,索引可以是负数,表示尾部开始计数,如-1表示最后1个元素。
  • lset key index value

例如:修改键为team:1的列表中下标为5的元素值为xiaocao2

lset team:1 5 xiaocao2

3.删除指定成员

语法:lrem key count value

  • count表示删除的数量,value表示要删除的成员。该命令默认表示将列表从左侧前count个value的元素移除
  • count==0,表示删除列表所有值为value的成员
  • count >0,表示删除列表左侧开始的前count个value成员
  • count <0,表示删除列表右侧开始的前count个value成员
127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB
(integer) 6

127.0.0.1:6379> lrem team:3 2 xiaoA
(integer) 2
# 从左侧开始删除2个xiaoA
127.0.0.1:6379> lrange team:3 0 -1
1) "xiaoB"
2) "xiaoC"
3) "xiaoA"
4) "xiaoB"


127.0.0.1:6379> del team:3
(integer) 1
127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB
(integer) 6
# 从右侧开始删除2个xiaoA
127.0.0.1:6379> lrem team:3 -2 xiaoA
(integer) 2
127.0.0.1:6379> lrange team:3 0 -1
1) "xiaoA"
2) "xiaoB"
3) "xiaoC"
4) "xiaoB"

# 删除所有xiaoA
127.0.0.1:6379> del team:3
(integer) 1
127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB
(integer) 6
127.0.0.1:6379> lrem team:3 0 xiaoA
(integer) 3
127.0.0.1:6379> lrange team:3 0 -1
1) "xiaoB"
2) "xiaoC"
3) "xiaoB"

4.获取列表成员

根据指定的索引获取成员的值
语法:lindex key index

例如:获取team:1下标为2以及-2的成员

127.0.0.1:6379> lindex team:1 2
"xiaocao"

127.0.0.1:6379> lindex team:1 -2
"xiaohong"

5.获取列表的切片

闭区间 (start, stop)
语法:lrange key start stop

# 获取列表的前三个成员
127.0.0.1:6379> lrange team:1 0 2
1) "xiaobai"
2) "xiaoshu"
3) "xiaocao"

# 获取下标为2-4之间的成员
127.0.0.1:6379> lrange team:1 2 4
1) "xiaocao"
2) "xiaohua"
3) "xiaohei"

# 获取列表尾部的三个成员
127.0.0.1:6379> lrange team:1 -3 -1
1) "xiaolan"
2) "xiaohong"
3) "xiaoming"

# 注意,redis的列表切片取值方向是从左往右的。
127.0.0.1:6379> lrange team:1 -1 -3
(empty array)


# 获取列表的全部成员
127.0.0.1:6379> lrange team:1 0 -1
 1) "xiaobai"
 2) "xiaoshu"
 3) "xiaocao"
 4) "xiaohua"
 5) "xiaohei"
 6) "xiaocao2"
 7) "xiaohua"
 8) "xiaolan"
 9) "xiaohong"
10) "xiaoming"

6.获取列表的长度

语法:llen key

例如:获取brother列表的成员个数

127.0.0.1:6379> llen team:1
(integer) 10

set

    无序集合,特点就是去重和无序。成员也只能是string。

1.添加元素

语法:sadd key member1 member2 ...

例如:向键authors的集合中添加元素zhangsanlisiwangwu

sadd authors zhangsan sili wangwu

2.获取集合的所有成员

语法:smembers key

例如:获取键authors的集合中所有元素

smembers authors

3.获取集合的长度

语法:scard keys

例如:获取authors集合的长度

127.0.0.1:6379> scard authors
(integer) 3

4.随机获取一个或多个成员

当集成的所有成员都被删除或提取出来,则key会自动被redis回收。
spop key [count=1]

  • count为可选参数,不填则默认1个。被提取成员会从集合中被删除掉

例如:随机获取authors集合的1个或多个成员

127.0.0.1:6379> sadd authors zhangsan sili wangwu
(integer) 3
127.0.0.1:6379> spop authors
"sili"
127.0.0.1:6379> spop authors
"wangwu"
127.0.0.1:6379> spop authors
"zhangsan"

127.0.0.1:6379> sadd authors zhangsan sili wangwu
(integer) 3
127.0.0.1:6379> spop authors 2
1) "sili"
2) "zhangsan"
127.0.0.1:6379> spop authors 2
1) "wangwu"
127.0.0.1:6379> spop authors 2
(empty array)

5.删除指定元素

语法:srem key value

例如:删除键authors的集合中元素wangwu

srem authors wangwu

6.交集、差集和并集

  • 交集,比较多个集合中共同存在的成员
    • sinter key1 key2 key3 ....
  • 差集,比较多个集合中不同的成员,我有你(们)没有的
    • sdiff key1 key2 key3 ....
  • 并集,合并所有集合的成员,并去重
    • sunion key1 key2 key3 ....

例如:商城的购物推荐,根据用户的购买的商品的相似度来进行推荐

# 基本数据
# user:1 = {1,2,3,4}
sadd user:1 1 2 3 4
# user:2 = {1,3,4,5}
sadd user:2 1 3 4 5
# user:3 = {1,3,5,6}
sadd user:3 1 3 5 6
# user:4 = {2,3,4}
sadd user:4 2 3 4

# 交集
127.0.0.1:6379> sinter user:1 user:2
1) "1"
2) "3"
3) "4"
127.0.0.1:6379> sinter user:1 user:3
1) "1"
2) "3"
127.0.0.1:6379> sinter user:1 user:4
1) "2"
2) "3"
3) "4"

127.0.0.1:6379> sinter user:2 user:4
1) "3"
2) "4"

# 并集
127.0.0.1:6379> sunion user:1 user:2 user:4
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

# 差集
127.0.0.1:6379> sdiff user:2 user:3
1) "4"  # 此时可以给user:3推荐4

127.0.0.1:6379> sdiff user:3 user:2
1) "6"  # 此时可以给user:2推荐6

127.0.0.1:6379> sdiff user:1 user:3
1) "2"
2) "4"

zset

    有序集合(sortedSet),去重并且根据score权重值(分数)对值进行排序。score从小到大或从大到小排列。有序集成的成员都是由分数+值组成的。

1.添加成员

语法:

  • zadd key score1 member1
  • zadd key score1 member1 score2 member2 score3 member3 ....

例如:设置榜单achievements,设置成绩和用户名作为achievements的成员

127.0.0.1:6379> zadd achievements 61 xiaoming 62 xiaohong 83 xiaobai  78 xiaohei 87 xiaohui 99 xiaolan
(integer) 6
127.0.0.1:6379> zadd achievements 85 xiaohuang 
(integer) 1
127.0.0.1:6379> zadd achievements 54 xiaoqing

2.给指定成员增加权重值(分数)

语法:

  • zincrby key score member

例如:给achievements中xiaobai增加10分

127.0.0.1:6379> ZINCRBY achievements 10 xiaobai
"93

3.获取集合长度

ps:也就是成员的个数
语法:

  • zcard key

例如:获取achievements的长度

zcard achievements

4.获取指定成员的权重值

语法:

  • zscore key member

例如:获取指定成员的权重值

127.0.0.1:6379> zscore achievements xiaobai
"93"
127.0.0.1:6379> zscore achievements xiaohong
"62"
127.0.0.1:6379> zscore achievements xiaoming
"61"

5.获取指定成员在集合中的排名

ps:排名从0开始计算
语法:

  • srank key member # score从小到大的排名
  • zrevrank key member # score从大到小的排名

例如:获取achievements中xiaohei的分数排名

# 从大到小
127.0.0.1:6379> zrevrank achievements xiaohei
(integer) 4

# 从小到大
127.0.0.1:6379> zrank achievements xiaohei
(integer) 3

6.获取在指定score区间的所有成员数量

语法:

  • zcount key min max

例如:获取achievements从0~60分之间的人数[闭区间]

127.0.0.1:6379> zadd achievements 60 xiaolv
(integer) 1
127.0.0.1:6379> zadd achievements 0 xiaocao
(integer) 1

# 获取分数在 (0,60) 这个区间的成员
127.0.0.1:6379> zcount achievements 0 60
(integer) 3

127.0.0.1:6379> zcount achievements 61 100
(integer) 7

7.获取在指定score/index区间的所有成员

语法:

  • zrangebyscore key min max # 按score进行从低往高排序获取指定score区间`
  • zrevrangebyscore key min max # 按score进行从高往低排序获取指定score区间`
  • zrange key start stop # 按scoer进行从低往高排序获取指定索引区间`
  • zrevrange key start stop # 按scoer进行从高往低排序获取指定索引区间`

例如:获取achievements中在(60,70)这个区间的数据

127.0.0.1:6379> zrangebyscore achievements 0 60
1) "xiaocao"
2) "xiaoqing"
3) "xiaolv"

127.0.0.1:6379> zrangebyscore achievements 90 100
1) "xiaobai"
2) "xiaolan"

8.删除成员

语法:

  • zrem key member1
  • zrem key member1 member2 member3 ....

例如:从achievements中删除xiaoming的数据

zrem achievements xiaoming

9.删除指定数量的成员

语法:
zpopmin key [count] # 删除指定数量的成员,从最低score开始删除
zpopmax key [count] # 删除指定数量的成员,从最高score开始删除

# 如果不指定count,则删除一个成员,zpopmin表示从score分数最低开始删除,而zpopmax则表示从score分数最高开始删除
127.0.0.1:6379> zpopmin achievements 
1) "xiaocao"
2) "0"

127.0.0.1:6379> zpopmax achievements
1) "xiaolan"
2) "99"


# 从achievements中提取并删除成绩最低的2个数据
127.0.0.1:6379>  zpopmin achievements 2
1) "xiaoqing"
2) "54"
3) "xiaolv"
4) "60"


# 从achievements中提取并删除成绩最高的2个数据
127.0.0.1:6379> zpopmax achievements 2
1) "xiaobai"
2) "93"
3) "xiaohui"
4) "87"

各种数据类型在开发中的常用业务场景

针对各种数据类型它们的特性,使用场景如下:

  • 字符串string: 用于保存一些项目中的普通数据,只要键值对的都可以保存,例如,保存 session/jwt,定时记录状态,倒计时、验证码、防灌水答案
  • 哈希hash:用于保存项目中的一些对象结构/字典数据,但是不能保存多维的字典,例如,商城的购物车,文章信息,json结构数据
  • 列表list:用于保存项目中的列表数据,但是也不能保存多维的列表,例如,消息队列,秒杀系统,排队,浏览历史
  • 无序集合set: 用于保存项目中的一些不能重复的数据,可以用于过滤,例如,候选人名单, 作者名单
  • 有序集合zset:用于保存项目中一些不能重复,但是需要进行排序的数据, 例如:分数排行榜, 海选人排行榜,热搜排行

相关文章
|
9月前
|
存储 缓存 NoSQL
Redis常见面试题全解析
Redis面试高频考点全解析:从过期删除、内存淘汰策略,到缓存雪崩、击穿、穿透及BigKey问题,深入原理与实战解决方案,助你轻松应对技术挑战,提升系统性能与稳定性。(238字)
|
10月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
10月前
|
存储 缓存 NoSQL
Redis持久化深度解析:数据安全与性能的平衡艺术
Redis持久化解决内存数据易失问题,提供RDB快照与AOF日志两种机制。RDB恢复快、性能高,但可能丢数据;AOF安全性高,最多丢1秒数据,支持多种写回策略,适合不同场景。Redis 4.0+支持混合持久化,兼顾速度与安全。根据业务需求选择合适方案,实现数据可靠与性能平衡。(238字)
|
缓存 监控 NoSQL
Redis 实操要点:Java 最新技术栈的实战解析
本文介绍了基于Spring Boot 3、Redis 7和Lettuce客户端的Redis高级应用实践。内容包括:1)现代Java项目集成Redis的配置方法;2)使用Redisson实现分布式可重入锁与公平锁;3)缓存模式解决方案,包括布隆过滤器防穿透和随机过期时间防雪崩;4)Redis数据结构的高级应用,如HyperLogLog统计UV和GeoHash处理地理位置。文章提供了详细的代码示例,涵盖Redis在分布式系统中的核心应用场景,特别适合需要处理高并发、分布式锁等问题的开发场景。
676 42
|
10月前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
11月前
|
存储 缓存 人工智能
Redis六大常见命令详解:从set/get到过期策略的全方位解析
本文将通过结构化学习路径,帮助读者实现从命令语法掌握到工程化实践落地的能力跃迁,系统性提升 Redis 技术栈的应用水平。
|
12月前
|
存储 缓存 NoSQL
Redis 核心知识与项目实践解析
本文围绕 Redis 展开,涵盖其在项目中的应用(热点数据缓存、存储业务数据、实现分布式锁)、基础数据类型(string 等 5 种)、持久化策略(RDB、AOF 及混合持久化)、过期策略(惰性 + 定期删除)、淘汰策略(8 种分类)。 还介绍了集群方案(主从复制、哨兵、Cluster 分片)及主从同步机制,分片集群数据存储的哈希槽算法。对比了 Redis 与 Memcached 的区别,说明了内存用完的情况及与 MySQL 数据一致性的保证方案。 此外,详解了缓存穿透、击穿、雪崩的概念及解决办法,如何保证 Redis 中是热点数据,Redis 分布式锁的实现及问题解决,以及项目中分布式锁
331 1
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
696 6
|
存储 缓存 NoSQL
Redis中的常用命令-get&set&keys&exists&expire&ttl&type的详细解析
总的来说,这些Redis命令提供了处理存储在内存中的键值对的便捷方式。通过理解和运用它们,你可以更有效地在Redis中操作数据,使其更好地服务于你的应用。
621 17
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。

推荐镜像

更多
  • DNS