我随意写,你随意看。

林老头儿

但愿绝望和无奈远走高飞

Fork me on Gitee

Redis基本数据结构

Redis系列:

  1. Redis安装和配置
  2. Redis基本数据结构
  3. Redis核心原理
  4. Redis集群演变和集群部署
  5. Redis高可用集群之水平扩展

Redis 有 5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。

image-20200317224020905

一、String字符串

字符串 string 是 Redis 最简单的数据结构。Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据。不同类型的数据结构的差异就在于 value 的结构不一样。字符串结构使用非常广泛,一个常见的用途就是缓存用户信息。我们将用户信息结构体使用 JSON 序列化成字符串,然后将序列化后的字符串塞进 Redis 来缓存。同样,取用户信息会经过一次反序列化的过程。

键值对:

127.0.0.1:6379> set name lin
OK
127.0.0.1:6379> get name
"lin"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)

批量键值对:可以批量对多个字符串进行读写,节省网络耗时开销

127.0.0.1:6379> set name1 lin
OK
127.0.0.1:6379> set name2 jin
OK
127.0.0.1:6379> mget name1 name2 name3 # 返回一个列表
1) "lin"
2) "jin"
3) (nil)
127.0.0.1:6379> mset name1 boy name2 girl name3 aaa
OK
127.0.0.1:6379> mget name1 name2 name3
1) "boy"
2) "girl"
3) "aaa"

过期和 set 命令扩展:可以对 key 设置过期时间,到点自动删除,这个功能常用来控制缓存的失效时间

127.0.0.1:6379> set name lin
OK
127.0.0.1:6379> get name
"lin"
127.0.0.1:6379> expire name 5 # 5s后过期
(integer) 1	# 等待5s后
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> setex name 5 lin # 直接在set时候设置5s过期
OK
127.0.0.1:6379> get name
"lin" # 等待5s后
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> setnx name lin	# 如果name不存在就执行set创建
(integer) 1
127.0.0.1:6379> get name
"lin"
127.0.0.1:6379> setnx name jin
(integer) 0 # set失败,因为name已经存在
127.0.0.1:6379> get name # name的值没有改变
"lin"

原子计数:如果 value 值是一个整数,还可以对它进行自增操作。自增是有范围的,它的范围是 signed long 的最大最小值,超过了这个值,Redis 会报错

127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> incr age
(integer) 31
127.0.0.1:6379> incrby age 5
(integer) 36
127.0.0.1:6379> incrby age -5
(integer) 31
127.0.0.1:6379> set lin 9223372036854775807 # Long.Max
OK
127.0.0.1:6379> incr lin
(error) ERR increment or decrement would overflow

二、list (列表)

Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n),这点让人非常意外。 当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。

Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

右边进左边出:队列

127.0.0.1:6379> rpush books python java golang
(integer) 3
127.0.0.1:6379> llen books
(integer) 3
127.0.0.1:6379> lpop books
"python"
127.0.0.1:6379> lpop books
"java"
127.0.0.1:6379> lpop books
"golang"
127.0.0.1:6379> lpop books
(nil)

右边进右边出:栈

127.0.0.1:6379> rpush books python java golang
(integer) 3
127.0.0.1:6379> rpop books
"golang"
127.0.0.1:6379> rpop books
"java"
127.0.0.1:6379> rpop books
"python"
127.0.0.1:6379> rpop books
(nil)

三、hash (字典)

Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。

hash 结构也可以用来存储用户信息,不同于字符串一次性需要全部序列化整个对象,hash 可以对用户结构中的每个字段单独存储。这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话就只能一次性全部读取,这样就会比较浪费网络流量。 hash 也有缺点,hash 结构的存储消耗要高于单个字符串,到底该使用 hash 还是字符串,需要根据实际情况再三权衡。

127.0.0.1:6379> hset books java "think in java"
(integer) 1
127.0.0.1:6379> hset books golang "think in go"
(integer) 1
127.0.0.1:6379> hset books python "think in python"
(integer) 1
127.0.0.1:6379> hgetall books
1) "java"
2) "think in java"
3) "golang"
4) "think in go"
5) "python"
6) "think in python"
127.0.0.1:6379> hlen books
(integer) 3
127.0.0.1:6379> hget books java
"think in java"
127.0.0.1:6379> hset books python "learning python"
(integer) 0	# 更新操作,返回0
127.0.0.1:6379> hget books python
"learning python"
127.0.0.1:6379> hmset books java "effect java" python "effect python"	# 列表插入
OK

四、set (集合)

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值NULL。 当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。

127.0.0.1:6379> sadd books python
(integer) 1
127.0.0.1:6379> sadd books python	# 因为set不可重复,返回0
(integer) 0
127.0.0.1:6379> sadd books java golang
(integer) 2
127.0.0.1:6379> smembers books # 顺序跟插入不一样,因为set是无序的。
1) "java"
2) "golang"
3) "python"
127.0.0.1:6379> sismember books java	# 查询某个value是否存在
(integer) 1
127.0.0.1:6379> sismember books rust
(integer) 0
127.0.0.1:6379> scard books	# 获取set的大小
(integer) 3
127.0.0.1:6379> spop books	# 弹出一个value
"java"
127.0.0.1:6379> scard books
(integer) 2
127.0.0.1:6379> smembers books
1) "golang"
2) "python"

五、zset (有序集合)

zset 类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。

zset 可以用来存粉丝列表,value 值是粉丝的用户 ID,score是关注时间。我们可以对粉丝列表按关注时间进行排序。

zset 还可以用来存储学生的成绩,value 值是学生的 ID,score 是他的考试成绩。我们可以对成绩按分数进行排序就可以得到他的名次。

127.0.0.1:6379> zadd books 9.0 "think in java"
(integer) 1
127.0.0.1:6379> zadd books 8.9 "java concurrency"
(integer) 1
127.0.0.1:6379> zadd books 8.6 "java cookbook"
(integer) 1
127.0.0.1:6379> zrange books 0 -1 # 按score排序输出,范围指定与python相似
1) "java cookbook"
2) "java concurrency"
3) "think in java"
127.0.0.1:6379> zcard books	# zset的大小
(integer) 3
127.0.0.1:6379> zscore books "java concurrency" # 获取指定value的score
"8.9000000000000004"	# score使用double存储,存在小数点精度问题
127.0.0.1:6379> zrank books "java concurrency" # 排名
(integer) 1
127.0.0.1:6379> zrangebyscore books 0 8.91 # 根据分值区间便利zset
1) "java cookbook"
2) "java concurrency"
127.0.0.1:6379> zrem books "java concurrency" # 删除value
(integer) 1
127.0.0.1:6379> zrange books 0 -1
1) "java cookbook"
2) "think in java"

六、其他高级命令

keys:全量遍历键,用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用

127.0.0.1:6379> set lin2 2
OK
127.0.0.1:6379> set lin1 1
OK
127.0.0.1:6379> set li1n 1
OK
127.0.0.1:6379> set li2n 2
OK
127.0.0.1:6379> keys *
1) "li1n"
2) "li2n"
3) "lin1"
4) "lin2"
127.0.0.1:6379> keys lin*
1) "lin1"
2) "lin2"
127.0.0.1:6379> keys li*n
1) "li1n"
2) "li2n"

scan:渐进式遍历键,scan 参数提供了三个参数,第一个是 cursor 整数值,第二个是 key 的正则模式,第三个是遍历的 limit hint。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。

127.0.0.1:6379> scan 0 match lin* count 4
1) "6" # 下一次的cursor
2) 1) "lin8"
   2) "lin4"
   3) "lin"
   4) "lin3"
127.0.0.1:6379> scan 6 match lin* count 4
1) "13"
2) 1) "lin6"
   2) "lin7"
   3) "lin1"
   4) "lin5"
127.0.0.1:6379> scan 13 match lin* count 4
1) "0" # 输出0,代表遍历结束
2) 1) "lin9"
   2) "lin2"

Redis存储键值对实际使用的是hashtable的数据结构

image-20200318114720937

Info:查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是:

  • Server 服务器运行的环境参数
  • Clients 客户端相关信息
  • Memory 服务器运行内存统计数据
  • Persistence 持久化信息
  • Stats 通用统计数据
  • Replication 主从复制相关信息
  • CPU CPU 使用情况
  • Cluster 集群信息
  • KeySpace 键值对统计数量信息
127.0.0.1:6379> info
# Server
redis_version:5.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:d05eea3b42d1beac
redis_mode:standalone
os:Darwin 19.3.0 x86_64
arch_bits:64
multiplexing_api:kqueue
atomicvar_api:atomic-builtin
gcc_version:4.2.1
process_id:31716
run_id:c63a31238057cc2a67844f29784014664d11a3ca
tcp_port:6379
uptime_in_seconds:5766
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:7444886
executable:/Users/jinchengll/soft/redis-5.0.7/./src/redis-server
......
posted @ 2020-03-19 08:16  林老头儿  阅读(683)  评论(0编辑  收藏  举报