neo4j实现分布式锁

neo4j实现分布式锁

应用场景:分布式环境下,希望能够生成一个唯一自增的序列号,自增序列号的存储使用neo4j

问题一:使用neo4j存储,节点的属性使用一个定值,节点的属性值是自增的,首先是节点的创建,分布式环境下,节点的创建无法保证,因为比如两个线程同时创建节点,第一个线程判断neo4j中没有该节点,准备创建;这时,还没有创建成功,第二个线程进入判断该节点不存在,创建节点,这样就会创建两个节点,这样是不对的。

解决办法:可以使用一个脚本,将该节点事先创建好

问题二:要保证更改节点的属性值的操作是一个原子性操作,不能先查出该节点,再将该节点的属性值自增,这样存在的问题同问题一

解决方法:写一个Cypher查询语句同时实现查询和自增:match (n:lock) set n.num = case when exists(n.num) then n.num + 1 else 1 end return n.num

实现代码:

// 创建节点,这个方法是要有的,避免节点未创建报错,但是要注意初始化节点不能被两个线程同时访问
public Boolean createAutoIncrementLock(String enterpriseCode, String serverCode) {
    openDriver();
    try (Session session = driver.session()) {
        try (Transaction transaction = session.beginTransaction()) {
            String searchSql = "match (l: " + Neo4jDBNodeType.IotAutoIncrementLock +  " {" + BaseFiled.ENTERPRISECODE + ":'" + enterpriseCode + "'," +  BaseFiled.SERVERCODE + ":'" + serverCode + "'}) return count(l)";
            StatementResult statementResultSearch = transaction.run(searchSql);
            List<Record> recordListSearch = statementResultSearch.list();
            if (CollectionUtils.isEmpty(recordListSearch) || recordListSearch.get(0).values().get(0).asInt() < 1) {
                String createSql = "create (l: " + Neo4jDBNodeType.IotAutoIncrementLock +  " {" + BaseFiled.ENTERPRISECODE + ":'" + enterpriseCode + "'," +  BaseFiled.SERVERCODE + ":'" + serverCode + "'}) return count(l)";
                StatementResult statementResultCreate = transaction.run(createSql);
                List<Record> recordListCreate = statementResultCreate.list();
                if (CollectionUtils.isEmpty(recordListCreate) || recordListCreate.get(0).values().get(0).asInt() < 1) {
                    transaction.failure();
                    return false;
                }
            }
            transaction.success();
            return true;
        }
    }
}

// 获取自增锁的属性值
public String getAutoIncrementLock(String field, String enterpriseCode, String serverCode) {
    openDriver();
    try (Session session = driver.session()) {
        try (Transaction transaction = session.beginTransaction()) {
            if (!createAutoIncrementLock(enterpriseCode, serverCode)) {
                return null;
            }
            String sql = "match (l: " + Neo4jDBNodeType.IotAutoIncrementLock + "{" + BaseFiled.ENTERPRISECODE + ":'" + enterpriseCode + "'," +  BaseFiled.SERVERCODE + ":'" + serverCode + "'}" + ") set l."+field+" = case when exists(l."+field+") then l."+field+" + 1 else 1 end return l."+field;
            logger.info("执行的sql:" + sql);
            logger.info("开始执行时间:" + System.currentTimeMillis());
            StatementResult statementResult = transaction.run(sql);
            List<Record> recordListSet = statementResult.list();
            if (CollectionUtils.isEmpty(recordListSet) || recordListSet.get(0).values().get(0).asInt() < 1) {
                transaction.failure();
                return null;
            }
            transaction.success();
            logger.info("结束时间:" + System.currentTimeMillis() + ",结果:" + recordListSet.get(0).values().get(0).asInt());
            return String.valueOf(recordListSet.get(0).values().get(0).asInt());
        }
    }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值