简介 概念 KV 存储(键值存储,Key-Value Storage) 是一种非关系型数据库(NoSQL)的存储模型,其核心思想是通过 “键(Key)” 快速索引和访问对应的 “值(Value)”,以实现高效的数据读写。它将数据存储为键值对集合,其中键是唯一标识符,值可以是任意类型的数据(如字符串、对象、二进制数据等)。 示例:键为 user:1001,值为 {"name": "Alice", "age": 30}。 例如,一个kv存储包含5个操作:set key value(增),get key(取值),del key(删),mod key value(改),exist key(查询是否存在)。 整体架构 一个轻量化的kv存储服务器整体架构如图所示: 执行流程 网络层接收客户端发送的请求并交付给协议层,协议层将内容拆分过滤后,通过适配层调用对应的接口完成对应的操作,然后将需要返回的内容依次提交至网络层发送给客户端。 在整个流程中,每一层对于其他层而言都是透明的,例如协议层并不需要知道下层网络模型是哪一个,也不需要知道上层所使用的数据结构是什么。利于项目的维护和扩展。 思考题 1. 已经有了像 redis、Memcached 等成熟的KV引擎,为什么还会开发这种基础的KVstore呢? 每个公司的业务不一样,可能不需要这么大而全的功能。实现基础的KV存储可以针对性地做优化,将性能做到极致。也可以根据业务需求定制数据结构、功能特性等。 对于一些简单的应用场景,使用通用数据库可能会使系统架构变得复杂。基础 KV 存储可以提供一个轻量级的解决方案,简化系统架构,降低开发和维护成本。 不同行业和应用对数据安全有不同的要求。基础 KV 存储可以根据具体的安全需求进行定制开发,如实现更高级别的数据加密、访问控制和审计功能,以满足特定的安全合规要求。 2. kv存储单线程和多线程的优缺点。 单线程: 优点:程序的逻辑清晰,没有复杂的线程同步和并发控制问题,代码的编写、调试和维护都相对容易。由于同一时间只有一个操作在进行,不会出现多个线程同时修改数据导致的数据不一致问题。单线程不需要额外的线程管理开销,如线程的创建、销毁和调度等,因此对系统资源的占用较少,适合在资源受限的环境中运行。 缺点:单线程只能依次处理请求,无法充分利用多核 CPU 的计算能力。当有大量并发请求时,响应时间会显著增加,吞吐量较低。如果某个操作耗时较长,会阻塞后续所有请求,导致系统响应不及时。 多线程: 优点:多线程可以充分利用多核 CPU 的计算能力,并行处理多个请求,从而提高系统的吞吐量和响应速度。 缺点:多线程编程需要考虑线程同步、并发控制、数据一致性等问题,如锁机制、信号量等,代码的编写和调试难度较大。如果处理不当,容易出现死锁、数据竞争等问题。多线程需要额外的线程管理开销,如线程的创建、销毁和调度等,会占用更多的系统资源。同时,线程之间的上下文切换也会消耗一定的时间和资源。 3. kv存储如何实现范围查询?用什么数据结构? 首先实现高效的范围查询(时间复杂度O(logn))需要在数据存入时就要满足有序的条件。 使用的数据结构可以是跳表(skip list)或者B+树,他们的数据都存在最下面的链表中,通过范围查询找到起始位置后按顺序读取会更加方便,实现逻辑更简单。 如果使用红黑树,因为红黑树的每个节点上都会存有数据,实现范围查找不是不行只是代码的逻辑会比较复杂,效率也不如前面提到的高。 4. 网络模型的性能差异 网络层面使用的三个模型 reactor, 协程, io_uring 的性能差异经过实际测试发现几乎没有差异,qps均在20000左右。 5. 测试用例如何实现?并且保证代码覆盖率超过90% 覆盖所有功能路径:确保每个 API(如set、get、delete)的所有逻辑分支都被测试到。 验证异常情况:例如,尝试读取不存在的键、删除不存在的键,确保不会崩溃。 测试边界值:空键、空值、特殊字符、大容量数据等。 验证状态转换:例如,插入→查询→删除→查询(验证数据已删除)。 6. kv存储能够跟哪些系统交互使用?常见kv引擎及其使用场景 Redis 使用场景 缓存系统:因其读写速度极快,可将高频访问的数据如热门商品信息、用户会话数据等存储在 Redis 中,减少对后端数据库的访问压力,提高系统响应速度。实时分析:支持原子操作和多种数据结构,能用于实时统计和分析,例如记录网站的访问量、点赞数、评论数等。消息队列:利用列表数据结构可以实现简单的消息队列,用于异步任务处理,如订单处理、邮件发送等。 性能特点 高吞吐量:单线程的事件驱动模型结合高效的内存操作,使其在处理简单的读写操作时能达到很高的吞吐量。低延迟:数据存储在内存中,读写操作几乎可以立即响应,延迟通常在毫秒级别甚至更低。 Memcached 使用场景 Web 缓存:作为 Web 应用的缓存层,减轻数据库负载,提高页面加载速度。例如,缓存数据库查询结果、页面片段等。分布式缓存:在分布式系统中,多个节点可以共享 Memcached 缓存,避免数据的重复计算和存储。 性能特点 快速读写:数据全部存储在内存中,且采用简单的键值存储模型,读写操作非常快速。多线程处理:多线程模型使其在多核处理器上能更好地利用 CPU 资源,提高并发处理能力。 LevelDB 使用场景 嵌入式系统:由于其轻量级和嵌入式的特点,适合在资源受限的嵌入式设备中使用,如智能家居设备、传感器节点等。元数据存储:可用于存储分布式系统中的元数据,如文件系统的元数据、数据库的索引信息等。 性能特点 顺序读写性能好:LSM 树结构使得顺序写入和读取操作非常高效,适合批量数据处理。随机读写性能相对较弱:由于需要在多个 SSTable 中查找数据,随机读写的性能不如内存型 KV 引擎。 RocksDB 使用场景 大数据分析:在大数据处理框架中,如 Hadoop、Spark 等,可作为数据存储引擎,支持海量数据的存储和快速查询。区块链:用于存储区块链的账本数据,保证数据的持久性和一致性。 性能特点 高并发处理能力:多线程并发操作和优化的 LSM 树结构使其在高并发场景下表现出色。可配置性强:提供了丰富的配置选项,可以根据不同的应用场景进行调优,以达到最佳性能。 总结 kv存储简单的说就是一个key对应一个value。这个项目整体就是借助之前学习中已经实现好的网络层和数据结构,实现数据的高效存储。 参考文章 https://github.com/0voice 一文看遍各大互联网公司的分布式KV系统概述