这是一个系列的文章,打算把Redis的基础数据结构、高级数据结构、持久化的方式以及高可用的方式都讲一遍,公众号会比其他的平台提前更新,感兴趣的可以提前关注,「SH的全栈笔记」,下面开始正文。
如果你是一个有经验的后端或者服务器开发,那么一定听说过Redis,其全称叫Remote Dictionary Server。是由C语言编写的基于Key-Value的存储系统。说直白点就是一个内存数据库,既然是内存数据库就会遇到如果服务器意外宕机造成的数据不一致的问题。
这跟很多游戏服务器也是一样的,感兴趣的可以参考我之前的文章游戏服务器和Web服务器的区别。其数据首先会流向内存,基于快速的内存读写来实现高性能,然后定期将内存的数据中的数据落地。Redis其实也是这么个流程,基于快速的内存读写操作,单机的Redis甚至能够扛住10万的QPS。
Redis除了高性能之外,还拥有丰富的数据结构,支持大多数的业务场景。这也是其为什么如此受欢迎的原因之一,下面我们就来看一看Redis有哪些基础数据类型,以及他们底层都是怎么实现的。
1. 数据类型
其基础数据类型有String
、List
、Hash
、Set
、Sorted Set
,这些都是常用的基础数据类型,可以看到非常丰富,几乎能够满足大部分的需求了。其实还有一些高级数据结构,我们在这章里暂时先不提,只聊基础的数据结构。
2. String
String可以说是最基础的数据结构了, 用法上可以直接和Java中的String挂钩,你可以把String类型用于存储某个标志位,某个计数器,甚至狠一点,序列化之后的JSON字符串都行,其单个key限制为512M。其常见的命令为get
、set
、incr
、decr
、mget
。
2.1 使用
get 获取某个key,如果key不存在会返回空指针 set 给key赋值,将key设置为指定的值,如果该key之前已经有值了,那么将被新的值给覆盖 incr 给当前的key的值+1,如果key不存在则会先给key调用 set
赋值为0,再调用incr
。当然如果该key的类型不能做加法运算,例如字符串,就会抛出错误decr 给当前key的值-1,其余的同上 mget 同get,只是一次性返回多条数据,不存在的key将会返回空指针
可能大多数的人只是到用一用的地步,这也无可厚非,但是如果是作为一个对技术有追求的开发,或者说你有想近大厂的想法,一定要有刨根问底的精神。只有当你真正知道一个东西的底层原理时,你遇到问题时才能提供给你更多的思路去解决问题。接下来我们就来聊一下Redis中String底层是如何实现的。
2.2 原理
2.2.1 结构
我们知道Redis是用C语言写的,但是Redis却没有直接使用,而是自己实现了一个叫SDS(Simple Dynamic String)的结构来实现字符串,结构如下。
struct sdshdr {
// 记录buf中已使用的字节数量
int len;
// 记录buf中未使用的字节数量
int free;
// 字节数组,用于保存字符串
char buf[];
}
2.2.2 优点
为什么Redis要自己实现SDS而不是直接用C的字符串呢?主要是因为以下几点。
减少获取字符串长度开销 C语言中获取字符串的长度需要遍历整个字符串,直到遇到结束标志位