redis数据库包含什么?基本架构
废话
redis是不是超级快,是不是?为啥啊?为啥这么快哦,我也不知道,是不是缓存?是不是因为是基于内存的?好像有点道理,学了这么久redis啥都不是啥都不会啊!!!!接下来把我自己学到的分享出来。
宏观感
- 构建redis时首先考虑到的应该时存什么样的数据。然后怎么操作数据,也就是数据模型和操作接口。了解了数据模型你就会知道为什么关系型数据库可以存的一些复杂数据也可以用redis这样的K,V存储了。
- 但是啊 如果你只知道数据模型不知道操作接口的话
,可能就没法理解在有些场景就不适合用键值对数据库了。比如你要做聚合操作,统计年龄,统计总数,做不了,无法支持复杂的聚合操作。 - 做做对比,设计一个简单的键值对数据库叫SHADIAO
学好redis必须要先搞清楚能做什么和不能做什么。
可以存什么数据?
- 对redis而言,基本数据模型就是key-value模型。比如
“hello”:"redis"就是一个基于KV对,"hello"就是key,"redis"是value。hello是String类型,而value却可以存很多类型。 - 不同键值对数据库支持的key大多数差异不大,而value却又很大的差异,在做键值对数据库选型时着重的考虑value支持的类型。比如Mencached支持的value类型只有String类型,而redis支持的就多了去了,有String、哈希表、列表、集合等。redis之所以受到广泛使用原因之一也是因为vlaue丰富的数据类型。
SHADIAO数据库就用最基本的String最为key,value也是String。
可以对数据做什么样的操作?
了解了数据模型后,就要知道怎么对数据的基本操作了。基本操作无非就是增删改查。
基本的操作,及SET、GET和DEL。
- SET:新写入或更新一个KV对;
- GET:根据一个key读取对应的value值;
- DEL:根据一个key删除整个KV对。
别的复杂操作这里先不说,SHADIAO数据库只聊最基本的。
因此SET、CGT、DEL时一个键值对数据库的基本操作。
如果随着自己的业务场景需要更加丰富的操作,比如,在一个用户登录后,用户的token是存储在键值对数据库的,那么就可以增加EXISTS操作接口,用于判断一个key是否存在。对键值对数据库来说,可以通过查看操作文档了解详细的操作接口。
由于是自己设计一个简单的键值对数据库,我们就不考虑redis的多类型操作,后续会介绍到。
到这里数据模型跟操作接口就算是设计完成了吧。接下来是不是该考虑数据存在哪里了是保存在外存还是内存呢?
- 内存:保存在内存的话速度肯定是非常快的,但是万一断电了的话在内存的脏数据是不会刷写到磁盘的,所有数据都会丢失。
- 外存:可以避免数据丢失,但是免不了超级慢的IO对磁盘的读写操作,就会导致整个数据库的整体性能被拉低。
为了和redis保存一致,SHADIAO也采用内存的存储方式。
基本组件
一个键值数据库包括了访问框架、索引模块、操作模块、存储模块。
访问模式
另一种是通过网络框架以socket通信形式对外提供键值对操作(比如Memcached和Redis)
通过网络框架提供键值服务,一方面扩大了数据库的受用面,但另一方面也给键值数据库的性能、运行模型带来了不同的设计选择。
- 比如我们客户端发生一个命令,这个命令携带数据被封装到网络包中发生给数据库,数据库收到发生的网络包后,按照相应的协议进行解析就可以知道客户端发生的是什么样的键值对,并且开始写入过程。那么问题来了,就是一个网络请求后数据库需要解析,以及存储数据,是用一个线程还是多个线程,该如何选择?
- 如果说一个线程的话处理网络连接、解析、又要完成数据的保存、一旦某一步出错就会发生阻塞,这就降低了系统性能。但是如果我用多线程的话,某个线程阻塞,其他线程还会正常运行,但是的但是,多线程嘛,这沙雕一看就有很多毛病,万一有访问共享资源就完蛋了,产生线程竞争,还有保证数据一致性,还要原子操作,也是影响了系统效率啊。
两难啊,redis是单线程的嘛?redis是怎么做到的?伏笔
如何定位
当客户端发送请求,这时服务的需要知道发生过来的键值对是否存在,这就依赖索引模块。索引的作用就是快速让键找到自己对应的老婆value的存储位置,进行嘿嘿嘿。
索引类型很多,常见的有探探,陌陌 哈哈 其实是哈希表、B+树等等,不同的会有不同的性能问题,redis采用的是哈希表作为key-value的索引。
redis采用哈希,很多原因是其存储在内存,内存可以高速随机访问(比如DRAM动态随机访问存储器,集成电路形式的存储器,可随机访问任何地址的内存)特性很好的与哈希表O(1)的复杂对匹配。
其次是value,对redis的value有很多类型的来说,找到key后还要查找value里面的数据,这个操作依赖它本身的实现结构。
redis采用常见的高效索引为某些value的底层数据结构。
不同操作的具体逻辑
SHADIAO的操作逻辑:
- 对于GET操作,找到就返回value即可;
- 对于SET操作就需要为其分配内存空间进行存储;
- 对于DEL操作需要删除键值对,然后还要释放内存空间,这个过程由分配器完成。
这些操作有些要分配内存和释放内存,就不得不说存储模块了。
存储、分配
我们的SHADIAO数据库就采用malloc和free。
- malloc:malloc(size)函数申请 size字节的内存并且返回已申请内存的地址。
- free:free(ptr) 函数可以释放ptr指针所指向的内存,该ptr指针由malloc(),calloc(),realloc() 等调用成功返回。
redis的内存分配器提供了很多选择,效率也有差别,后续会介绍。
持久化
在一个就是持久化的问题,我希望重启后可以快速的恢复数据。
我们只需要把数据在一定的时间段写到文件里就可以了。
两种方式:
- 对于每一个键值操作,都进行磁盘落地,这样数据就会非常可靠,但是同时性能也会下降,因为每次都要IO操作有,点像redis的AOF。
- 另一种就是在某个周期的进行保存,这样可以避免频繁写磁盘操作,但是极大可能丢失数据,有点像redis的RDB。
后续介绍redis的吧
差不多了基本架构算是完成,但是跟redis比相差甚远。SHADIAO数据库麻雀虽小但是五脏内全。
做个对比吧:
- redis主要通过网络框架访问。
- redis数据模型中的value类型非常丰富,因此带来了很多操作接口。
- redis持久化支持两种:RDB,AOF。
- SHADIAO数据库是个单机的,redis支持高集群、高扩展。
后续会详细介绍redis。
本文地址:https://blog.csdn.net/qq_45422703/article/details/109246666
上一篇: 40 个 CSS 布局技巧
下一篇: QT 【样式表】