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编码结构存储。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目模块十七:HttpServer模块

一、项目模块设计思路 目的:实现HTTP服务器搭建 思想:设计请求路由表,记录请求方法与对应业务的处理函数映射关系。用户实现请求方法和处理函数添加到路由表,服务器只接受请求并调用用户的处理函数即可。 处理流程: …

vue项目npm run serve出现【- Network: unavailable】(从排查到放弃)

1. 问题现象 环境: 系统:win11node:v16.20.2“vue”: “2.6.10” 执行npm run serve启动vue项目,期望: App running at:- Local: http://localhost:9528/ - Network: http://x.x.x.x:9528/实际: App runn…

喜报|超维机器人荣获昇腾AI创新大赛铜奖

近日,在备受瞩目的昇腾AI创新大赛中,超维机器人凭借扎实的技术实力和创新产品,荣获大赛铜奖。这一荣誉不仅展现了超维机器人在智能巡检领域的技术创新与突破,也标志着超维机器人的智能巡检解决方案在人工智能领域获得了广泛认可&a…

编程初学者的第一个 Rust 系统

编程初学者的第一个 Rust 系统 对编程初学者而言,存在一个 “第一个系统” 的问题,如果没有学会第一个系统,编程初学者是学不会编程的。原因是,现实生活里的应用程序都是有一定体量的,不是几十行,几百行的…

单元测试、集成测试、系统测试有什么区别

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 单元测试、集成测试、系统测试有什么区别 1、粒度不同 集成测试bai粒度居中,单元测试粒度最小,系统du测试粒度最大。 2、测试方式不同…

Java面试要点16 - 面向对象基础:类与对象

本文目录 一、引言二、类的定义与对象创建三、成员变量与封装四、构造方法五、this关键字六、静态成员七、总结 一、引言 面向对象编程是Java的核心特性之一,它通过类和对象的概念来组织和管理代码,使代码更加模块化、可复用和易于维护。本文将深入探讨…

【免越狱】iOS砸壳 可下载AppStore任意版本 旧版本IPA下载

软件介绍 下载iOS旧版应用,简化繁琐的抓包流程。 一键生成去更新IPA(手机安装后,去除App Store的更新检测)。 软件界面 支持系统 Windows 10/Windows 8/Windows 7(由于使用了Fiddler库,因此需要.Net环境…

LeetCode 热题100 之 多维动态规划

1.不同路径 思路分析:动规五部曲 dp数组定义:dp[i][j]表示从起点(0,0)到位置(i,j)的路径数量递推公式:dp[i][j] dp[i-1][j] dp[i][j-1] 从 (i-1, j) 位置到 (i, j) 需要走一步向下的路径。从 (i, j-1) 位…

文件操作(3)

前言,在上篇博客介绍了如何正确的打开一个文件和关闭一个文件,今天我们来学习如何在文件中输出和输入数据。 对文件数据的读写可以分为顺序读写和随机读写。顺序读写,即挨着顺序对文件中的数据进行输入或输出。 在这片博客中,我们…

Openstack7--安装消息队列服务RabbitMQ

只需要在控制节点安装 安装RabbitMQ yum -y install rabbitmq-server 启动RabbitMQ并设置开机自启 systemctl start rabbitmq-server;systemctl enable rabbitmq-server 创建 rabbitmq 用户 并设置密码为 000000 rabbitmqctl add_user rabbitmq 000000 如果你不慎创错了…

Unity图形学之Shader2.0 模板测试

1.模版测试:符合条件的 通过 不符合条件的 像素 丢弃 比较公式: if((referenceValue&readMask) comparisonFunction (stencilBufferValue&readMask)) 通过像素 else 抛弃…

020_Servlet_Mysql学生选课系统(新版)_lwplus87

摘 要 随着在校大学生人数的不断增加,教务系统的数据量也不断的上涨。针对学生选课这一环节,本系统从学生网上自主选课以及课程发布两个大方面进行了设计,基本实现了学生的在线信息查询、选课功能以及教师对课程信息发布的管理等功能&…

SpringBoot教程(二十五) | SpringBoot配置多个数据源

SpringBoot教程(二十五) | SpringBoot配置多个数据源 前言方式一:使用dynamic-datasource-spring-boot-starter引入maven依赖配置数据源动态切换数据源实战 方式二:使用AbstractRoutingDataSource1. 创建数据源枚举类2. 创建数据源…

Python 正则表达式进阶用法:分组与引用详解

Python 正则表达式进阶用法:分组与引用详解 正则表达式是一种用于字符串匹配和处理的强大工具。它不仅能识别简单的文本模式,还能通过更高级的特性来完成复杂的文本处理任务。本文将深入探讨 Python 正则表达式中的“分组”和“引用”——两个在高级匹配…

米家通过HomeAssistant控制笔记本电脑开关机

米家通过HomeAssistant控制笔记本电脑开关机 配置HomeAssistant配置EMQX mqtt自动化配置电脑关机实现电脑开机实现(网络唤醒WOL包) 环境准备: HomeAssistant:能配置接入米家的设备,我这里采用fnos安装MQTT服务器&…

前端环境配置

对于换公司的小伙伴来讲,重新安装环境,百度或许稍微有点麻烦,本文章让你无脑式直接操作,保证环境畅通无阻。 1.安装nvm-setup 该插件是一款管理nodeJs的包,无需你单独下载nodeJs去安装,只需要下载安装此…

[CKS] K8S AppArmor Set Up

最近准备花一周的时间准备CKS考试,在准备考试中发现有一个题目关于AppArmor Pod操作权限的问题。 ​ 专栏其他文章: [CKS] Create/Read/Mount a Secret in K8S-CSDN博客[CKS] Audit Log Policy-CSDN博客 -[CKS] 利用falco进行容器日志捕捉和安全监控-CSDN博客[CKS] …

提升自然排名的有效策略与方法

内容概要 在数字营销的快速发展背景下,自然排名的提升日益显得重要。自然排名不仅影响网站的流量,同时也直接关系到品牌的曝光度和市场竞争力。针对这个主题,我们将探讨多个关键因素,帮助读者更好地理解自然排名的重要性及其影响…

golang go语言 组建微服务架构详解 - 代码基于开源框架grpc+nacos服务管理配置平台

整体介绍: 本文主要介绍如何用go语言 来组建微服务的框架,grpc服务管理 示例框架 代码由grpcnacos go sdk 组成。 grpc负责将调用序列化并传递到远端,nacos负责服务发现和服务管理。 grpc和nacos都是开源产品。代码复制下来就能跑。 微服…

软件测试项目实战

软件测试是使用人工或者自动的手段来运行或者测定某个软件系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。 在软件投入使用前,要经过一系列的严格测试,才能保证交付质量。 一、引言 1.编写目的 本文档…