Eventually-Consistent Storage Backends

  • 当Janusgraph运行在具有最终一致性的存储后端上时,为了保证数据的一致性,需要使用Janusgraph支持最终一致性的特性。(即:如果不想保证一些数据的最终一致性,则可以不使用,为了性能考虑,JanusGraph对存储的元素都不保证一致性。)
  • 支持最终一致性存储后端: Apache Cassandra or Apache HBase
  • 下面总结了如果保证数据(顶点、属性、边、索引)的一致性的方法。下文的存储后端都均是指具有最终一致性的存储后端。如果存储后端不具有最终一致性,那么下面的措施也无法保证数据的一致性

Data Consistency

  • 由于存储后端不提供事务隔离,所以JanusGraph为了保证数据的一致性,就必须通过锁机制

  • 为了效率,JanusGraph默认不采用锁,但是用户可以对需要保证一致性的schema 元素选择使用锁。

  • 设置数据一致性方法:

//element 元素:Property、VertexLabel、Index、EdgeLabel
//ConsistencyModifier.LOCK加锁
JanusGraphManagement.setConsistency(element, ConsistencyModifier.LOCK) 

案例

  • 下面对consistentName属性、byConsistentName索引进行了加锁,从而可以保证数据的一致性。
mgmt = graph.openManagement()
name = mgmt.makePropertyKey('consistentName').dataType(String.class).make()
index = mgmt.buildIndex('byConsistentName', Vertex.class).addKey(name).unique().buildCompositeIndex()
mgmt.setConsistency(name, ConsistencyModifier.LOCK) //确保每个顶点只有一个name,默认不保证此name是SINGLE
mgmt.setConsistency(index, ConsistencyModifier.LOCK) // 确保name值具有唯一性
mgmt.commit()

通过锁保证数据一致性原理

  • 在一个事务中修改具有一致性约束的元素时,当事务结束时( tx.commit())JanusGraph会执行如下策略(乐观锁)来保证数据一致性:(注意是在事务结束后进行验证)

    • 1.新开启一个事务,对被一致性约束的所有元素获取一个锁
    • 2.在新的事务里,从数据库中重新读取所有元素的值,验证事务里元素的状态是修改后元素的之前状态。如果不是,则发生并发修改问题,抛出PermanentLocking exception。
    • 3.保存事务状态到数据库
    • 4.释放所有锁。
  • 锁机制中还有一些优化:本地冲突检测、失败场景检测

JanusGraph锁实现类

  • JanusGraph对锁协议进行了接口抽象,当前提供了2种实现。

    • 1.A locking implementation based on key-consistent read and write operations that is agnostic to the underlying storage backend as long as it supports key-consistent operations (which includes Cassandra and HBase). This is the default implementation and uses timestamp based lock applications to determine which transaction holds the lock.
    • 2.A Cassandra specific locking implementation based on the Astyanax locking recipe.
  • 注:对于需要严格保证数据一致性的应用,建议使用具有事务隔离级别的存储后端。

Data Consistency without Locks

---待更新

你可能感兴趣的:(Eventually-Consistent Storage Backends)