当前位置: 首页 > news >正文

redis存储原理与对象模型

redis中的不同线程

redis单线程是指什么?

redis的所有命令处理都在同一个线程中完成

redis为什么采用单线程?

redis中存在多种数据结构存储value,如果采用多线程,加锁会很复杂、加锁力度不阿红控制,同时,采用多线程涉及频繁的cpu上下文切换,抵消多线程的优势。

redis 存储结构

redis采用hashtable组织其存储的kv数据

hashtable字典实现

redis 中 hashtable 组织是通过字典来实现的;hash 结构当节点超过 512 个或者单个字符串长度大于 64 时,hash 结构采用字典实现

数据结构

typedef struct dictEntry {void *key;union {void *val;uint64_t u64;int64_t s64;double d;} v;struct dictEntry *next;} dictEntry;typedef struct dictht {dictEntry **table;unsigned long size;// 数组长度
unsigned long sizemask; //size-1unsigned long used;//当前数组当中包含的元素
} dictht;typedef struct dict {dictType *type;void *privdata;dictht ht[2];long rehashidx; /* rehashing not in progress if rehashidx == -1 */int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) 
用于安全遍历*/} dict;

冲突

抽屉原理 :n+1个苹果放在 n 个抽屉中,苹果最多的那个抽屉至少有 2 个苹果;64位整数远大 于数组的长度,比如数组长度为 4,那么 1、5、9、1+4n 都是映射到1号位数组;所以大概 率会发生冲突

抽屉就是hashtable,苹果就是对应k-v对。

负载因子

负载因子 = used / size ;

used 是数组存储元素的个数,size是hashtable大小

负载因子越小,冲突越小;负载因子越大,冲突越大;

redis 的负载因子是 1;

扩容

如果负载因子 > 1,为了避免频繁的hash冲突,则会发生扩容,即申请一个新的的数组;扩容的规则是翻倍;

如果正在 fork(在 rdb、aof 复写以及 rdb-aof 混用情况下)时,会阻止扩容;但是此时若负载 因子 > 5,索引效率大大降低, 则马上扩容;这里涉及到写时复制原理

扩容后的渐进式rehash

rehash的原因

扩容后,hashtable的size发生改变,基于原来size的映射规则不在适用

rehash步骤

将 ht[0] 中的元素重新经过 hash 函数生成 64 位整数,再对 射到 ht [1] ;

渐进式rehash的原因

当 hashtable 中的元素过多的时候,不能一次性 rehash 到 ht[1] ;这样会长期占用 redis,其他 命令得不到响应;所以需要使用渐进式 rehash;

渐进式规则

 1. 分治的思想,将 rehash 分到之后的每步增删改查的操作当中;

2. 在定时器中,最大执行一毫秒 rehash ;每次步长 100 个数组槽位;

处于渐进式 rehash 阶段时,不会会发生扩容缩容

缩容

如果负载因子 < 0.1 ,则会发生缩容;缩容的规则是恰好包含 used 的 2^n

恰好的理解:假如此时数组存储元素个数为 9,恰好包含该元素的就是2^{4} ,也就是 16;

redis-value存储转换

跳表

理想跳表到概率跳表

redis跳表

redis IO多线程处理

为什么要采用IO多线程?

多个连接同时发送数据到redis时,会导致IO密集操作(read和send)和cpu密集型操作(decode和encode),如果采用单线程处理,就只能串行的处理每个连接的数据,但是read、decode、encode和send是可以并行执行的。

处理流程

1.主线程将IO密集型任务和cpu密集型任务放入全局队列中,并分配给每个IO线程并行执行。

2.所有的命令处理由一个线程单独执行

3.结果处理再交由每个IO线程执行。

redis的单线程为什么高效?

1.采用hashtable,使其增删改查操作时间复杂度为O(1),同时采用渐进式rehash,避免长时间对redis的占用。

2.对不同value采用高效的数据结构,同时基于节点数量会对数据结构进行切换。

3.采用高效的reactor网络模型,基于IO多路复用,实现对网络多客户端连接的快速响应。

柔性数组

https://github.com/0voice

http://www.dtcms.com/a/334800.html

相关文章:

  • 《A Practical Guide to Building Agents》文档学习
  • 数学建模:智能优化算法
  • PostgreSQL——事务处理与并发控制
  • CVE-2021-4300漏洞复现
  • 海康机器人3D相机的应用
  • ZKmall开源商城的数据校验之道:用规范守护业务基石
  • Vue 3与React内置组件全对比
  • 【lucene】SegmentInfos
  • 《Leetcode》-面试题-hot100-技巧
  • 科研工具的一些注意事项
  • 【minio】一、Linux本地部署MinIO
  • stringstream + getline()实现字符串分割
  • Java 10 新特性及具体应用
  • 二分查找。。
  • 【大语言模型 02】多头注意力深度剖析:为什么需要多个头
  • Python 类元编程(元类的特殊方法 __prepare__)
  • nflsoi 8.16 题解
  • 【数据结构】-2- 泛型
  • Python - 100天从新手到大师:第十一天常用数据结构之字符串
  • Java实现汉诺塔问题
  • AI Agents 2025年十大战略科技趋势
  • 【嵌入式C语言】六
  • .net印刷线路板进销存PCB材料ERP财务软件库存贸易生产企业管理系统
  • mit6.824 2024spring Lab1 MapReduce
  • 衡石使用指南嵌入式场景实践之仪表盘嵌入
  • 3 统一建模语言(UML)(上)
  • 力扣 hot100 Day75
  • 动手学深度学习(pytorch版):第三章节—线性神经网络(6) softmax回归的从零开始实现
  • 基于深度学习的老照片修复系统
  • 嵌入式硬件篇---电源电路