01键值数据库基本架构
- 前言
- 一、数据模型和操作接口
- 二、可以存那些数据
- 三、可以对数据做什么操作
- 四、保存在内存还是外存
- 五、基本内部架构
- 六、采用什么访问模式
- 七、如何定位键值对的位置
- 总结
前言
Redis 本身比较复杂,如果直接研究一个个具体的技术点,比如“单线程”“缓存”等,虽然可以直接学习到具体的内容,甚至立马就能解决一些小问题。但是这样学,很容易迷失在细枝末节里。
更好的学习方式就是先建立起“系统观”。如果想要深入理解和优化 Redis,就必须要对它的总体架构和关键模块有一个全局的认知,然后再深入到具体的技术点。经过这样一个过程,在实践中定位和解决问题时,就会轻松很多,而且还可以把这个学习方式迁移到其他的学习活动上。使得学习、工作效率更高。
构造这个简单的键值数据库,我们只需要关注整体架构和核心模块。通过剖析这个最简单的键值数据库,来迅速抓住学习和调优 Redis 的关键。
一、数据模型和操作接口
开始构造 SimpleKV 时,首先就要考虑里面可以存什么样的数据,对数据可以做什么样的操作,也就是数据模型和操作接口。这是理解 Redis 经常被用于缓存、秒杀、分布式锁等场景的重要基础。
理解了数据模型,就会明白,为什么在有些场景下,原先使用关系型数据库保存的数据,也可以用键值数据库保存。
例如,用户信息(用户 ID、姓名、年龄、性别等)通常用关系型数据库保存,在这个场景下,一个用户 ID 对应一个用户信息集合,这就是键值数据库的一种数据模型,它同样能完成这一存储需求。
如果只知道数据模型,而不了解操作接口的话,可能就无法理解,为什么在有些场景中,使用键值数据库又不合适了。
例如,同样是在上面的场景中,如果要对多个用户的年龄计算均值,键值数据库就无法完成了。因为它只提供简单的操作接口,无法支持复杂的聚合计算。
Redis 到底能做什么,不能做什么呢?需要先搞懂它的数据模型和操作接口。
二、可以存那些数据
对于键值数据库而言,基本的数据模型是 key-value 模型。key 是 String 类型,而 value 是基本数据类型,例如 String、整型等。
不同键值数据库支持的 key 类型一般差异不大,而 value 类型则有较大差别。我们在对键值数据库进行选型时,一个重要的考虑因素是它支持的 value 类型。
例如,Memcached支持的 value 类型仅为 String 类型,而 Redis 支持的 value 类型包括了 String、哈希表、列表、集合等。Redis 能够在实际业务场景中得到广泛的应用,就是得益于支持多样化类型的 value。
不同 value 类型的实现,不仅可以支撑不同业务的数据需求,而且也隐含着不同数据结构在性能、空间效率等方面的差异,从而导致不同的 value 操作之间存在着差异。
三、可以对数据做什么操作
3 种基本操作,即 PUT、GET 和 DELETE:
- PUT:新写入或更新一个 key-value 对;
- GET:根据一个 key 读取相应的 value 值;
- DELETE:根据一个 key 删除整个 key-value 对。
四、保存在内存还是外存
-
保存在内存的好处是读写很快,毕竟内存的访问速度一般都在百 ns 级别。但是,潜在的风险是一旦掉电,所有的数据都会丢失。
-
保存在外存,虽然可以避免数据丢失,但是受限于磁盘的慢速读写(通常在几 ms 级别),键值数据库的整体性能会被拉低。
如何进行设计选择,通常需要考虑键值数据库的主要应用场景。
缓存场景下的数据需要能快速访问但允许丢失,通常采用内存保存键值数据。Memcached 和 Redis 都是属于内存键值数据库。
五、基本内部架构
一个键值数据库包括了访问框架、索引模块、操作模块、存储模块四部分。
六、采用什么访问模式
访问模式通常有两种:
- 通过函数库调用的方式供外部应用使用,比如,上图中的libsimplekv.so,就是以动态链接库的形式链接到程序中,提供键值存储功能(RocksDB);
- 通过网络框架以 Socket 通信的形式对外提供键值对操作,可以提供广泛的键值存储服务。在上图中网络框架中包括 Socket Server 和协议解析( Memcached 和 Redis )。
不同的键值数据库服务器和客户端交互的协议并不相同,在对键值数据库进行二次开发、新增功能时,必须要了解和掌握键值数据库的通信协议,这样才能开发出兼容的客户端。
通过网络框架提供键值存储服务,一方面扩大了键值数据库的受用面,但另一方面,也给键值数据库的性能、运行模型提供了不同的设计选择,带来了一些潜在的问题,就是网络连接的处理、网络请求的解析,以及数据存取的处理,是用一个线程、多个线程,还是多个进程来交互处理呢?该如何进行设计和取舍呢?一般把这个问题称为 I/O 模型设计。不同的 I/O 模型对键值数据库的性能和可扩展性会有不同的影响。
-
如果一个线程既要处理网络连接、解析请求,又要完成数据存取,一旦某一步操作发生阻塞,整个线程就会阻塞住,这就降低了系统响应速度。
-
如果采用不同线程处理不同操作,某个线程被阻塞时,其他线程还能正常运行。但是,不同线程间如果需要访问共享资源,那又会产生线程竞争,也会影响系统效率。
七、如何定位键值对的位置
键值数据库解析了客户端发来的请求,需要查找所要操作的键值对是否存在,这依赖于键值数据库的索引模块。索引的作用是让键值数据库根据 key 找到相应 value 的存储位置,进而执行操作。
索引的类型有很多,常见的有哈希表、B+ 树、字典树等。不同的索引结构在性能、空间消耗、并发控制等方面具有不同的特征。不同键值数据库采用的索引并不相同。
例如,Memcached 和 Redis 采用哈希表作为 key-value 索引,而 RocksDB 则采用跳表作为内存中 key-value 的索引。
内存键值数据库(例如 Redis)采用哈希表作为索引的原因:其键值数据基本都是保存在内存中的,而内存的高性能随机访问特性可以很好地与哈希表O(1) 的操作复杂度相匹配。
Redis的 value 支持多种类型,通过索引找到一个key 所对应的 value 后,仍然需要从 value 的复杂结构(例如集合和列表)中进一步找到实际需要的数据,这个操作的效率本身就依赖于它们的实现结构。
总结
为了支持更加丰富的业务场景,Redis 对这些组件或者功能进行了扩展,或者说是进行了精细优化,从而满足了功能和性能等方面的要求。
- Redis 主要通过网络框架进行访问,而不再是动态库了,使得 Redis 可以作为一个基础性的网络服务进行访问,扩大了 Redis 的应用范围。
- Redis 数据模型中的 value 类型很丰富,因此也带来了更多的操作接口,例如面向列表的 LPUSH/LPOP,面向集合的 SADD/SREM 等。
- Redis 的持久化模块能支持两种方式:日志(AOF)和快照(RDB),这两种持久化方式具有不同的优劣势,影响到 Redis 的访问性能和可靠性。
- Redis 支持高可靠集群和高可扩展集群,因此Redis 中包含了相应的集群功能支撑模块。
最后
以上就是微笑音响最近收集整理的关于01键值数据库基本架构前言一、数据模型和操作接口二、可以存那些数据三、可以对数据做什么操作四、保存在内存还是外存五、基本内部架构六、采用什么访问模式七、如何定位键值对的位置总结的全部内容,更多相关01键值数据库基本架构前言一、数据模型和操作接口二、可以存那些数据三、可以对数据做什么操作四、保存在内存还是外存五、基本内部架构六、采用什么访问模式七、如何定位键值对内容请搜索靠谱客的其他文章。
发表评论 取消回复