String数据结构

3 分钟阅读 544 字 + 279 词
字符串实现原理
为了支持丰富和高性能的字符串操作函数、保存二进制格式数据、节省内存,以及实现“既要又还要”的目标,使用了SDS,中文叫做简单动态字符串。
C语言字符串的缺点:
  1. 没有长度信息,要获取长度信息只能遍历找到'\0'
  2. 无法做到安全的二进制格式数据存储 ,图片等二进制格式数据无法保存。 无法存储\0这种特殊字符是因为\0在C语言字符串中表示结尾。
  3. 字符串的扩容和缩容 ,char数组的长度在创建字符串的时候就确定下来。如果要追加数据,则要重新申请一块空间,把追加的字符串内容拷贝进去,再释放旧空间看,十分消耗资源
sds 简单动态字符串
指针向右移是数据buf,指针向左移是元信息,数组总长度,使用的长度,flags表示SDS类型
SDS一共设计了5种类型,sdshdr5, sdshdr8,sdshdr16,sdshdr32,sdshdr64
struct __attribute__ ((__packed__)) sdshdr8{
    //使用了专门的编译优化手段来节省空间。这个作用就是告诉编译器,不要使用字节对齐的方式,而是采用紧凑的方式分配内存。
  	uint8_t len;  
  	uint8_t alloc;  
  	unsigned char flags;  
  	char buf[];  
};
当对SDS进行缩短操作时,程序并不会回收多余的内存空间,如果后面需要append追加操作,则可以直接使用数组中未使用的空间。
实战:
分布式ID生成器
为了防止重启数据丢失,开启AOF,但是还是有可能丢失1秒的数据。
所以使用一个异步机制将生成的最大ID持久化到一个Mysql
  1. 当应用服务启动时先从Mysql中查询出最大值M,然后执行EXISTS counter:order判断是否存在键
  2. 如果不存在这个键,则SET counter:order M将值写入Redis中
  3. 如果存在这个键 值为N,则比较N和M的值,SET counter:order max(M,N)将最大值写入Redis中,如果相等则不操作。
  4. 应用服务启动完毕后,在每次需要生成ID时,应用程序就向Redis服务器发送INCR counter:order命令
  5. 应用将获取到的ID发送到MQ中,消费者监听队列把值持久化到Mysql.