【redis】redis常见数据结构及其底层,redis单线程读写效率高于多线程的理解,

redis常用数据结构及底层

  • string字符串、list链表、set无序集合、zset有序集合、hash哈希

1.string

  • 底层结构是SDS简单动态字符串

    struct sdshdr {
    int len; // 已用长度(字符串实际长度)
    int free; // 剩余可用空间
    char buf[]; // 数组,存储实际字符数据
    };

  • 相较于c字符串 ,它通过lenfree 字段实现O(1)长度查询,自动扩容,支持二进制存储

2.list

  • 是一个有序可重复 链表结构,会根据数据量和长度 ,自动选择不同数据结构,提升性能
  • 底层实现主要三种:
    • ziplist 压缩列表:redis3.2之前 ,元素数量<512 ,元素大小<64用压缩列表
    • linkedlist 双链表:redis3.2之前大数据量使用。
    • quicklist 快速列表:redis3.2之后 的默认存储,所有情况都用quicklist ,他是由多个ziplist 组成的双向链表

3.set

  • 无序 ,元素唯一 的集合类型,会根据数据量和内容 ,自动选择不同数据结构,提升性能
  • 底层两种实现:
    • intset 整数集合:适用于,都是整数数量<=512 。内存连续升序 排列,插入删除慢
    • hashtable 哈希表:适用于,多数据类型,数量多。标准hash,内存开销较大 (存储指针、哈希表结构)操作效率高

redis会根据数据自动切换,添加非整数/数量超512自动转hashtable,但是不会重新转回来

4.zset

  • 元素唯一 ,通过每个元素关联的score 自动排序 的结构,支持范围查找,范围排名等操作
  • 底层两种实现:
    • skiplist跳表:跳表提供有序遍历和范围操作
    • hashtable哈希表:哈希表提供快速查找

为什么用跳表 而不是红黑树?

实现简单插入删除性能好 (时间复杂度平均 O(log n)),更容易实现范围操作

  • 跳表原理 :通过分多个索引层加速查询底层完整 的有序链表 ,上层是索引层 ,每上一层减少一半,所以log₂n

    第3层:1 --------------------------> 9
    第2层:1 ------> 5 ------> 7 ------> 9
    第1层:1 -> 3 -> 5 -> 6 -> 7 -> 8 -> 9

5.hash

  • 一个键值对集合 ,常用于存对象(用户配置)等,会根据字段数量和内容自动选择不同的实现方式
  • 底层两种实现:
    • ziplist 压缩列表: 对象用压缩列表,(字段数<512,长度<64 )连续内存,占用少,节省空间,查询速度稍慢,字段超过阈值时,会自动转换为hashtable
    • hashtable 哈希表: 对象用hash表,读写效率更高

为什么小数据用 ziplist?

内存利用率高(无指针开销)
Redis 的哈希表如何扩容?

采用 渐进式扩容:扩容时同时保留新旧两个哈希表,分批次迁移数据

关于hash渐进式扩容,可以看我的这篇https://blog.csdn.net/m0_74282926/article/details/147522876

总结

数据类型 底层结构 说明
String int / embstr / raw(SDS) 根据长度和内容选择优化方式:int 表示整数,embstr 表示小字符串,raw 是通用 SDS
List ziplist(旧) / quicklist Redis 3.2+ 默认用 quicklist(多个 ziplist + 双向链表)
Set intset / hashtable 小量整数用 intset,其他情况用 hashtable
ZSet skiplist + hashtable 哈希表查找,跳表排序;两个结构同时维护
Hash ziplist / hashtable 字段少且短用 ziplist,否则用 hashtable

为什么redis单线程反而更快?

  1. 一个误区:并不是多线程一定比单线程快:
  • 在mysql中我们对于耗时较长的磁盘io 操作往往采用多线程并发执行,因为多线程产生的线程切换开销 往往于磁盘读写开销,所以并发等待可以提高效率;
  • 而redis是内存存储 ,本身单线程速度就很快,如果用多线程,
    涉及cpu上下文切换,锁竞争 ,这些耗时可能会超过内存中取数据的时间,从而降低性能。
  1. redis的性能瓶颈往往是网络或者内存 ,而非cpu,内存访问的速度高于切换线程的开销

  2. Redis 6.0 起引入了I/O 多线程模型,用于并行处理高并发 下,客户端的网络读写数据 (网络 I/O),但命令执行 仍是单线程,以保证数据一致性

网络 线程并发提速,核心逻辑线程保证安全。

  1. redis的数据协议 设计很高效 ,比如HashTable,理想情况下只需要O(1)的时间复杂度就可以找到数据。

例如 Hash 的 ziplist + hashtable 组合,在数据量小 时用 ziplist(节省内存),时转 HashTable(O(1) 查询)。

相关推荐
LilySesy3 分钟前
【案例总结】幽灵单据——消失的交货单号
数据库·ai·oracle·编辑器·sap·abap
看天走路吃雪糕3 分钟前
墨者:SQL注入实战-MySQL
数据库·mysql·base64·sql注入·sqlmap·墨者靶场·tamper
程序猿小D8 分钟前
Java项目:基于SSM框架实现的进销存管理系统【ssm+B/S架构+源码+数据库+毕业论文+远程部署】
java·数据库·mysql·ssm·jsp·毕业论文·进销存管理系统
HoHeHa16 分钟前
IDEA 手动下载安装数据库驱动,IDEA无法下载数据库驱动问题解决方案,IDEA无法连接数据库解决方案(通用,Oracle为例)
java·数据库·intellij-idea
22:30Plane-Moon19 分钟前
SQL 查询语法笔记
数据库·笔记·sql
一只小风华~33 分钟前
JavaScript:数组常用操作方法的总结表格
前端·javascript·数据结构·vue.js·算法
望获linux1 小时前
【Linux基础知识系列】第六十四篇 - 了解Linux的硬件架构
linux·运维·服务器·开发语言·数据库·操作系统·嵌入式软件
全栈小51 小时前
【数据库】使用Sql Server将分组后指定字段的行数据转为一个字段显示,并且以逗号隔开每个值,收藏不迷路
数据库·sql server
一匹电信狗1 小时前
【C++】手搓一个STL风格的vector容器
c语言·数据结构·c++·算法·leetcode·stl·visual studio
小小小白的编程日记1 小时前
C语言中的数据结构--栈和队列(2)
c语言·数据结构