# 数据类型

redis 中,所有 key 都是字符串,讨论数据结构时,都是存储值的数据类型,常见的包括:

  • String:字符串、整数或浮点数。对整个字符串或字符串的一部分进行操作;对整数或浮点数进行自增或自减操作。
  • List:对链表的两端进行 push 和 pop 操作,读取单个或多个元素;根据值查找或删除元素;
  • Set:字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等。
  • Zset:字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素。
  • Hash:添加、获取、删除单个元素

关于集合的命令,有啥想不起就去搜。

# String

记住上一篇文章讲的几个命令即可: get,set,del,incr,decr,incrby,decrby

# List

可以实现消息队列,将任务存 PUSH 在 List 中,工作线程再 POP 操作将任务取出执行。

两边都可以增删节点,对应方法就是 L/RPUSHL/RPOP ,具体使用为:

127.0.0.1:6379> lpush mylist 1 2 ll ls mem
(integer) 5
127.0.0.1:6379> lrange mylist 0 -1	-- lrange 获取列表所有值
1) "mem"
2) "ls"
3) "ll"
4) "2"
5) "1"
127.0.0.1:6379> lindex mylist -1	-- lindex 根据索引获取元素 (0 开始),负数也可以,-1 表示最后一个
"1"
127.0.0.1:6379> lindex mylist 10        -- index 不在 mylist 的区间范围内
(nil)

还有一些骚操作:

-- 从前一个数组的最后取一个数出来放到另一个数组的头部,并返回元素
rpoplpush 当前数组 目标数组
-- 如果列表中没有元素,那么就等待,如果指定时间(秒)内被添加了数据,那么就执行 pop 操作,如果超时就作废,支持同时等待多个列表,只要其中一个列表有元素了,那么就能执行
blpop <key>... timeout

# Set

不同元素无序排列,直接看命令:

127.0.0.1:6379> sadd myset hao hao1 xiaohao hao	-- sadd 添加若干个成员
(integer) 3
127.0.0.1:6379> smembers myset	-- 返回所有成员
1) "xiaohao"
2) "hao1"
3) "hao"
127.0.0.1:6379> sismember myset hao	-- 判断集合 myset 是否有集合 hao 成员
(integer) 1
-- 随机移除一个幸运儿
spop <key>
-- 移除指定
srem <key> <value>...

集合之间的运算:

-- 集合之间的差集
sdiff <key1> <key2>
-- 集合之间的交集
sinter <key1> <key2>
-- 求并集
sunion <key1> <key2>
-- 将集合之间的差集存到目标集合中
sdiffstore 目标 <key1> <key2>
-- 同上
sinterstore 目标 <key1> <key2>
-- 同上
sunionstore 目标 <key1> <key2>
-- 移动指定值到另一个集合中
smove <key> 目标 value

# Hash

string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。

假设散列表名是 user:

  • 添加: hset user key1 val1
  • 获取值: hget user key1
  • 获取所有键值对: hgetall user
  • 移出键: hdel user key

# Zset

每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。

有序集合是通过两种数据结构实现:

  1. 压缩列表 (ziplist): ziplist 是为了提高存储效率而设计的一种特殊编码的双向链表。它可以存储字符串或者整数,存储整数时是采用整数的二进制而不是字符串形式存储。它能在 O (1) 的时间复杂度下完成 list 两端的 push 和 pop 操作。但是因为每次操作都需要重新分配 ziplist 的内存,所以实际复杂度和 ziplist 的内存使用量相关
  2. 跳跃表(zSkiplist): 跳跃表的性能可以保证在查找,删除,添加等操作的时候在对数期望时间内完成,这个性能是可以和平衡树来相比较的,而且在实现方面比平衡树要优雅,这是采用跳跃表的主要原因。跳跃表的复杂度是 O (log (n))。

相关命令:

  • 添加: zadd table key1 val1 score
  • 获取: zrange table key1
  • 删除: zrem table key1

因为都有一个分数值,所以可以根据分数值操作:

-- 通过分数段查看
zrangebyscore <key> start stop [withscores] [limit]
-- 统计分数段内的数量
zcount <key>  start stop
-- 根据分数获取指定值的排名
zrank <key> <value>

# 参考

https://pdai.tech/md/db/nosql-redis/db-redis-data-types.html

https://www.yuque.com/qingkongxiaguang/spring/nka2vz#List