raft+rocksdb实现秒级生成快照

背景

hugegraph使用jraft+rocksdb的checkpoint实现了快照,这样能保证服务重启或者有新节点加入时快速同步状态机的数据。但是由于目前实现的只是多副本版,所以每一个服务都是存储着全部的数据。

当服务导入较多数据后,每生成一次快照耗时几分钟,再把快照压缩又需要几分钟,在这期间占用了较多的CPU资源,并且随着数据量的持续增长,很容易出现上一次的快照还未生成完,又要生成新一波的快照了。很容易导致服务不可用。

在之前的一片文章《定位rocksdb生成快照慢问题》中,已经提到:生成快照慢是因为保存快照文件的磁盘和保存原始数据的盘不是同一个盘,跨盘是不能进行硬链接的,所以rocksdb的checkpoint就走了copy file的分支,这样自然就慢了。所以解决方法就是:将快照目录设置为原始数据的兄弟目录,这样能保证是同一块磁盘,checkpoint一定会走硬链接。

生成快照

优化前保存快照的目录结构如下:

disk1/raftlog/snapshot/_128/ss.zip
                           /snapshot_meta
                           /ss/g/{md5}/sst,manifest,log
                              /m/{md5}/sst,manifest,log
                              /s/{md5}/sst,manifest,log

这里为什么会存在 md5 这一级目录呢?因为每个store(g/m/s)都可以配置多个数据目录用来保存其不同类型的数据,比如对于 store g,vertex 和 edge 可以配置成不同的目录,所以这里就会对 vertex 和 edge 的目录各自做 md5 运算,然后加载的时候通过遍历的方式进行目录匹配,代码风格实在是不太好。

优化后保存快照的目录结构如下:

# 原始数据目录
disk1/rocksdb_data/g
                  /m
                  /s
# 对应的快照目录
disk1/snapshot_rocksdb_data/g
                           /m
                           /s

# 原始数据目录
disk2/rocksdb_vertex/g
                    /m
                    /s
# 对应的快照目录
disk2/snapshot_rocksdb_vertex/g
                             /m
                             /s

结构很清晰,就是在每一个原始数据目录的父级目录下,放置一个带snapshot前缀的快照目录,然后目录内部的结构与原始数据目录完全相同。这样能保证快照目录与原始数据目录一定是同一个磁盘上的,能够使用硬链接的方式快速生成快照。

所以设置好快照目录结构后,代码就很简单了,因为核心的调用 checkpoint 的部分已经实现过了,只需要将目录的层级关系配置好即可。具体实现中使用 Path 类做相关的操作比用字符串或 File 都方便一些。

加载快照

上面已经实现了秒极生成快照,但还有一个问题就是:如何加载快照?

为什么加载快照会成为一个问题呢,直接把原始数据删除,然后把快照目录重命名为原始数据目录不就可以了吗?核心步骤当然是这样,但是这样存在的一个问题是:如果本次启动服务删除了快照目录,并且在下次生成快照前服务就宕掉了,那下次启动服务的时候可就没有快照目录供重命名了。所以在raft模式下,不能在加载快照时把快照目录删除。

既然不能删除,又必须得加载快照,怎么办呢?很简单,再做一次硬链接不就可以了吗。

话不多说,看下面的示意图即可。

# 原始数据目录
disk1/rocksdb_data/g
                  /g_link    <--------+ 
                  /m                  |
                  /m_link             |
                  /s                  |
                  /s_link             |
# 对应的快照目录                        |
disk1/snapshot_rocksdb_data/g  -------+
                           /m
                           /s

# 原始数据目录
disk2/rocksdb_vertex/g
                    /g_link
                    /m
                    /m_link
                    /s
                    /s_link
# 对应的快照目录
disk2/snapshot_rocksdb_vertex/g
                             /m
                             /s

加载快照时的日志

2021-03-26 11:23:24 11696 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.raft.StoreStateMachine [] - The node 127.0.0.1:8281 start snapshot loading
2021-03-26 11:23:24 11896 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Delete origin data directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/m
2021-03-26 11:23:24 11903 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Move snapshot directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/m_link to /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/m
2021-03-26 11:23:24 11936 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStore [] - The store 'm' resume snapshot successfully
2021-03-26 11:23:24 11970 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Delete origin data directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/g
2021-03-26 11:23:24 11973 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Move snapshot directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/g_link to /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/g
2021-03-26 11:23:24 11989 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Delete origin data directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-vertex/g
2021-03-26 11:23:24 11991 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Move snapshot directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-vertex/g_link to /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-vertex/g
2021-03-26 11:23:24 11997 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStore [] - The store 'g' resume snapshot successfully
2021-03-26 11:23:24 12020 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Delete origin data directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/s
2021-03-26 11:23:24 12023 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStdSessions [] - Move snapshot directory /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/s_link to /Users/liningrui/IdeaProjects/baidu/xbu-data/hugegraph/node1/rocksdb-data/s
2021-03-26 11:23:24 12037 [JRaft-FSMCaller-Disruptor-0] [INFO ] com.baidu.hugegraph.backend.store.rocksdb.RocksDBStore [] - The store 's' resume snapshot successfully

你可能感兴趣的:(raft+rocksdb实现秒级生成快照)