raft中另外一个问题就是log存储了,像360开源的floyd直接是使用的leveldb,选举状态相关存储也是leveldb。
leveldb作为一个嵌入式的kv库自然是能很好的完成这样的功能,本着从学习的角度读了下bfs的log相关代码。
抛开代码,如果自己设计,应该从什么角度考虑?
1.log存储的东西有什么?
对raft而言,需要存储的是大量的(seq, value)和极少量的(key, value)键值对
2.log读写方面有什么特点?
对于seq,有大量的顺序写入(用户操作),有少量的随机范围读取(日志复制)
对于key,有少量但较多的随机写(更新状态),有大量的随机读
3.大概方案?
对key来说挺简单,毕竟key很少,所以文件仅仅是落地做可靠用,一个内存map就可以处理好读写,
初始化=重新依次读入内存
对本需求来说,无法快速定位到某个seq。也许map定位是可以的,但对于海量数据,内存cache显然是不行的。
如果header有损坏怎么跳过本条数据到下一个?
可否在header/foot尾部加一段magic?可以,但如果v比较长,采用朴素的memcmp要比较很久。
本质原因说起来就是没法快速定位下一个header,但header本身其实是定长的,基于这个理由可以 得出这个方案
leveldb作为一个嵌入式的kv库自然是能很好的完成这样的功能,本着从学习的角度读了下bfs的log相关代码。
抛开代码,如果自己设计,应该从什么角度考虑?
1.log存储的东西有什么?
对raft而言,需要存储的是大量的(seq, value)和极少量的(key, value)键值对
2.log读写方面有什么特点?
对于seq,有大量的顺序写入(用户操作),有少量的随机范围读取(日志复制)
对于key,有少量但较多的随机写(更新状态),有大量的随机读
3.大概方案?
对key来说挺简单,毕竟key很少,所以文件仅仅是落地做可靠用,一个内存map就可以处理好读写,
初始化=重新依次读入内存
文件存储套路方面和内存分配器有一点点类似,对于一个存储块,如何知道读完了然后读下一个?
3.1很直观的方式就是前面存一个包含长度和校验码的header,同样也带来问题:对本需求来说,无法快速定位到某个seq。也许map定位是可以的,但对于海量数据,内存cache显然是不行的。
如果header有损坏怎么跳过本条数据到下一个?
可否在header/foot尾部加一段magic?可以,但如果v比较长,采用朴素的memcmp要比较很久。
本质原因说起来就是没法快速定位下一个header,但header本身其实是定长的,基于这个理由可以 得出这个方案