Dgraph事务详解

作者: 贺大伟 | 来源:发表于2018-08-16 11:19 被阅读73次

    Dgraph是可扩展的,分布式的,低延迟图形数据库,采用badger作为存储引擎。DGraph 的目标是提供 Google 生产水平的规模和吞吐量,在超过TB的结构数据里,为用户提供足够低延迟的实时查询。DGraph 支持 GraphQL 作为查询语言,响应 JSON。Dgraph 0.9开始支持事务,下面我们就详细介绍一下Dgraph事务模型。

    如上图所示,参与事务的角色有:

    Client:事务的发起者,网络客户端。

    Dgraph server:Dgraph http server,负责接收处理client的http读写请求。

    Zero server:Dgraph集群的中心节点,负责元数据维护,事务管理,负载均衡等工作,多副本部署,使用raft协议保证高可用和数据一致性。

    Worker server:Dgraph 数据存储处理节点,多副本部署,使用raft协议保证高可用和数据一致性。

    1. 创建事务。

    Dgraph server收到client的写请求,创建一个事务Txn,从Zero server申请一个事务开始时间戳startTS

    2.    预写事务。

    Dgraph server向所有参与事务的worker server发起预写请求

    从这里提交raft log,预写日志在提交raft之前不会检查事务冲突。

    Worker server raft apply预写Txn的时候才会进行事务冲突检查,Dgraph 的事务一定程度上利用了raft 串行apply来解决并行写冲突。

    上图中detectPendingTxns()方法中会进行写冲突检查。

    如果事务没有冲突,那么注册本地事务,此时所有要写入磁盘的数据都暂时缓存在内存中,等待commit.

    事务未提交以前,要写入的数据都存储在内存中。这里需要说明一下,Dgraph对数据的存储是多版本存储,底层的badger支持多版本事务(本地事务),但是如果预写数据直接存储在磁盘上的话,没有特殊的读写控制,则事务隔离存在问题,因此(作者没有对事务的设计做说明,至少我没有找到,这是我根据代码逻辑的推理)需要将数据暂时放在内存里。数据在内存里的组织是按照postlist组织(不是很了解图的数据逻辑,推测应该跟ES中的postlist类似,从作者的部分注释中也可以看出,为了加速读,Dgraph会在内存中缓存postlist(多版本的postlist,以start TS作为版本,一个map结构管理))

    预写数据会暂时存入postlist,如下:

    提交的时候会整体序列化后写入磁盘,版本是commitTS

    3.    事务提交和终止

    事务预写成功后,dgraph server向zero server发起commit or abort请求。

    Zero server收到commit请求,会写入一条raft log,zero server在apply Txn commit日志时向所有参与事务的worker server发送commit命令。

    Zero server会把commit命令放入一个异步队列,异步向worker server发起commit操作。

    这里需要说明的是,如果我们要终止一个事务,那么仍然会发送commit命令给worker server,只是其中的commitTS设置为0.

    这里需要说明的是:

    1.    zero server会对一系列要commit的事务按照commitTS排序,保证顺序提交。

    2.    zero server提交raft commit log成功即认为事务一定会成功,所以会在提交前分片commitTS。

    worker server会在一直向zero server订阅(利用grpc stream),实时接收commit命令。

    Worker server接收到zero

    server的commit命令也会提交一条raft log。

    这样就完成了事务的提交,数据落盘。

    之前也介绍了如果要终止一个事务,zero server发送commit时Txn的commitTS=0,这里在toDisk的时候,检查如果commitTs==0,那么不执行写磁盘操作。

    事务两阶段提交过程中每一个过程都通过raft log持久化,因此事务过程中发生意外,仍然可以保证事务最终提交成功。

    同时Dgraph的事务并发冲突主要依赖raft的串行apply机制解决。

    Dgraph事务超时机制

    worker server会定期检查本地未提交的事务是否超时,超时时间默认是5分钟,如果发现超时,则通知zero server取消本次事务。

    Dgraph 事务补偿机制

    Dgraph事务如果在zero server commit阶段失败,Dgraph server会对事务进行补偿,补偿依赖zero server定期检查(30s)各个worker server的最后一次提交事务的时间戳,根据查询到各个worker server的最后一次事务提交成功的时间戳更新zero server维护的minTS,Dgrpah server会定期检查(10s)minTS来决定哪个时间戳之前的raft 日志可以做快照。这样未完成的事务有机会被补偿执行。

    不过仍然存在不严谨的地方,如前面所说,worker server会定期订阅zero server的事务commit通知,但是zero server并没有机制保证commit的时候所有的worker都在订阅(比如worker发生leader切换),这样事务会存在部分提交的问题。目前没有看到相关的处理机制。

    参考资料

    https://github.com/dgraph-io/dgraph

    https://www.jianshu.com/p/db730cbf282f

    https://yq.aliyun.com/articles/599124

    相关文章

      网友评论

      • 绽放_f8b6:您好,我想问下,raft log是要实时查询的吗?我现在碰到一个问题,Unable to find log file,please retry.现在没找到解决办法,想请教下您,不知道方不方便加个联系方式。或者互相关注。谢谢

      本文标题:Dgraph事务详解

      本文链接:https://www.haomeiwen.com/subject/wyhnbftx.html