Redis源码解析:数据结构详解-sds

在这里插入图片描述

介绍

我们知道Redis是一个键值对数据库,当你执行如下命令时

set testKey testValue;
rpush fruits banana apple;

其中的键就是用sds(Simple Dynamic String,简单动态字符串)来实现的,redis中string类的值也是用SDS实现的(如上面的testValue)。我们来看一下SDS的底层数据结构是啥?

3.0版本及以前

struct sdshdr {
	// buf数组中已使用字符的数量
    unsigned int len;
    // buf数组中未使用字符的数量
    unsigned int free;
    // 字符数组,用来保存字符串
    char buf[];
};

如下是一个sds的示例
在这里插入图片描述

free:free为0,表示未使用的空间
len:这个sds保存了5字节长的字符串
buf:char类型的数组,前5个字节是字符串,后一个字节是\0,表示结尾,\0不计入总长度

当要存的字符串变大或者变小的时候,会造成频繁的内存分,进而影响性能。所以Redis通过空间预分配和惰性空间释放策略来避免内存的频繁分配

空间预分配

当sds的内容变大时,程序不仅会为sds分配修改所需要的空间,还会为sds分配额外的未使用的空间。

  1. 对sds进行修改之后,sds的长度(即len属性的值)小于1MB,程序分配和len属性同样大小的未使用空看,即sds len属性的值和free属性的值相同
  2. 对sds进行修改之后,sds的长度(即len属性的值)大于等于1MB,程序会分配1MB的未使用空间

惰性空间释放

当sds内容变小时,程序并不会释放缩短后剩余的空间,只是修改free属性,将未使用字符数量记录下来,等以后使用

3.0版本以后

类型占用字节数
uint8_t1
uint16_t2
uint32_t4
uint64_t8
unsigned char1
char1

上面的结构有改进的空间吗?如果让你来写sds,你会怎么写呢?

不同长度的字符串是否有必要占用相同大小的头部?

当字符串很小的时候,我们还得额外的使用8个字节(len和free各占4个字节),感觉有点太浪费了。

我们是否可以根据字符串的长度,来决定len和free占用的字节数呢?比如短字符串len和free的长度为1字节就够了。长字符串,用2字节或4字节,更长的字符串,用8字节。

那我们如何区分这3种情况呢?

很简单,再加一个一字节的字段标明类型就行了

所以在redis 3.2中,有如下5种类型

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[];
};
  1. len:buf数组中已使用字符的数量
  2. alloc:buf数组中已分配字符的数量
  3. flags:标识当前结构体的类型,低3位用作标识位,高5位预留(3个字节能保存的种类数为2的3次方即8,sds总共的种类数为5,所以用低三位就能用标识种类)
  4. buf:字符数组,用来保存字符串

可以看到sdshdr5比较特殊,并没有len和alloc两个字段,那它是如何存已使用和已分配的数量呢?

在这里插入图片描述

sdshdr5中,flags占用一个字节,低3位表示type,高5位表示长度,能表示的区间长度为(0~31,即25-1)

sdshdr5并没有存在alloc的值,因此它不会进行空间预分配和惰性空间空间释放,长度变动每次都重新申请内存

当字符串长度大于31时,flags的后5位就存不下了,所以我们就将len和free单独存放

在这里插入图片描述

参考博客

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SDS(SQL Data Security)是一款专门用于SQL数据库文件加密的保密软件。通过加密和访问控制技术,可控制SQL数据库文件无法拷贝,禁止导出,备份加密,远程销毁,脱离环境无法打开等等。 SDS分为管理程序和控制程序,需要在安装SQL Server数据库的机器上安装控制程序和管理程序,可在局域网内安装管理程序对SDS软件进行远程操控,安装后,所有数据库文件将处于加密状态,即使将文件拷贝出去也无法使用。同时,通过SQL企业管理器备份出来的数据也是加密的,离开本机环境将无法使用,SDS可禁止SQL组件导出数据。 SDS与数据库应用程序及数据库大小无关,后台实时监控数据的写入和读取,不会影响应用程序正常调用数据。 SDS的特点如下: 1.安装,维护简单。一键式安装,配套安装使用教程,专业的售后维护团队。 2.后台运行,实时监控数据库的读写。 3.数据库数据拷贝离开本机环境无法使用。本机环境内则不受影响。 4.与应用程序无关,不影响应用程序使用。ERP、PDM、等管理系统可以正常调用数据库文件,和正常操作一样。 5.与数据库大小无关。 6.通过设置,可本地或管理端临时禁用数据库。黑客来袭或者紧急情况可以通过本软件提供的禁用数据库功能使数据库文件无法打开,即使在本机环境依然无法正常打开使用,之后可恢复正常状态。 7.可设定云端验证。当服务器被盗时,可以是服务器电脑在本公司环境外部无法正常开机,卸载硬盘更换电脑依然无法正常开机,即数据库文件不会被外人获取。 SDS目前支持SQL2000、SQL2005、SQL2008、SQL2012。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java识堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值