Redis中的String编码转换底层原理及6.0新特性

String编码转换底层原理

String对象为什么把大于39字节或者44字节的字符串编码为raw,小于的时候编码为embstr?

在Redis3.2以前的版本中,SDS作为字符串类型中存储字符串内容的结构,源码如下:

3.2版本SDS结构

struct sdshdr {// 记录buf数组中已使用字节的数量// 等于SDS保存字符串的长度 4byteint len;// 记录buf数组中未使用字节的数量 4byteint free;// 字节数组,用于保存字符串 字节\0结尾的字符串占用了1bytechar buf[];
}

Redis对象头

一个字符串对象不仅仅包含SDS结构,还包含了RedisObject(Redis对象头),这时每个Redis对象都要携带的一种结构跟Java对象类似,Java对象也有相应的对象头,它的结构如下

// Redis对象
typedef struct redisObject {// 类型 4bits; 即【String、List、Hash、Set、Zset】中的一个unsigned type:4// 编码方式 4 bits, encoding表示对象底层所使用的编码unsigned encoding:4;// LRU时间(相对于server.lrulock) 24bits;unsigned lru:24;// 引用计数 Redis里面的数据可以通过引用计数进行共享 32bitsint refcount;// 指向对象的值 64bitvoid* ptr;
} robj; // 16bytes

操作系统中的内存分配

由于操作系统使用jmalloc和tmalloc进行内存的分配,而内存分配的单位都是2的N次方,所以是2,4,8,16,32,64,如果Redis采取32字节分配的化,那么32-16(RedisObject)-9(3.2版本的SDS)=7,相当于可使用字节数为7字节,Redis认为太过于小了,所以Redis采取分配的是64字节,即64-25=39。

SDS结构优化

在Redis之后的版本中,为了进一步优化字符串对象在一次操作系统的内存分配中扩大可使用的空间,又将sdshdr分为了sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64结构如下

struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
// 一些变量的定义 
#define SDS_TYPE_5  0
#define SDS_TYPE_8  1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4

结构示例图

  • sdshdr5的结构如图
    在这里插入图片描述
  • sdshdr8的结构如图
    在这里插入图片描述

疑惑解答

有人可能会问既然分出来这么多的结构,如果用sdshdr5的结构,那么64-16-1-1=46个字节,跟平常说的44个字节不一样,如果我们用sdshdr5的结构,那么这个结构的flags中只有5个bit可以让我们使用,
表示的空间地址就是2^5=32个长度,表示的空间太小了,所以我们得用sdshdr8的结构那么可以表示的空间地址
将会是2^8=256,但实际上,在Redis内部中,键是使用sdshdr5的结构,因为键不大可能会更新,而值会经常更新,所以干脆直接sdshdr8来表示值对象

Redis6.0新特性

多线程

概述

redis6.0提供了多线程的支持,redis6以前的版本,严格来说也是多线程,只不过执行用户命令的请求是单线程模型,还有一些线程用来执行后台任务,比如unlink删除大key,rdb持久化等

redis6.0提供了多线程的读写IO,但是最终执行用户命令的线程依然是单线程的,这样,就没有多线程数据的竞争关系,依然很高效

线程模型

在这里插入图片描述

  • redis6.0以前线程执行模式,如下操作再一个线程中执行完成

在这里插入图片描述

  • redis6.0线程执行模式:
参数配置

可以通过如下参数配置多线程模型:

io-threads 4 // 这里说 有三个IO线程,还有一个线程是main线程,main线程负责IO读写和命令执行操作

默认情况下,如上配置,有三个IO线程,这三个IO线程只会执行IO中的write操作,也就是说,read和命令执行都由main线程执行,最后多线程讲数据写回客户端。

在这里插入图片描述
开启了如下参数:

io-threadas-do-reads yes // 将支持IO线程执行 读写任务

Client side caching(客户端缓存)

概述

redis6提供了服务端追踪key的变化,客户端缓存数据的特性,这需要客户端实现
在这里插入图片描述

执行流程

当客户端访问某个key时,服务端将记录key和client,客户端拿到数据后,进行客户端缓存,这时,当key再次被访问时,key将被直接返回,避免了与redis服务器的再次交互,节省服务端资源,当数据被其他请求修改时,服务端将主动通知客户端失效的key,客户端进行本地失效,下次请求时,重新获取最新数据目前只有lettuce对其进行了支持:

代码示例
  • 依赖导入
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce‐core</artifactId>
<version>6.0.0.RELEASE</version>
</dependency>
  • Java代码
public class Main {public static void main(String[] args) {RedisClient redisClient = RedisClient.create("redis://127.0.0.1");Map<String, String> clientCache = new ConcurrentHashMap<>();StatefulRedisConnection<String, String> myself = redisClient.connect();CacheFrontend<String, String> frontend = ClientSideCaching.enable(CacheAccessor.forMap(clientCache), myself,TrackingArgs.Builder.enabled().noloop));String key = "csk";int count = 0;while (true) {System.out.println(frontend.get(key));TimeUnit.SECONDS.sleep(3);if (count++ == Integer.MAX_VALUE) {myself.close();redisClient.shutdown();}}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习实践】面部表情识别,深度学习分类模型,mmpretrain用于分类的实用教程,多任务网络头

文章目录 数据集数据集的进一步处理转换training.csv转换validation.csv 剔除无法使用的图片数据选择mmpretrain框架来训练配置四个文件改写base model改写base datasetsschedulesdefault_runtime 总配置开始训练训练分析考虑在网络上增加facial_landmarks回归head考虑是否可以…

B树B+树,字典树详解,哈夫曼树博弈树

目录 B树&#xff1a;B-Tree B树 字典树&#xff1a;Trie Tree 哈夫曼树 博弈树 B树&#xff1a;B-Tree 多路平衡搜索树 1.M阶B树&#xff0c;就是M叉&#xff08;M个指针&#xff09;。 2.每个节点内记录个数<M-1。 3.根节点记录个数>1。 4.其余节点内记录个数&…

人工智能技术的不当利用与风险

目录 前言1 视频篡改技术的滥用1.1 虚假信息传播与社会动荡1.2 对公众信任的破坏与舆论混乱 2 隐私泄露与监视风险2.1 个人信息安全与数据滥用风险2.2 社会稳定与个人自由权利的平衡 3 虚假评论与信息传播3.1 舆论操纵与社会意识形态的影响3.2 对信息可信度与公众信任的威胁 结…

【Linux】进程---概念---进程---优先级

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.操作系统(Operator System) 1.1 概念 1.2 设计OS的目的 1.3 定位 1.4 如何理解 "管理" 1.5 总结 1.6 系统调用和…

蓝桥杯刷题总结(Python组)

1、蛇形矩阵 解题思路&#xff1a;每次赋值后都对方向进行改变&#xff0c;一般上下左右就是&#xff08;-1&#xff0c;0&#xff09;&#xff0c;&#xff08;0&#xff0c;1&#xff09;&#xff0c;&#xff08;1&#xff0c;0&#xff09;&#xff0c;&#xff08;0&…

智慧城市物联网建设:提升城市管理效率与居民生活品质

目录 一、智慧城市物联网建设的意义 1、提升城市管理效率 2、改善居民生活品质 3、促进城市可持续发展 二、智慧城市物联网建设面临的挑战 1、技术标准与互操作性问题 2、数据安全与隐私保护问题 3、投资与回报平衡问题 三、智慧城市物联网建设的实施策略 1、制定统一…

Linux下安装多个nodejs并映射Jenkins

背景 需要Jenkins中切换多个Node&#xff0c;比如nodejs16和nodesjs18,所以在宿主机按照好这两个版本&#xff0c;然后再映射到Jenkins容器中 步骤 1.下载地址 https://nodejs.org/dist/ 放到 cd /opt/soft/2.解压 tar -xzvf node-v16.20.0-linux-x64.tar.gz tar -xzvf n…

STM32F4+薄膜压力传感器(FSR)AO模拟输出程序ADC模数转换器详解

前言&#xff1a;博主在使用STM32F4加薄膜压力传感器用来测量压力时&#xff0c;发现给的例程只有STM32F1系列的&#xff0c;而STM32F4系列库函数程序不太一致&#xff0c;博主实战解决了该问题&#xff0c;用STM32F4标准库开发。有关ADC模数转换器的详细知识点详情点击我的博文…

ChatGPT是什么,怎么使用,需要注意些什么?

一、ChatGPT 是什么&#xff1f; ChatGPT&#xff0c;全称聊天生成预训练转换器&#xff08;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;是 OpenAI 开发的人工智能(AI)聊天机器人程序&#xff0c;于2022年11月推出。该程序使用基于GPT-3.5、GPT-4架构的…

基于java+springboot+vue实现的旅游信息管理系统(文末源码+Lw+ppt)23-464

摘 要 本系统为用户而设计制作旅游信息管理系统&#xff0c;旨在实现旅游信息智能化、现代化管理。本旅游信息管理自动化系统的开发和研制的最终目的是将旅游信息的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的便利和条件…

【C语言】空心正方形图案

思路&#xff1a; 1&#xff0c;两行两列打印* &#xff1a;第一行和最后一行&#xff0c;第一列和最后一列。 2&#xff0c;其他地方打印空格。 代码如下&#xff1a; #include<stdio.h> int main() { int n 0; int i 0; int j 0; while (scanf("…

centos创建并运行一个redis容器 并支持数据持久化

步骤 : 创建redis容器命令 docker run --name mr -p 6379:6379 -d redis redis-server --appendonly yes 进入容器 : docker exec -it mr bash 链接redis : redis-cli 查看数据 : keys * 存入一个数据 : set num 666 获取数据 : get num 退出客户端 : exit 再退…

GaussDB分区表自动新增分区

前言 GaussDB是华为自主研发的企业级分布式关系型数据库&#xff0c;支持集中式和分布式两种部署方式。为企业提供了高可用&#xff0c;高可靠&#xff0c;高安全等能力&#xff0c;其产品全栈自研&#xff0c;并且具有完善生态工具和开源社区。在实际去O的项目过程&#xff0…

自己录的视频怎么配上字幕?推荐几种方法

自己录的视频怎么配上字幕&#xff1f;在数字化时代&#xff0c;视频已经成为人们获取信息、娱乐消遣的重要形式。而对于许多内容创作者来说&#xff0c;为自己的视频添加字幕不仅能提升观众的观看体验&#xff0c;还能增加视频的专业度和吸引力。那么&#xff0c;如何为自己的…

MM1: Methods, Analysis Insights from Multimodal LLM Pre-training

MM1: Methods, Analysis & Insights from Multimodal LLM Pre-training 相关链接&#xff1a;arxiv 关键字&#xff1a;多模态学习、大型语言模型、预训练、视觉语言连接、混合专家模型 摘要 本文讨论了构建高性能的多模态大型语言模型&#xff08;MLLMs&#xff09;。特别…

【鸿蒙HarmonyOS开发笔记】动画过渡效果之布局更新动画

概述 动画的原理是在一个时间段内&#xff0c;多次改变UI外观&#xff0c;由于人眼会产生视觉暂留&#xff0c;所以最终看到的就是一个“连续”的动画。UI的一次改变称为一个动画帧&#xff0c;对应一次屏幕刷新&#xff0c;而决定动画流畅度的一个重要指标就是帧率FPS&#x…

云原生(四)、Docker-Compose

Docker-Compose Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它使用一个简单的 YAML 文件来配置应用程序的服务、网络和卷&#xff0c;从而使得在不同环境中轻松部署应用程序变得更加简单和可靠。 Docker Compose 主要由以下几个核心组件组成&#xf…

HTML静态网页成品作业(HTML+CSS)——世博园介绍(2个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有2个页面。 二、作品演示 三、代…

BUUCTF-Ezsql1

1.打开靶机 打开第一个链接 2.万能密码 使用万能密码&#xff1a;a or 1 # 密码为随意 第二个用kali打开 3.ssh连接靶机 ssh ctf284490d0-7600-4c65-9160-5ced02f45633.node5.buuoj.cn -p 28191 由题可知密码为123456 4.找到并修改index.php文件 找到index.php文件 #内容如…