- 论坛徽章:
- 9
|
本帖最后由 wlmqgzm 于 2016-05-09 14:35 编辑
存储层的数据规划思路:
1)主要技术思路与Mangodb接近.分为数据和索引两部分, 数据完全在存放在文件中, 由File mapping管理, 所有的读写全部由操作系统来控制, 代码除了定期flush一下, 就完全不管了. 索引全部放在内存中.
其余部分是与mangoDB不同的:
2)索引部分是真正由自己的代码控制, 主要就是一个"hash(Key)===>(Key_value data)offset"的构造, 实现Key--Value的查询.
查询过程是: Key==>Hash(key) 统一转化为8字节的编码==>hash_map find, map内部第2次hash,==>输出8字节全局Offset==>3字节文件索引号+4字节File offset+1字节块内部索引编号
==>利用file mapping读取数据头, 发现是LZ4压缩, 执行LZ4读, 如果是非压缩格式, 直接读
3)只有索引部分常驻内存, 因此,这部分数据决定了内存的消耗量, 目前的设计是16个字节索引一条记录, 8字节的hash(Key), 8字节的全局Offset. 对于1亿条记录, 总体消耗1.6G内存.
32G内存, 理论上总体可实现20亿条记录的索引全部缓存在内存中, 实际按照80%可用内存消耗计算, 对于32G的单机, 大约是16亿条记录每台服务器.
8字节全局Offset==>3字节文件索引号+4字节File offset+1字节块内部索引编号
3字节索引号 表示最大使用1600万个文件.
4字节File offset 表示每个文件最大4G字节, 其实默认就是4G字节, 也是推荐的参数. 这个可以把4字节的每个比特都用尽, 不浪费.
1字节块内部索引编号 表示每个数据块最大存储254个记录, 其中记录号0保留作为单块单记录的标识, 记录号255保留做未来扩充使用, 能够使用的只有1-254, 一共能够最大存储254个记录.
为了提高性能, 初步确定, 每个数据块内部的记录Offset使用2个字节来表示, 因此,数据块最大长度为64KByte, 这个块的大小是可调整的, 建议的范围是0K--64KB, 这个块大小与Mysql 4K-32K很接近.
最终推荐大小将根据产品的实际测试情况,推荐或者固定为一个最优值.
与过去的其他任何数据库的设计的重要的区别:
1)这次设计的数据块要完全优化SSD, 绝对避免随机写, 任何数据块都是只写一次, 不会有第2次重写, 因此, 为了节约存储空间, 所有的块都是按照实际使用量连续排列的, 内部没有任何浪费,没有任何预留空间, 并且块开头不是4K对齐的.
由于块与块是紧密相连的, 为了故障处理和崩溃恢复, 在块与块之间, 引入了同步隔离码的概念.
2)数据是压缩与非压缩混合的, 任何一个数据块在第一次写入时都是非压缩的, 就是说任何最近的数据都是非压缩格式. 这样提供了最高的读写性能.
对于稍微旧一些的数据(还是有效数据), 或者在夜间时段,或者满足一定的条件, 将在后台低优先级进程启用最高压缩率的处理, 数据将第2次写入, 但是写入到新的区域,
使用LZ4压缩, LZ4压缩方式是HC模式, 即默认高压缩模式, 该模式非常消耗CPU资源, 大约压缩性能与gzip相当, LZ4解压是高性能的, 大约500M字节每秒.
这种设计实现了高性能并发与高压缩比同时兼顾, 并且实现了查询下的高性能解压缩, 从设计理念上是非常先进的.
数据块内部的进一步编码优化: 这个部分尚在仔细考虑设计中, 因为已经决定使用LZ4压缩存储, 对块内部的压缩, 或者没有必要进行额外的压缩处理. (正在考虑是否采用)
长整数编码的压缩设计: 使用压缩编码来编码8字节长整数, 压缩后编码长度范围是1字节到9字节, 平均长度是4字节. 4字节整数的压缩后平均长度是2字节
这部分整数压缩代码虽然已经测试完毕, 但是可能最终会废弃不使用. 整数压缩的原理是: 4-8字节的整数, 可能多数时候只有少数字节是非零的,这样就可以用非零字节数+非零字节来表示, 尤其是全零的整数, 只需要1个字节就可表示.
先提交这部分设计, 后续再写. |
|