redis数据结构-动态字符串

1、内存对齐

1.1 对齐原因

CPU和总线是64位的,所以CPU每次可以从内存里面拿出8个字节,而这8个字节是对齐的,也就是说只能是0-7,8-15, 16-23这样的,不能从中间拿。这个时候你要读一个double,如果double的地址可以被8整除,那你就只需要跟内存要一次数据。如果不能整除,那你就得跟内存要2次数据。

1.2 对齐规则
  • 结构体变量的起始地址能够被其最宽的成员大小整除
  • 结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节
  • 结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节

如该结构体占用空间为12字节

struct A{
    char a;
    int b;
    short c;
};

2、数据结构

struct __attribute__((__packed_) ) sdshdr8 {
uint8_t len; /* 已使用长度,用1字节存储*/
uint8_t alloc ; /*总长度,用1字节存储*/
unsigned char flags;/*低3位存储类型,高5位预留*/
char buf[];/*柔性数组,存放实际内容*/
};

struct _attribute__( (_packed__) ) sdshdr16 {
uint16_t len; /*已使用长度,用2字节存储*/
uint16_t alloc; /*总长度,用2字节存储*/
unsigned char flags;/*低3位存储类型,高5位预留*/
char buf[];/*柔性数组,存放实际内容*/
};
...

  • len:表示 buf中已占用字节数。
  • alloc:表示 buf中已分配字节数
  • flags:标识当前结构体的类型,低3位用作标识位,高5位预留。
  • buf:柔性数组,真正存储字符串的数据空间。
3. sds特性

1、二进制安全

  • C 字符串内容 必须是 类似 ASCII 一样的编码,并且除了字符串结尾 不能有 空字符,否则会被提前当做 结尾,这样的话就没法 存储 图片、音频、视频、压缩文件等 二进制数据
  • 而SDS 就不同了,依赖自带 的 len 属性,不会按照 字符串内容里的 空字符串 判断结尾。所以这一特性,使得 Redis 不仅支持 文本存储,还支持 多样性的二进制数据存储

2、获取长度时间复杂度O(1)

典型的空间换取时间

3、取消内存对齐

  • 通过_attribute__( (_packed__) )取消内存对齐,节省空间
  • sds返回给上层的不是结构体地址,而是指向内容的buf地址,无论是sdshdr8sdshdr16,都能通过buf[-1]定位到flag地址,同样定位到len、aloc地址
4、interesting code
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))

## 代表字符串拼接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值