- 当Janusgraph运行在具有最终一致性的存储后端上时,为了保证数据的一致性,需要使用Janusgraph支持最终一致性的特性。(即:如果不想保证一些数据的最终一致性,则可以不使用,为了性能考虑,JanusGraph对存储的元素都不保证一致性。)
- 支持最终一致性存储后端: Apache Cassandra or Apache HBase
- 下面总结了如果保证数据(顶点、属性、边、索引)的一致性的方法。下文的存储后端都均是指具有最终一致性的存储后端。如果存储后端不具有最终一致性,那么下面的措施也无法保证数据的一致性
Data Consistency
由于存储后端不提供事务隔离,所以JanusGraph为了保证数据的一致性(此处的一致性是指事务中ACID的C,而不是CAP的C),就必须通过锁机制
为了效率,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
---待更新