- string
- 字典Hash
- list
- 集合set
- 有序集合
- HyperLogLog
- Geo
- Pub/Sub
string
get/set 场景:
- session
- 通常的数据缓存
- 计数器
- 分布式锁 底层实现: 基于SDS数据结构实现,并没有使用单纯的c语言字符串。 原因:
- C语言字符串取长度要遍历
- C语言字符串增加/减少设计重新分配
- 不能保存图片等二进制信息
C 字符串 | SDS |
---|---|
获取字符串长度的复杂度为 O(N) 。 | 获取字符串长度的复杂度为 O(1) 。 |
API 是不安全的,可能会造成缓冲区溢出。 | API 是安全的,不会造成缓冲区溢出。 |
修改字符串长度 N 次必然需要执行 N 次内存重分配 | 修改字符串长度 N 次最多需要执行 N 次内存重分配。 |
只能保存文本数据。 | 可以保存文本或者二进制数据。 |
可以使用所有 <string.h> 库中的函数。 | 可以使用一部分 <string.h> 库中的函数。 |
字典Hash
hget/hset/hgetall
场景:
- 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。
rehash:
- 没执行BGSAVE/BGSAVEAOF命令的时候,设置负载因子=1
- 在执行BGSAVE/BGSAVEAOF命令的时候,为了避免消耗内存,提高了负载因子=5,因为在执行 BGSAVE 命令或 BGREWRITEAOF 命令的过程中, Redis 需要创建当前服务器进程的子进程, 而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率, 所以在子进程存在期间, 服务器会提高执行扩展操作所需的负载因子, 从而尽可能地避免在子进程存在期间进行哈希表扩展操作, 这可以避免不必要的内存写入操作, 最大限度地节约内存。
- hash函数:murmurhash2
渐进式rehash:
因为在进行渐进式 rehash 的过程中, 字典会同时使用 ht[0] 和 ht[1] 两个哈希表, 所以在渐进式 rehash 进行期间, 字典的删除(delete)、查找(find)、更新(update)等操作会在两个哈希表上进行: 比如说, 要在字典里面查找一个键的话, 程序会先在 ht[0] 里面进行查找, 如果没找到的话, 就会继续到 ht[1] 里面进行查找, 诸如此类。 另外, 在渐进式 rehash 执行期间, 新添加到字典的键值对一律会被保存到 ht[1] 里面, 而 ht[0] 则不再进行任何添加操作: 这一措施保证了 ht[0] 包含的键值对数量会只减不增, 并随着 rehash 操作的执行而最终变成空表。
有序集合
底层实现是跳跃表
redis跳跃表相关数据结构的介绍 跳表数据结构
跳跃表的增加节点、删除节点 跳跃表原理