9.1 Kvstore
目前KV存储没有持久化,down 之后 就清空。
- 全量持久化。 save() -> 全保存数据集。
- 增量持久化。 每执行一条,把命令写入文件里。下次允许把日志重新运行。
目前KV存储 key value 都是调用的 malloc, 都是系统的内存分配。
- 会出现大量的内存碎片,实现一个内存池,管理内存数据。
- 对比有内存池和没有内存池的性能差异,以及开源内存池 jemalloc 的性能差别。
sudo apt-get install -y libjemalloc-dev
测试:
虚拟内存的占用情况 htop。插入百万条数据集(KV*100w,set 200w del 100w delete 200w set 100w)。
单条插入
无内存池: --> time_used=1488789 ms, ops=6000000, qps=4030
VIRT 105M

自实现内存池: --> time_used=1439444 ms, ops=6000000, qps=4168
VIRT 135M

jemalloc: time_used=1502797 ms, ops=6000000, qps=3992
VIRT 99M
批处理
一次执行100条。
无内存池:--> time_used=142913 ms, ops=6000000, qps=41983
VIRT 99M
自实现内存池: --> time_used=122754 ms, ops=6000000, qps=48878
VIRT 135M
jemalloc:--> time_used=122206 ms, ops=6000000, qps=49097
VIRT 99M
性能分析:
- key :
- A_0: mp_alloc (3+8B) -> 16B, malloc (3B) -> 8B
- A_1000: mp_alloc (6+8B) -> 16B, malloc (3B) -> 8B
- A_100000 : mp_alloc(8+8B) -> 16B, malloc (8B) -> 16B
内存初始状态 25B, malloc (115-25B) = 90B, mp_alloc(193-25B) = 168B,平均浪费接近50%。
目前的kv存储是单指令的,一条指令一交互。
从单挑指令实现批量处理。
对于同一个连接,目前缺少对以下情况的处理:
- 收到半包
- 收到多条消息
对不同连接,隔离他们的消息到不同的缓冲区?要不先不考虑不同的连接的情况?Nytoco代码不是很熟。
如果read->execute->send->read同步循环,不会出现缓冲区被覆盖的情况。但是可能会有半包或者两个命令都抵达了,才触发事件。所以应用层需要解析到完整请求才执行下一步。
目前KV存储是一个单点服务,实现一个主从同步的功能。
主从同步:启动两个KVstore。在a里set,在b里get。
目前的Key和Value都是单个单词的,实现支持特殊字符。
如:空格回车换行。支持插入博客。
这里需要在协议中定义消息长度而不是特殊字符做分隔来确定哪些数据是key哪些是value。
还要修改底层,不要用strlen和strcpy,用memcpy。
面试题
- 为什么会实现kvstore,使用场景在哪里?
- reactor, ntyco, io_uring的三种网络模型的性能差异?
- 多线程的kvstore该如何改进?
- 私有协议如何设计会更加安全可靠?
- 协议改进以后,对已有的代码有哪些改变?
- kv引擎实现了哪些?
- 每个kv引擎的使用场景,以及性能差异?
- 测试用例如何实现?并且保证代码覆盖率超过90%
- 网络并发量如何?qps如何?
- 能够跟哪些系统交互使用?
