【愚公系列】2022年05月 .NET架构班 046-分布式中间件 Redis存储原理之string
【摘要】 前言 1.SDS概念Redis中字符串的实现,Simple Dynamic String简单动态字符串,是一数据结构。Redis是用C语言实现的,但C语言本身没有字符串类型(只能用字符数组 char[]实现)。所以就会有以下问题:使用字符数组必须先给目标变量分配足够的空间,否则可能会溢出。如果要获取字符长度,必须遍历字符数组,时间复杂度是 O(n)。C 字符串长度的变更会对字符数组做内存重...
前言
1.SDS概念
Redis中字符串的实现,Simple Dynamic String简单动态字符串,是一数据结构。
Redis是用C语言实现的,但C语言本身没有字符串类型(只能用字符数组 char[]实现)。所以就会有以下问题:
- 使用字符数组必须先给目标变量分配足够的空间,否则可能会溢出。
- 如果要获取字符长度,必须遍历字符数组,时间复杂度是 O(n)。
- C 字符串长度的变更会对字符数组做内存重分配。
通过从字符串开始到结尾碰到的第一个’\0’来标记字符串的结束,因此不能保 存图片、音频、视频、压缩文件等二进制(bytes)保存的内容,二进制不安全。
而SDS的特点:
- 不用担心内存溢出问题,如果需要会对SDS进行扩容。
- 获取字符串长度时间复杂度为 O(1),因为定义了len属性。
- 通过“空间预分配”( sdsMakeRoomFor)和“惰性空间释放”,防止多次重分配内存。
- 判断是否结束的标志是 len 属性(它同样以’\0’结尾是因为这样就可以使用 C语言中函数库操作字符串的函数了),可以包含’\0’。
一、Redis存储原理之string
1. string结构
redisObject 结构如下:
typedef struct redisObject {
unsigned type:4; /* 对象的类型,包括:OBJ_STRING、OBJ_LIST、OBJ_HASH、OBJ_SET、OBJ_ZSET */
unsigned encoding:4; /* 具体的数据结构 */
unsigned lru:LRU_BITS; /* 24 位,对象最后一次被命令程序访问的时间,与内存回收有关 */
int refcount; /* 引用计数。当 refcount 为 0 的时候,表示该对象已经不被任何对象引用,则可以进行垃圾回收了 */
void *ptr; /* 指向对象实际的数据结构 */
} robj;
SDS结构如下:
/* sds.h */
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* 当前字符数组的长度 */
uint8_t alloc; /*当前字符数组总共分配的内存大小 */
unsigned char flags; /* 当前字符数组的属性、用来标识到底是 sdshdr8 还是 sdshdr16 等 */
char buf[]; /* 字符串真正的值 */
};
2.string编码类型
字符串的编码有三种:
- int:存储 8 个字节的长整型(long,2^63-1)。大小超过了 long 的范围 (2^63-1=9223372036854775807)时会自动转成embstr。
- embstr:代表 embstr 格式的 SDS(Simple Dynamic String 简单动态字符串), 存储小于 44 个字节的字符串。分配一次内存空间,而且是只读的。
- raw:存储大于 44 个字节的字符串(3.2 版本之前是 39 字节)。分配二次内存空间。
3.应用场景
场景 | 说明 |
---|---|
缓存 | 热点数据缓存(例如报表,微博热搜榜),对象缓存,全页缓存。可以提升热点数据的访问速度。 |
数据共享分布式 | 因为 Redis 是分布式的独立服务,可以在多个应用之间共享。分布式 Session |
分布式锁 | String 类型 setnx 方法,只有不存在时才能添加成功,返回 true。 |
全局ID | INT 类型,incrby,利用原子性。分库分表 |
计数器 | INT 类型,incr 方法。文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到数据库。 |
限流 | INT 类型,incr 方法。以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。 |
位统计 | 因为 bit 非常节省空间(1 MB=8388608 bit),可以用来做大数据量的统计。在线用户统计,留存用户统计 |
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)