登录
首页 >  数据库 >  Redis

深入解析Redis源码之SDS

来源:51cto

时间:2023-02-24 15:59:03 119浏览 收藏

学习知识要善于思考,思考,再思考!今天golang学习网小编就给大家带来《深入解析Redis源码之SDS》,以下内容主要包含数据结构、sds、Redi等知识点,如果你正在学习或准备学习数据库,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!

1.前言

Hello,欢迎大家来到《 Redis 数据结构源码解析系列》,在《Redis为什么这么快?》一文中我说过 Redis 速度快的一个原因就是其简单且高效的数据结构。

本系列文章面向各个阶段的 Coder 们,新手也不用怕。每一篇文章敖丙都将从命令实战入门入手,随后深入源码解析,最后面试题回顾这三个方向上给各位卷王一一介绍。

深入解析Redis源码之SDS

2.SDS命令实战[初来乍到]

SDS 是 Redis 中最简单的数据结构。Redis 中所有的数据结构都是以唯一的 key 字符串作为名称,根据 key 获取value,差异仅在于 value 的数据结构不同。

SDS 在生产环境中使用非常广泛,比如,我们使用 SDS 做分布式锁;将对象转成 JSON 串作为缓存等。

在 Redis 面试过程中一旦提及相关数据结构 SDS 一定是绕不过去的话题,它很简单(或者说看完此文后很简单😄),面试官可以不问,但我们不能不懂😄。

首先我们从命令实战开始切入吧~(老司机直接跳过)

更多命令查看官网:https://redis.io/commands#string

2. 1设置字符串

格式:set 。其中value的值可以为字节串(byte string)、整型和浮点数。

> set name aobing
OK

2.2 获取字符串

格式:get 。

> get name
"aobing"

2.3 获取字符串长度

格式:strlen

> strlen name
(integer) 6

2.4 获取子串

格式:getrange start end。获取字符串的子串,在Redis2.0之前此命令为substr,现使用getrange。返回位移为start(从0开始)和end之间(都包括,而不是像其他语言中的包头不包尾)的子串。

可以使用负偏移量来提供从字符串末尾开始的偏移量。因此-1表示最后一个字符,-2表示倒数第二个,依此类推。

该函数通过将结果范围限制为字符串的实际长度来处理超出范围的请求(end设置非常大也是到字符串末尾就截止了)。

127.0.0.1:6379> set mykey "This is a string"
OK
127.0.0.1:6379> getrange mykey 0 3
"This"
127.0.0.1:6379> getrange mykey -3 -1
"ing"
127.0.0.1:6379> getrange mykey 0 -1
"This is a string"
127.0.0.1:6379> getrange mykey 10 10000

2.5 设置子串

格式:setrange offset substr。返回值:修改后字符串的长度。

从value的整个长度开始,从指定的偏移量覆盖key处存储的一部分字符串。如果偏移量大于key处字符串的当前长度,则该字符串将填充零字节以使偏移量适合。

不存在的键被视为空字符串,因此此命令将确保它包含足够大的字符串以能够将值设置为offset。

注意:您可以设置的最大偏移为2^29 - 1(536870911),因为Redis字符串限制为512 MB。如果您需要超出此大小,可以使用多个键。

127.0.0.1:6379> set key1 "hello world"
OK
127.0.0.1:6379> setrange key1 6 redis
(integer) 11
127.0.0.1:6379> get key1
"hello redis"
127.0.0.1:6379> setrange key2 6 redis
(integer) 11
127.0.0.1:6379> get key2
"x00x00x00x00x00x00redis"

2.6 追加子串

格式:append substr如果key已经存在并且是字符串,则此命令将value在字符串末尾附加。如果key不存在,则会创建它并将其设置为空字符串,因此APPEND在这种特殊情况下 将类似于SET。

127.0.0.1:6379> exists key4
(integer) 0
127.0.0.1:6379> append key4 hello
(integer) 5
127.0.0.1:6379> append key4 world
(integer) 10
127.0.0.1:6379> get key4
"helloworld"

2.7 计数

在使用Redis中我们经常将字符串做为计数器,使用incr命令进行加一。格式:incr 。返回值:key递增后的值。将存储的数字key加1。如果key不存在,则在执行操作之前将其设置为0。如果key包含错误类型的值或包含不能表示为整数的字符串,则返回错误。此操作仅限于64位带符号整数。计数是由范围的,它不能超过Long.Max,不能低于Long.Min。

2.8 过期和删除

字符串可以使用del命令进行删除,也可以使用expire命令设置过期时间,到期自动删除。我们可以使用ttl命令获取字符串的寿命(还有多少时间过期)。

格式:del ...返回值:删除key的个数

127.0.0.1:6379> SET key1 "Hello"
"OK"
127.0.0.1:6379> SET key2 "World"
"OK"
127.0.0.1:6379> DEL key1 key2 key3
(integer) 2

格式:expire time返回值:如果设置了超时返回1。如果key不存在返回0。

如何将设置了过期的字符串设置为永久的呢?

生存时间可以通过使用DEL命令来删除整个 key 来移除,或者被SET和GETSET命令覆写(overwrite),这意味着,如果一个命令只是修改一个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。

比如说,对一个 key 执行INCR命令,对一个列表进行LPUSH命令,或者对一个哈希表执行HSET命令,这类操作都不会修改 key 本身的生存时间。

如果使用RENAME对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。

RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。

使用PERSIST命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。

127.0.0.1:6379> expire age 100
(integer) 1
127.0.0.1:6379> ttl age
(integer) 97
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> ttl age
(integer) -1
127.0.0.1:6379> expire age 100
(integer) 1
127.0.0.1:6379> ttl age
(integer) 98
127.0.0.1:6379> rename age age2
OK
127.0.0.1:6379> ttl age2
(integer) 87
127.0.0.1:6379> expire age 100
(integer) 1
127.0.0.1:6379> ttl age
(integer) 96
127.0.0.1:6379> persist age
(integer) 1
127.0.0.1:6379> ttl age
(integer) -1

3.SDS 简介与特性[八股]

深入解析Redis源码之SDS

Redis 面试中大概率会提及相关的数据结构,SDS 的八股文大部分人倒背如流,可是没有读过源码,知其然不知其所以然,这可万万使不得呀!!

4.SDS 结构模型[老司机]

本次敖丙阅读的Redis源码为最新的 Redis6.2.6 和 Redis3.0.0 版本

相信各位看官在听到 Redis 中的字符串不是简简单单的C语言中的字符串,是 SDS(Simple Dynamic String,简单动态字符串)时以为是造出了啥新类型呢,对此,敖丙想说的是不慌,其实 SDS 内容的源码底层就是typedef char *sds;。

4.1 数据结构

Redis6.x 的 SDS 的数据结构定义与 Redis3.0.0 相差比较大,但是核心思想不变。先从简单版本(Redis3.x)开始吧~

struct sdshdr {
   //记录buf数组中已使用字节的数量
   //等于SDS所保存字符串的长度
   unsigned int len;

   //记录buf数组中未使用字节的数量
   unsigned int free;

   //char数组,用于保存字符串
   char buf[];
};

如下图所示为字符串"Aobing"在Redis中的存储形式:

深入解析Redis源码之SDS
深入解析Redis源码之SDS

  • len 为6,表示这个 SDS 保存了一个长度为5的字符串;

  • free 为0,表示这个 SDS 没有剩余空间;

  • buf 是个char类型的数组,注意末尾保存了一个空字符'

声明:本文转载于:51cto 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>