回答

收藏

Redis 使用的底层数据结构是什么?

技术问答 技术问答 307 人阅读 | 0 人回复 | 2023-09-11

我试图在一个明确的列表中回答两个问题:5 U! o0 O0 i4 m, C2 c
[ol]Redis 使用的底层数据结构是什么?
( ?& ]* H- \- |+ i每种类型的主要优缺点/用例是什么?[/ol]所以,我读过Redis列表实际上是通过链表实现的。但对于其他类型,我不能挖掘任何信息。此外,如果有人偶然发现了这个问题,并且没有对修改或访问不同数据结构的优缺点进行高级总结,他们也会有一个完整的列表来解释什么时候最好使用特定类型?进行引用。
) i  R) A( h) [4 d具体来说,我希望概述所有类型:字符串、列表、集合zset 和哈希。
: E4 J' R& u, |                                                                2 G0 a2 P$ T6 h
    解决方案:                                                               
& X: \) A8 P2 w& [4 R                                                                我会试着回答你的问题,但我会从一开始可能看起来很奇怪的事情开始:如果你对 Redis 内部不感兴趣,你不要在意如何在内部实现数据类型。这是一个简单的原因:对于每个 Redis 操作,你会在文档中找到时间复杂性,如果你有一组操作和时间复杂性,那么你唯一需要的是一些关于内存使用的线索(因为我们有很多可能因数据而异的优化,获这些数据的最好方法是进行一些琐碎的现实世界测试)。: `* m, }8 ^6 v; T
但既然你问了,这是每个 Redis 实现数据类型的底层。
/ k+ I2 F/ _; s) m3 q  }3 l/ W5 T7 ?字符串是使用 C 动态字符串库已经实现,因此我们不需要为额外操作中的分配付费(更近)。例如,通过这种方式,我们有 O(N) 附加,而不是二次行为。9 v9 V& X, v; Z6 d: e! _7 d
列表用链表实现。
: R0 v" z! l& y- [集合哈希它是用哈希表实现的。) }/ n, Y# F& X1 [/ n( Y. {
排序集跳过列表(一种特殊类型的平衡树)实现。
然而,当列表、集合和排序集合的项目数量和最大值较小时,将使用不同的、更紧凑的代码。该代码因类型而异,但其特点是它是一个紧凑的数据块,通常强制 每个操作O(N) 扫描。因为我们只使用这种格式的小对象,这不是问题;扫描一个小 O(N) blob 是缓存无意识,所以其实很快。当元素太多时,编码会自动切换到机器编码(链表、哈希等)。! q8 D; k" j$ V0 w9 q, _! ]# H  h4 B2 v
但你的问题不仅仅是关于内部,你的观点是用什么类型来完成什么?.* B, B' o& N# A/ m7 S8 B
字符串这是所有类型的基本类型。List 是字符串列表, Set 是一组字符串,等等。
* L: m3 E& o- ^" {1 u+ |7 K想存放 HTML 页面的所有明显场景,以及当您想要避免转换已编码的数据时,Redis 字符串是个好主意。所以,比如你有 JSON 或 MessagePack,您可以将对象存储为字符串。Redis 2.你甚至可以在6 中使用 Lua 脚本操作此对象服务器端。) W6 G' a7 m4 [! _4 g* {2 y
另一 Redis 导出命令访问随机字节,甚至单位。例如,查看这篇优秀的博客文章:使用 Redis 的 Fast Easy 实时指标。3 V; Z' a9 i4 }
列表当您可能只触及列表的极端时,列表是好的:接近尾或接近头。由于随机访问速度慢,列表不适合分页内容,O(N)。因此,列表的良好用途是简单的队列和堆栈,或使用具有相同源和目标的 RPOPLPUSH 以旋转项目环处理循环中的项目。
! n$ G9 c5 L" n只想创建 N 收集项目上限时,列表也很好,通常当 N 很小时。
$ J: ^) _4 F- o( W' \6 N# _集合集合是一个无序的数据集合,所以每次你有一个项目集合,以一种非常快的方式检查集合的存在或大小是非常重要的。另一件很酷的事情是支持偷看或弹出随机元素(SRANDMEMBER 和 SPOP 命令)。
$ Z# |  k) z7 W4 Y4 s, U集合也可以很好的表达关系,比如用户 X 什么是朋友? 等等。但我们将看到,其他用于此类内容的好数据结构是排序集。' k& P) o  Z) h8 G8 m; J" M
集合支持复杂的操作,如交集和并集。因此,当您有数据并想要转换数据以获得一些输出时,这是一种计算使用 Redis 数据结构良好。0 `( L* r: Q: l
小集合以非常有效的方式编码。
2 m5 B7 J* s% m$ r( j" S哈希值哈希是由字段和值组成的表示对象的完美数据结构。 也可用于散列字段HINCRBY 以原子的形式增加。当你有对象时,如用户、博客文章或其他类型项目,如果你不想使用自己的代码,哈希很可能会去。JSON或类似的方法。
0 l- B2 S6 p/ \3 Z但请记住,Redis 非常高效地编码小散列,您可以要求 Redis 以非常快的方式原子地 GET、SET 或增加单个字段。0 c: w* @; J. Z  L
散列也可以用来表示链接的数据结构,并使用引用。例如,检查 lamernews.com 评论的实现。
: u5 y" |7 ~$ Y排序集排序集是除列表外唯一用于维护有序元素的数据结构。你可以用排序集做一些很酷的事情。例如,你可以在你的 Web 有各种各样的应用程序Top Something列表。按分数排名最高的用户,按页面浏览量排名最高的帖子,无论什么排名最高,但单个 Redis 实例将支持每秒大量插入和获取顶部元素的操作。7 ~2 |+ v+ r, M% a; \; X) H2 v
像常规集一样,排序集可以用来描述关系,但它们也允许你分页并记住项目列表的顺序。例如,如果我记得用户 X 朋友有一个排名集,我可以很容易地按照接受的友谊顺序记住他们。
# [# W6 I5 U/ u4 L0 ^7 D3 n8 _) C排序集适用于优先队列。
" |8 U, X- w6 H: {1 P: ^# P排序集就像一个更强大的列表,从列表中间插入、删除或获取总是很快。但它们使用更多的内存和 O(log(N)) 数据结构。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则