36.Redis核心设计原理

本文针对前面的讲解做一次总结

1.Redis基本特性

    1.非关系型键值对数据库,可以根据键以O(1)的时间复杂度取出或插入关联值

    2.Redis的数据是存在内存中的

    3.键值对中键的类型可以是字符串,整型,浮点型等,且键是唯一的

    4.键值对中的值类型可以是字符串,哈希,列表,集合,排序集合等

    5.Redis内置了复制,磁盘持久化,LUA脚本,事务,SSL,ACL,客户端缓存,客户端代理等功能

    6.通过Redis哨兵和Redis集群模式提供高可用性

2.Redis应用场景

2.1 缓存

可以作为缓存使用,数据存在内存中,数据存取效率非常高

2.2 计数器

实现计数器功能。Redis 这种内存型数据库的读写性能非常高可以对 String 进行自增自减运算,很适合存储频繁读写的计数量。

2.3 分布式ID生成

利用自增特性一次请求一个大一点的步长如 incr 2000,缓存在本地使用,用完再请求。

2.4 海量数据统计

位图_(bitmap):存储是否参过某次活动,是否已读谋篇文章,用户是否为会员,日活统计

2.5 会话缓存

可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

2.6 分布式队列/阻塞队列

List 是一个双向链表,可以通过 lpush/rpush 和 rpop/lpop 写入和读取消息。可以通过使用brpop/blpop 来实现阻塞队列。

2.7 分布式锁实现

在分布式场景下,无法使用基于进程的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的SETNX 命令实现分布式锁。

2.8 热点数据存储

最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据。

2.9 社交类需求

Set 可以实现交集,从而实现共同好友等功能,Set通过求差集,可以进行好友推荐,文章推荐。

2.10 排行榜

sorted set可以实现有序性操作,从而实现排行榜等功能。

2.11 延迟队列

使用sorted set(zset),使用 【当前时间戳 +需要延迟的时长】做score,消息内容作为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数据做轮询处理。消费完再删除任务 rem keymember

3.Redis键(Key)存储

所有的键都是String类型,都存储在buf里面,参考下面DB存储结构

4.Redis(Value)DB存储

redis的数据结构更偏向于map,在redis更具象化叫做dict,通过key找到value,存储海量数据;存储结构包括

1.数组:O(1)

2.链表: O(N)

4.1 String

Redis 3.2以前

    C语言中使用字符串数组存储 char buf[] = "xiehao\0";但是C语言有个问题,在read键时,可能会漏读String键的长度,所以redis重新定义了一个SDS存储方式:

如下以键“xiehao”的键的存储位案例分析;

在 C语言中存储 C:char data[] = "xiehao\0",默认结尾会带一个“\0”;

SDS:

free:0

len:6

char buf [] = "xiehao"

当扩容free长度不够时

将键"xiehao"变成"xiehao123",数组长度会自动计算多一些( 6+3)*2 =18

SDS:

free: 9

len :9

char buf[]="xiehao123"

当扩容free长度够用时

如果再次扩容变成"xiehao123456",则增加了3个长度,判断free剩余长度可以容纳,则直接使用free,不需要扩容

SDS:

free: 6

len :12

char buf[]="xiehao123456"

当扩容到1024 *1024(也就是内存为1M时)则不会在继续扩容

Redis 3.2后

len:长度

buf: 数据

alloc:buf分配的长度

flags:1字节 类型和业务数据长度,根据类型指向定义不同长度的内存;

类型有: sdshrd5 、 sdshrd8、 sdshrd16 、 sdshrd32 、 sdshrd64

使用SDS优点:

1.二进制安全的数据结构;

2.提供了内存预分配机制,避免了频繁的内存分配

3.兼容C语言的函数库

4.2 Hash

    Hash数据结构根据Hash(key)进行随机散列,并且将hash值变成自然数,这样可以将自然数作为索引来定位数据,大大提高效率;若发生hash碰撞,则进行链表关联;

例如:

创建一个大的数组:

arr[4]

hash( key)->自然数[大]%4=「0,arr.size]

1.任意相同的输入,一定能得到相同的输出

2.不同的输入,有可能得到相同的输出

定义3个键值对 (k1,v1)(k2,v2),(k3,v3)

hash(k1)%4=0

hash(k2)%4=1

hash(k3)%4=1

arr[0]->(k1,v1,next->null)

arr[1]->(k3,v3,next ->k2 )(k2,v2,next ->null)

链表 :redis:头插入方式

Redis 有16个DB

typedef struct redisDb{

dict *dict; (k-v)

dict *expires; (过期时间)

dict *blocking keys; (阻塞队列

dict *ready keys; (客户端

dict *watched_keys; (事务处理

int id; (SELECT * 命令 - 数据库索引

long long avg_ttl; (数据统计、遍历等

unsigned long expires_cursor;

list *defrag _later;

}redisDb;

typedef struct dict{

dictType *type; (类型

void *privdata;

dictht ht[2]; (扩容

long rehashidx; (渐进式rehash)

unsigned long iterators;

}dict;

typedef struct dictht{

dictEntry **table;

unsigned long size;

unsigned long sizemask;

unsigned long used;

}dictht;

typedef struct dictEntry{

void *key;

union{

void *val;

uint64t u64;

int64t s64;

double d;

}V;

struct dictEntry *next;

}dictEntry;

typedef struct redisObject{

unsigned type:4; (约束类型

unsigned encoding:4; (数据类型

unsigned Iru:LRU BITS;

int refcount;

void *ptr; (数据存储位置

}robj;

4.3 List

List存储结构采用quickList(双端链表) 和 zipList存储;数据结构K-V(array)

zipList

zibytes: 4字节 存多少数据

zltail:尾节点的索引

zllen:有多少元素

zlend:1字节 数据结尾标识

prerawlen: 前一个数据的信息

len: 当前数据的类型

data:当前的数据

quickList:

head:

tail

count:

length:

quickListNode:节点数据

zl:ziplist的数据

单个ziplist节点最大能存储  8kb  ,超过则进行分裂,将数据存储在新的ziplist节点中

hash

4.4 Set

Set为无序的,自动去重的集合数据类型,Set 数据结构底层实现为一个value为x`的字典(dict),当数据可以用整形表示时,Set集合将被编码为intset数据结构。两个条件任意满足时Set将用hashtable存储数据。K - V(array)

1:元素个数大于set-max-intset-entries;

2:元素无法用整形表示;

typedef struct intset{

uint32t encoding;

uint32t length;

int8t contents[];

}intset;

encoding:编码类型

length:元素个数

contents[]:元素存储

整数集合是一个有序的,存储整型数据的结构。整型集合在Redis中可以保存int16t,int32 t,int64t类型的整型数据,并且可以保证集合中不会出现重复数据。

4.5 Zset

ZSet 为有序的,自动去重的集合数据类型,ZSet 数据结构底层实现为字典(dict)+跳表(skiplist),当数据比较少时,用ziplist编码结构存储。K-V(array)

zipList

zset-max-ziplist-entries 128/元素个数超过128,将用skiplist编码

zset-max-ziplist-value64//单个元素大小超过64 byte,将用skiplist编码

skipList

typedef struct zskiplist{

struct zskiplistNode *header,(头节点,做索引,不存数据)

*t ail; (尾节点,会

存数据)

unsigned long length;(元素个数)

int level; (层高)

}zskiplist;

跳表算法:

数据项:N

index1 : N/2

index2 : N/2^2

index3: N/2^3

indexk: N/2^k

N/2^K = 2

2^K = N/2

k = log2 N/2

k = logN

ZSet  为有序的,自动去重的集合数据类型,ZSet 数据结构底层实现为 字典(dict) + 跳表(skiplist) ,当数据比较少时,用ziplist编码结构存储。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/13451.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

《人工智能网络安全现状(2024)》深度解读:机遇、挑战与应对策略

在当今数字化浪潮汹涌澎湃的时代,人工智能(AI)与网络安全已然深度交融,二者相互作用所塑造的发展态势正深刻重塑着我们的信息安全格局。《人工智能网络安全现状(2024)》这份报告恰似一盏明灯,为…

光控资本 :股票支撑位是什么?股票支撑位怎么找?

股票支撑位是指在股票价格的前史K线走势有两次或者两次以上,出现下跌到某一方位,股票就出现反弹的走势,则投资者可以把这个方位称为支撑位,支撑位阐明下方托单较多,个股无法持续下跌,在托单的影响下&#x…

网站小程序app怎么查有没有备案?

网站小程序app怎么查有没有备案?只需要官方一个网址就可以,工信部备案查询官网地址有且只有一个,百度搜索 "ICP备案查询" 找到官方gov.cn网站即可查询! 注:网站小程序app备案查询,可通过输入单位…

STM32+AI语音识别智能家居系统

基于 STM32 和 AI 语音识别的智能家居系统的详细硬件和软件设计,包括各个模块的详细描述和代码示例。 一、硬件设计 1. 微控制器(STM32): 选择 STM32F7 系列或更高性能的芯片,如 STM32F767ZIT6,以满足处理…

【初阶一】初识c语言

【初阶一】初识c语言 一、为什么学C语言?二、学习前的准备1.搭建编译环境以及使用2.代码库GitHub/Gitee创建以及使用3.写博客的作用以及教学 三、个人感悟 一、为什么学C语言? C语言是一门经久不衰的计算机编程语言,有句话叫:万物…

Linux DRM 那些事 - HDMI 接口 DTS 配置

本文基于RockPI 4A单板Debian系统 Linux 4.4 内核介绍DRM框架HDMI接口DTS配置。 在DTS中主要实现:HDMI的使能、VOP绑定、IOMUX引脚配置和HDMI控制器配置。 一、HDMI 配置 文件:arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi #include "rk3…

QT仿QQ聊天项目,第三节,实现聊天界面

一,界面控件示意图 界面主要由按钮QPushButton,标签QLabel,列表QListWidget 要注意的是QListWidget既是实现好友列表的控件,也是实现聊天气泡的控件 二,控件样式 QPushButton#btn_name {border:none;}QPushButton#btn_close {border:1px;bac…

前端学习八股资料CSS(二)

更多详情:爱米的前端小笔记,更多前端内容,等你来看!这些都是利用下班时间整理的,整理不易,大家多多👍💛➕🤔哦!你们的支持才是我不断更新的动力!找…

项目笔记:在stm32f103c8上用DMA控制串口收发

一、传统串口收发与引入DMA控制的区别 传统串口收发每一步都经过CPU处理和控制,当总线数据量大且频繁时CPU要反复地进入中断中处理,而引入DMA的差异就在于DMA会自动处理这个过程,并不需要占用CPU。 二、在不同芯片上所包含的DMA数量不同 对于…

基于SpringBoot的“原创歌曲分享平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“原创歌曲分享平台”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 平台功能结构图 平台首页界面图 用户注册界面…

CLion配置QT开发环境

一、将qmake工程转为cmake工程(方法一:用工具转换并做适当修改) 1、工具链接:链接:https://pan.baidu.com/s/1grW2QY3sW8X2JaHWM_ePPw 提取码:7at4 工具源码:https://github.com/milahu/qmake2cmake 2、执行…

【动手学电机驱动】 STM32-FOC(7)基于 MCSDK6.0 控制与调试速度环

STM32-FOC(1)STM32 电机控制的软件开发环境 STM32-FOC(2)STM32 导入和创建项目 STM32-FOC(3)STM32 三路互补 PWM 输出 STM32-FOC(4)IHM03 电机控制套件介绍 STM32-FOC(5&…

力扣 LeetCode 142. 环形链表II(Day2:链表)

解题思路&#xff1a; 使用set判断是否重复添加&#xff0c;如果set加入不进去证明之前到达过该节点&#xff0c;有环 public class Solution {public ListNode detectCycle(ListNode head) {Set<ListNode> set new HashSet<>();ListNode cur head;while (cur …

基于Ubuntu2410脚本搭建OpenStack-D版

openstack 初始化环境安装数据库、memcahe、rabbitmq等服务安装keystone服务安装glance服务安装placement服务安装nova服务安装neutron服务安装horizon服务启动云主机 本次实验使用单节点搭建&#xff0c;Ubuntu2410系统&#xff1a;搭建openstack-D版&#xff0c;采用ovs网络组…

Vue 3 在现代前端开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Vue 3 在现代前端开发中的应用 Vue 3 在现代前端开发中的应用 Vue 3 在现代前端开发中的应用 引言 Vue 3 概述 定义与原理 发展历…

QT鼠标事件

QT鼠标事件 1.概述 这篇文章介绍如何使用事件和获取事件的信号 2.创建项目 创建一个widget类型项目&#xff0c;在widget.ui文件中添加一个label控件 然后在项目名称上右键选择Add new... 添加文件&#xff0c;选择 C Class 自定义类名Mylabel&#xff0c;选择基类Base …

VUE tab栏选中状态与滚动项展示状态对应

实现效果 实现思路 记录滚动容器、滚动项的ref点击某一项tab时&#xff0c;滚动对应项到界面上监听滚动容器滚动&#xff0c;计算展示在界面的滚动项&#xff0c;选中对应tab项 关键代码 html <!-- tab栏 --> <a-tabs id"template-tab" v-model:activeK…

手动安装Ubuntu系统中的network-manager包(其它包同理)

自己手闲把系统中的network-manager包给删了&#xff0c;导致的结果就是Ubuntu系统彻底没有网络。结果再装network-manager时&#xff0c;没有网络根本装不了&#xff0c;网上的方法都试了也没用&#xff0c;然后就自己源码装&#xff0c;这篇文章就是记录一下怎么手动下载包然…

Qt初识简单使用Qt

使用C代码实现hello world 之前介绍过用图形化界面的方式创建hello world&#xff0c;这里我们使用C代码的方式再来实现一次hello world。 如上&#xff0c;首先要先包含一个头文件。 在QT这里&#xff0c;每一个类都有一个对应的同名头文件。比如这里我就包含了 <QLabel&…

自定义集成ESXI网卡驱动

需要的软件&#xff1a; ESXi-Customizer-v2.7.2 集成工具&#xff0c;可以将vib网卡驱动加载到镜像中&#xff0c;不用敲命令了 VIB 网卡驱动 根据自己网卡的型号自行下载 ESXi-Customizer-v2.7.2 软件地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1v5aI9T-Tl5…