欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

分析需求 劳务派遣信息管理系统 :显然

点击: 次  来源:劳务派遣管理系统 时间:2017-11-11

原文出处: 徐靖峰

漫衍式遭遇并发

在前面的章节,昆山软件开发,并发操纵要么产生在单个应用内,一般利用基于JVM的lock办理并发问题,要么产生在数据库,可以思量利用数据库层面的锁,而在漫衍式场景下,需要担保多个应用实例都可以或许执行同步代码,则需要做一些特另外事情,一个最典范漫衍式同步方案即是利用漫衍式锁。

漫衍式锁由许多种实现,但本质上都是雷同的,即依赖于共享组件实现锁的询问和获取,假如说单体式应用中的Monitor是由JVM提供的,那么漫衍式下Monitor即是由共享组件提供,而典范的共享组件各人其实并不生疏,包罗但不限于:Mysql,Redis,Zookeeper。同时他们也代表了三种范例的共享组件:数据库,缓存,漫衍式协调组件。基于Consul的漫衍式锁,其实和基于Zookeeper的漫衍式锁大同小异,都是借助于漫衍式协调组件实现锁,大而化之,这三种范例的漫衍式锁,道理也都差不多,只不外,锁的特性和实现细节有所差别。

Redis实现漫衍式锁

界说需求:A应用需要完成添加库存的操纵,陈设了A1,A2,A3多个实例,实例之间的操纵要担保同步。

阐明需求:显然,此时依赖于JVM的lock已经没步伐办理问题了,A1添加锁,无法担保A2,A3的同步,这种场景可以思量利用漫衍式锁应对。

成立一张Stock表,包括id,number两个字段,别离让A1,A2,A3并发对其操纵,担保线程安详。

@Entity
public class Stock {
    @Id
    private String id;
    private Integer number;
}

界说数据库会见层:

public interface StockRepository extends JpaRepository<Stock,String> {
}

这一节的主角,redis漫衍式锁,利用开源的redis漫衍式锁实现:Redisson。

引入Redisson依赖:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.5.4</version>
</dependency>

界说测试类:

@RestController
public class StockController {
    @Autowired
    StockRepository stockRepository;
    ExecutorService executorService = Executors.newFixedThreadPool(10);
    @Autowired
    RedissonClient redissonClient;
    final static String id = "1";
    @RequestMapping("/addStock")
    public void addStock() {
        RLock lock = redissonClient.getLock("redisson:lock:stock:" + id);
        for (int i = 0; i < 100; i++) {
            executorService.execute(() -> {
                lock.lock();
                try {
                    Stock stock = stockRepository.findOne(id);
                    stock.setNumber(stock.getNumber() + 1);
                    stockRepository.save(stock);
                } finally {
                    lock.unlock();
                }
            });
        }
    }
}

上述的代码使得并发产生在多个层面。其一,在应用内部,启用线程池完成库存的加1操纵,自己即是线程不安详的,其二,在多个应用之间,这样的加1操纵越发是不受约束的。若初始化id为1的Stock数量为0。别离在当地启用A1(8080),A2(8081),A3(8082)三个应用,同时并发执行一次addStock(),若线程安详,一定可以使得数据库中的Stock为300,这即是我们的检测依据。

简朴解读下上述的代码,利用redisson获取一把RLock,RLock是java.util.concurrent.locks.Lock接口的实现类,Redisson辅佐我们屏蔽Redis漫衍式锁的实现细节,利用过java.util.concurrent.locks.Lock的伴侣城市知道下述的代码可以被称得上是同步的起手范式,究竟这是Lock的java doc中给出的代码:

Lock l = ...;
l.lock();
try {
   // access the resource protected by this lock
} finally {
  l.unlock();
}

而redissonClient.getLock(“redisson:lock:stock:” + id)则是以”redisson:lock:stock:” + id该字符串作痛同步的Monitor,担保了差异id之间是相互不阻塞的。

为了担保产生并发,实际测试中我插手了Thread.sleep(1000),使竞争得以产生。测试功效:

 阐明需求 劳务调派信息打点系统 :显然

Redis漫衍式锁简直起了浸染。

锁的留意点

假如仅仅是实现一个可以或许用于demo的Redis漫衍式锁并不难,但为何各人更方向于利用开源的实现呢?主要照旧可用性和不变性,we make things work是我在写博客,写代码时紧记在脑海中的,假如然的要细究如何本身实现一个漫衍式锁,可能平时利用锁担保并发,需要有哪些留意点呢?罗列几点:阻塞,超时时间,可重入,可用性,其他特性。

阻塞