受益匪浅!图解Janusgraph系列 并发安全:锁机制(本地锁+分布式锁)超全分析

本文深入探讨了JanusGraph的分布式锁机制,包括一致性行为、LockID、本地锁和分布式锁的实现。JanusGraph通过数据库锁来保证并发安全,其中本地锁确保图实例内操作无冲突,分布式锁通过HBase实现并发控制。在数据导入时,可选择开启或关闭分布式锁以平衡一致性和性能需求。
摘要由CSDN通过智能技术生成

前言

在分布式系统中,难免涉及到对同一数据的并发操作,如何保证分布式系统中数据的并发安全呢?分布式锁!

一:分布式锁

常用的分布式锁实现方式:

1、基于数据库实现分布式锁

​ 针对于数据库实现的分布式锁,如mysql使用使用for update共同竞争一个行锁来实现; 在JanusGraph中,也是基于数据库实现的分布式锁,这里的数据库指的是我们当前使用的第三方backend storage,具体的实现方式也和mysql有所不同,具体我们会在下文分析

2、基于Redis实现的分布式锁

​ 基于lua脚本+setNx实现

3、基于zk实现的分布式锁

​ 基于znode的有序性和临时节点+zk的watcher机制实现

4、MVCC多版本并发控制乐观锁实现

本文主要介绍Janusgraph的锁机制,其他的实现机制就不在此做详解了

下面我们来分析一下JanusGraph锁机制实现~

二:JanusGraph锁机制

在JanusGraph中使用的锁机制是:本地锁 + 分布式锁来实现的;

2.1 一致性行为

JanusGraph中主要有三种一致性修饰词(Consistency Modifier)来表示3种不同的一致性行为,来控制图库使用过程中的并发问题的控制程度;

public enum ConsistencyModifier {
    DEFAULT,
    LOCK,
    FORK
}

源码中ConsistencyModifier枚举类主要作用:用于控制JanusGraph在最终一致或其他非事务性后端系统上的一致性行为!其作用分别为:

  • DEFAULT:默认的一致性行为,不使用分布式锁进行控制,对配置的存储后端使用由封闭事务保证的默认一致性模型,一致性行为主要取决于存储后端的配置以及封闭事务的(可选)配置;无需显示配置即可使用
  • LOCK:在存储后端支持锁的前提下,显示的获取分布式锁以保证一致性!确切的一致性保证取决于所配置的锁实现;需management.setConsistency(element, ConsistencyModifier.LOCK);语句进行配置
  • FORK:只适用于multi-edgeslist-properties两种情况下使用;使JanusGraph修改数据时,采用先删除后添加新的边/属性的方式,而不是覆盖现有的边/属性,从而避免潜在的并发写入冲突;需management.setConsistency(element, ConsistencyModifier.FORK);进行配置

LOCK

在查询或者插入数据时,是否使用分布式锁进行并发控制,在图shcema的创建过程中,如上述可以通过配置schema元素ConsistencyModifier.LOCK方式控制并发,则在使用过程中就会用分布式锁进行并发控制;

为了提高效率,JanusGraph默认不使用锁定。 因此,用户必须为定义一致性约束的每个架构元素决定是否使用锁定。

使用JanusGraphManagement.setConsistency(element,ConsistencyModifier.LOCK)显式启用对架构元素的锁定

代码如下所示:

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) // Ensures only one name per vertex 
mgmt.setConsistency(index, ConsistencyModifier.LOCK) // Ensures name uniqueness in the graph 
mgmt.commit()

FORK

由于边缘作为单个记录存储在基础存储后端中,因此同时修改单个边缘将导致冲突。

FORK就是为了代替LOCK,可以将边缘标签配置为使用ConsistencyModifier.FORK

下面的示例创建一个新的edge label,并将其设置为ConsistencyModifier.FORK

mgmt = graph.openManagement() 
related = mgmt.makeEdgeLabel('related').make() 
mgmt.setConsistency(related, ConsistencyModifier.FORK) 
mgmt.commit()

经过上述配置后,修改标签配置为FORK的edge时,操作步骤为:

  1. 首先,删除该边
  2. 将修改后的边作为新边添加

因此,如果两个并发事务修改了同一边缘,则提交时将存在边缘的两个修改后的副本,可以在查询遍历期间根据需要解决这些副本。

注意edge fork仅适用于MULTI edge。 具有多重性约束的边缘标签不能使用此策略,因为非MULTI的边缘标签定义中内置了一个唯一性约束,该约束需要显式锁定或使用基础存储后端的冲突解决机制

下面我们具体来看一下janusgrph锁机制的实现:

2.2 LoackID

在介绍锁机制之前,先看一下锁应该锁什么东西呢?

我们都知道在j

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值