首页 > 编程知识 正文

redis hash数据结构(redis中key的数据结构)

时间:2023-05-06 04:22:53 阅读:92658 作者:4954

前言

列表(list )类型用于存储多个规则字符串。 在Redis中,可以在列表的两端进行插入(push )和弹出)操作,还可以获取指定范围的元素列表、获取指定索引的下标元素等。

列表是一种相对灵活的数据结构,可以充当堆栈和队列,在实际开发中有许多应用场景。

如图所示,a、b、c、d、e五个要素从左到右构成了有顺序的列表。 列表中的每个字符串称为元素,一个列表最多可以包含2 >2 ^ 32 - 1个元素。

的插入和弹出操作

获取、剪切和删除列表的操作 )。

正文

1.相关命令

下面基于列表中的五种操作类型说明命令。

1.1 .添加命令

1.1.1 .从右插入要素

r推式键值[值. ]下面的代码从右向左插入元素c、b和a。

127.0.0.1:6379 rpushlistkeycba

(整数) 3

lrange 0 -1命令可以从左到右获取列表中的所有元素。

127.0.0.1:6379 lrangelistkey0- 1

1 ) c )是指

2 ) b )是指

3 )在a )中

1.1.2 .从左侧插入要素

lpush key value [value .]的使用方法与rpush相同,但从左侧插入,在此不作说明。

1.1.3 .在某个要素之前或之后插入要素

linsertkeybefore|afterpivotvaluelinsert命令从列表中查找等于第一个pivot的元素,并在该元素之前(before )或之后)插入新元素value。 例如,以下操作将在列表的元素b之前插入redis :

127.0.0.1:6379 linsertlistkeybeforebredis

(整数) 4

结果为4,表示当前列表的长度,当前列表如下所示:

127.0.0.1:6379 lrangelistkey0- 1

1 ) c )是指

2 )雷迪斯)雷迪斯

3 ) b )是指

4 ) ) a )。

1.2 .查询指令

1.2.1 .获取指定范围内的要素列表

lrange key start stoplrange动作可检索列表中指定索引范围的所有元素。

索引有两个特征。

其一,索引的下标从左到右分别为0到N-1,但从右到左分别为-1到-N。 其二,lrange的end选项包含自身,这与许多编程语言不包含end不太一样。 从左到右检索列表中的第二个到第四个元素后,可以执行以下操作:

127.0.0.1:6379 lrangelistkey 13

1 ) redis )是指

2 ) b )是指

3 )在a )中

要从右向左检索列表中的第一个到第三个元素,请执行以下操作:

127.0.0.1:6379 lrangelistkey-3-1

1 ) redis )是指

2 ) b )是指

3 )在a )中

1.2.2 .获取列表并指定索引下标的要素

lindex key index例如,当前列表的最后一个元素是a。

127.0.0.1:6379 lindexlistkey-1

' a '号运载火箭

1.2.3 .获取列表长度

llen key例如,以下示例的当前列表长度为4。

127.0.0.1:6379 LLEN列表密钥

(整数) 4

1.3 .删除命令

1.3.1 .从列表左侧弹出元素

lpop key弹出列表最左侧的元素c,弹出后列表将更改为redis、b和a,如下所示:

p>127.0.0.1:6379> lpop listkey

"c"

127.0.0.1:6379> lrange listkey 0 -1

1) "redis"

2) "b"

3) "a"

1.3.2. 从列表右侧弹出元素

rpop key

它的使用方法和 lpop 是一样的,只不过从列表 右侧 弹出元元素。

127.0.0.1:6379> lpop listkey

"a"

127.0.0.1:6379> lrange listkey 0 -1

1) "c"

2) "redis"

3) "b"

1.3.3. 删除指定元素

lrem key count value

lrem 命令会从 列表 中找到 等于 value 的元素进行 删除,根据 count 的不同分为三种情况:

count > 0:从左到右,删除最多 count 个元素。count < 0:从右到左,删除最多 count 绝对值 个元素。count = 0,删除所有。

例如向列表 从左向右 插入 5 个 a,那么当前 列表 变为 “阳光的热狗”,下面操作将从列表 左边 开始删除 4 个为 a 的元素:

127.0.0.1:6379> lrem listkey 4 a

(integer) 4

127.0.0.1:6379> lrange listkey 0 -1

1) "a"

2) "redis"

3) "b"

4) "a"

1.3.4. 按照索引范围修剪列表

127.0.0.1:6379> ltrim listkey 1 3

OK

127.0.0.1:6379> lrange listkey 0 -1

1) "redis"

2) "b"

3) "a"

1.4. 修改命令

1.4.1. 修改指定索引下标的元素

修改 指定索引下标 的元素:

lset key index newValue

下面操作会将列表 listkey 中的第 3 个元素设置为 mysql:

127.0.0.1:6379> lset listkey 2 mysql

OK

127.0.0.1:6379> lrange listkey 0 -1

1) "redis"

2) "b"

3) "mysql"

1.5. 阻塞操作命令

阻塞式弹出 操作的命令如下:

blpop key [key ...] timeoutbrpop key [key ...] timeout

blpop 和 brpop 是 lpop 和 rpop 的 阻塞版本,它们除了 弹出方向 不同,使用方法 基本相同,所以下面以 brpop 命令进行说明, brpop 命令包含两个参数:

key[key...]:一个列表的 多个键。timeout:阻塞 时间(单位:秒)。

对于 timeout 参数,要氛围 列表为空 和 不为空 两种情况:

列表为空

如果 timeout = 3,那么 客户端 要等到 3 秒后返回,如果 timeout = 0,那么 客户端 一直 阻塞 等下去:

127.0.0.1:6379> brpop list:test 3

(nil)

(3.10s)

127.0.0.1:6379> brpop list:test 0

...阻塞...

如果此期间添加了数据 element1,客户端 立即返回:

127.0.0.1:6379> brpop list:test 3

1) "list:test"

2) "element1"

(2.06s)

列表不为空:客户端会 立即返回。

127.0.0.1:6379> brpop list:test 0

1) "list:test"

2) "element1"

在使用 brpop 时,有以下两点需要注意:

其一,如果是 多个键,那么 brpop 会 从左至右 遍历键,一旦有 一个键 能 弹出元素,客户端 立即返回:

127.0.0.1:6379> brpop list:1 list:2 list:3 0

..阻塞..

此时另一个 客户端 分别向 list:2 和 list:3 插入元素:

client-lpush> lpush list:2 element2

(integer) 1

client-lpush> lpush list:3 element3

(integer) 1

客户端 会立即返回 list:2 中的 element2,因为 list:2 最先有 可以弹出 的元素。

127.0.0.1:6379> brpop list:1 list:2 list:3 0

1) "list:2"

2) "element2"

其二,如果 多个客户端 对 同一个键 执行 brpop,那么 最先执行 brpop 命令的 客户端 可以 获取 到弹出的值。

按先后顺序在 3 个客户端执行 brpop 命令:

客户端1:

client-1> brpop list:test 0

...阻塞...

客户端2:

client-2> brpop list:test 0

...阻塞...

客户端3:

client-3> brpop list:test 0

...阻塞...

此时另一个 客户端 lpush 一个元素到 list:test 列表中:

client-lpush> lpush list:test element

(integer) 1

那么 客户端 1 会获取到元素,因为 客户端 1 最先执行 brpop 命令,而 客户端 2 和 客户端 3 会继续 阻塞。

client> brpop list:test 0

1) "list:test"

2) "element"

有关 列表 的 基础命令 已经介绍完了,下表是相关命令的 时间复杂度:

2. 内部编码

列表类型的 内部编码 有两种:

2.1. ziplist(压缩列表)

当列表的元素个数 小于 list-max-ziplist-entries 配置(默认 512 个),同时列表中 每个元素 的值都 小于 list-max-ziplist-value 配置时(默认 64 字节),Redis 会选用 ziplist 来作为 列表 的 内部实现 来减少内存的使用。

2.2. linkedlist(链表)

当 列表类型 无法满足 ziplist 的条件时, Redis 会使用 linkedlist 作为 列表 的 内部实现。

2.3. 编码转换

下面的示例演示了 列表类型 的 内部编码,以及相应的变化。

当元素 个数较少 且 没有大元素 时,内部编码 为 ziplist:

127.0.0.1:6379> rpush listkey e1 e2 e3

(integer) 3

127.0.0.1:6379> object encoding listkey

"ziplist"

当元素个数超过 512 个,内部编码 变为 linkedlist:

127.0.0.1:6379> rpush listkey e4 e5 ... e512 e513

(integer) 513

127.0.0.1:6379> object encoding listkey

"linkedlist"

当某个元素超过 64 字节,内部编码 也会变为 linkedlist:

127.0.0.1:6379> rpush listkey "one string is bigger than 64 byte..."

(integer) 4

127.0.0.1:6379> object encoding listkey

"linkedlist"

Redis3.2 版本提供了 quicklist 内部编码,简单地说它是以一个 ziplist 为 节点 的 linkedlist,它结合了 ziplist 和 linkedlist 两者的优势,为 列表类型 提供了一种更为优秀的 内部编码 实现,它的设计原理可以参考 Redis 的另一个作者 Matt Stancliff 的博客 redis-quicklist。

3. 应用场景

3.1. 消息队列

通过 Redis 的 lpush + brpop 命令组合,即可实现 阻塞队列。如图所示:

生产者客户端 使用 lrpush 从列表 左侧插入元素,多个消费者客户端 使用 brpop 命令 阻塞式 的 “抢” 列表 尾部 的元素,多个客户端 保证了消费的 负载均衡 和 高可用性。

3.2. 文章列表

每个 用户 有属于自己的 文章列表,现需要 分页 展示文章列表。此时可以考虑使用 列表,因为列表不但是 有序的,同时支持 按照索引范围 获取元素。

每篇文章使用 mldxg结构 存储,例如每篇文章有 3 个属性 title、timestamp、content:

hmset acticle:1 title xx timestamp 1476536196 content xxxx

hmset acticle:2 title yy timestamp 1476536196 content yyyy

...

hmset acticle:k title kk timestamp 1476512536 content kkkk

向用户文章列表 添加文章,user:{id}:articles 作为用户文章列表的 键:

lpush user:1:acticles article:1 article:3 article:5

lpush user:2:acticles article:2 article:4 article:6

...

lpush user:k:acticles article:7 article:8

分页 获取 用户文章列表,例如下面 伪代码 获取用户 id=1 的前 10 篇文章:

articles = lrange user:1:articles 0 9

for article in {articles}

hgetall {article}

使用 列表 类型 保存 和 获取 文章列表会存在两个问题:

第一:如果每次 分页 获取的 文章个数较多,需要执行多次 hgetall 操作,此时可以考虑使用 Pipeline 进行 批量获取,或者考虑将文章数据 序列化为字符串 类型,使用 mget 批量获取。第二:分页 获取 文章列表 时, lrange 命令在列表 两端性能较好,但是如果 列表较大,获取列表 中间范围 的元素 性能会变差。此时可以考虑将列表做 二级拆分,或者使用 Redis 3.2 的 quicklist 内部编码实现,它结合 ziplist 和 linkedlist 的特点,获取列表 中间范围 的元素时也可以 高效完成。

3.3. 其他场景

实际上列表的使用场景很多,具体可以参考如下:

命令组合 对应数据结构 lpush + lpop Stack(栈) lpush + rpop Queue(队列) lpush + ltrim Capped Collection(有限集合) lpush + brpop Message Queue(消息队列) 小结

本文介绍了 Redis 中的 列表 的 一些 基本命令、内部编码 和 适用场景。通过组合不同 命令,可以把 列表 转换为不同的 数据结构 使用。

参考

《Redis 开发与运维》

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。