Redis字符串原理的深入理解

数据库 发布日期:2024/12/23 浏览次数:1

正在浏览:Redis字符串原理的深入理解

前言

来掘进都有两年多了一直当个小透明,今天终于发一次文章了.

最近在看 Redis,感觉收获很多,写篇博客记录一下.

Redis 有五种基础数据结构:string,list,set,zset,hash.其中 string是最最最简单的也是最常用的.这个数据类型虽然简单但是内部的结构设计却很是精致.

基本介绍

相比于 Java,在 Redis 中 string 是可以修改的,是动态字符串(Simple Dynamic String 简称 SDS)他的内部结构更像是一个 ArrayList,维护一个字节数组并预分配冗余空间以减少内存的频繁分配.当字符串的长度小于 1MB时,每次扩容都是加倍现有的空间,如果字符串长度超过 1MB 时,每次扩容时只会扩展 1MB 的空间.

ps:字符串长度为最大长度 512MB.

> set name test
OK
> get name
"test"
> mset name1 test1 name2 test2
OK
> mget name1 name2
1) "test1"
2) "test2"
> del name
(integer) 1

上面是字符串的基本操作 命令mset 和 mget 可以对多个字符串读写 节省网络开销

不仅如此redis 的字符串还可以用来储存整数(更不像Java 的字符串了),并且可以自增操作.字符串保存整数类型的的范围在 至
如果保存的数大于这个取值范围就会变成普通字符类型 无法自增操作.这将由字符串编码格式决定.

字符串由多个字节组成,每个字节有 8bit.这样的数据结构还可以当做 bitmap 去使用.

> set foo 1
OK
> get foo 
"1"
> incr foo
(integer) 2
> get foo
"2"

内部原理

基本实现

Redis字符串原理的深入理解

上图所示为字符串的基本结构,其中 content 里面保存的是字符串内容,和 c 一样用 0x\0作为结束字符.这个结束字符不会被计算len 中.代码如下:

struct SDS{
  T capacity;		//数组容量
  T len;			//实际长度
  byte flages;	//标志位,低三位表示类型
  byte[] content;	//数组内容
}

可以看到 capacity和len 都是泛型,为什么不直接使用 int 呢"htmlcode">

struct RedisObject{
  int4 type;		//数据类型 5 种
  int4 encoding;	//键值内部编码格式 int 或 embstr 等等
  int24 lru;		// 当内存超限时采用LRU算法清除内存中的对象
  
  int32 refcount;	//改键值被引用的数量
  void *ptr;		//对象内容
}

int 编码

当储存的值是64 位有符号整数类型的时候将会采用 int  编码,这时可以使用键值自增操作.Redis 在启动时会建立1w 个redisObject共享对象下文会讲到,值在[0,1000)之间.如果存入整数的值在[0,1000)中Redis将不会创建新的对象,而是直接指向共享对象,键值不额外占用空间.

使用 object encoding命令可以查看编码格式 使用 debug object命令可以查看更多信息

> set foo 1
OK
> object encoding foo
"int"
> set foo2 1
OK
> debug object foo
Value at:0x7f44b020aca0 refcount:2147483647 encoding:int serializedlength:2 lru:14691591 lru_seconds_idle:72588
> debug object foo2
Value at:0x7f44b020aca0 refcount:2147483647 encoding:int serializedlength:2 lru:14691591 lru_seconds_idle:72594

可以看到 foo 和 foo2  都在0x7f44b020aca0这里指向的是同一个对象

embstr 编码

当存储的字符串长度较短时(len<=44 字节),Redis将会采用 embstr 编码.embstr 即embedded string 嵌入式的字符串.将SDS结构体嵌入RedisObject对象中, 使用 malloc 方法一次分配内存地址是连续的.

如图所示:

Redis字符串原理的深入理解

raw 编码

当存储的字符串长度较长时(len>44 字节),Redis 将会采用 raw 编码,和 embstr 最大的区别就是 RedisObject 和 SDS 不在一起了,内存地址不再连续了.

如图所示:

Redis字符串原理的深入理解

思考

为什么字符串会有两种格式 embstr 和格式和 raw分界线是 44 个字节"text-align: center">Redis字符串原理的深入理解

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。