在非分布式系统中要实现锁的机制很简单,利用java.util.concurrent.locks包下的Lock和关键字synchronized都可以实现。但是在分布式系统中,如何实现各个单独的微服务需要共享某个资源的时候进行有效的锁的保护机制呢?这边使用Redisson来实现。

一、Redisson简介
  Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。更多,https://github.com/redisson/redisson/wiki/1.-%E6%A6%82%E8%BF%B0

二、springboot+redission 演示
  1、pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.3.2</version>
</dependency>
</dependencies>

  2、application.properties

server.port=8070

# redisson
redisson.address=192.168.3.3:6379
redisson.password=test123

  3、DistributedLocker

import java.util.concurrent.TimeUnit;

/**
* 定义Lock的接口类
* @author ko
*
*/
public interface DistributedLocker { void lock(String lockKey); void unlock(String lockKey); void lock(String lockKey, int timeout); void lock(String lockKey, TimeUnit unit ,int timeout);
}

  4、RedissonDistributedLocker

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient; import com.redlock.locker.DistributedLocker; import java.util.concurrent.TimeUnit; /**
* Lock接口实现类
* @author ko
*
*/
public class RedissonDistributedLocker implements DistributedLocker { private RedissonClient redissonClient; @Override
public void lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
} @Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
} @Override
public void lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
} @Override
public void lock(String lockKey, TimeUnit unit ,int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
} public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
}

  5、RedissonProperties

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* redisson属性装配类
* @author ko
*
*/
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties { private int timeout = 3000; private String address; private String password; private int connectionPoolSize = 64; private int connectionMinimumIdleSize=10; private int slaveConnectionPoolSize = 250; private int masterConnectionPoolSize = 250; private String[] sentinelAddresses; private String masterName; public int getTimeout() {
return timeout;
} public void setTimeout(int timeout) {
this.timeout = timeout;
} public int getSlaveConnectionPoolSize() {
return slaveConnectionPoolSize;
} public void setSlaveConnectionPoolSize(int slaveConnectionPoolSize) {
this.slaveConnectionPoolSize = slaveConnectionPoolSize;
} public int getMasterConnectionPoolSize() {
return masterConnectionPoolSize;
} public void setMasterConnectionPoolSize(int masterConnectionPoolSize) {
this.masterConnectionPoolSize = masterConnectionPoolSize;
} public String[] getSentinelAddresses() {
return sentinelAddresses;
} public void setSentinelAddresses(String sentinelAddresses) {
this.sentinelAddresses = sentinelAddresses.split(",");
} public String getMasterName() {
return masterName;
} public void setMasterName(String masterName) {
this.masterName = masterName;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public int getConnectionPoolSize() {
return connectionPoolSize;
} public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
} public int getConnectionMinimumIdleSize() {
return connectionMinimumIdleSize;
} public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {
this.connectionMinimumIdleSize = connectionMinimumIdleSize;
}
}

  6、RedissLockUtil

import java.util.concurrent.TimeUnit;

import com.redlock.locker.DistributedLocker;

/**
* redis分布式锁工具类
* @author ko
*
*/
public class RedissLockUtil {
private static DistributedLocker redissLock; public static void setLocker(DistributedLocker locker) {
redissLock = locker;
} public static void lock(String lockKey) {
redissLock.lock(lockKey);
} public static void unlock(String lockKey) {
redissLock.unlock(lockKey);
} /**
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位:秒
*/
public static void lock(String lockKey, int timeout) {
redissLock.lock(lockKey, timeout);
} /**
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
public static void lock(String lockKey, TimeUnit unit ,int timeout) {
redissLock.lock(lockKey, unit, timeout);
}
}

  7、RedissonAutoConfiguration

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.redlock.bean.RedissonProperties;
import com.redlock.locker.DistributedLocker;
import com.redlock.locker.impl.RedissonDistributedLocker;
import com.redlock.util.RedissLockUtil; /**
* Redisson+springboot 自动配置类
* @author ko
*
*/
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration { @Autowired
private RedissonProperties redssionProperties; /**
* 哨兵模式自动装配
* @return
*/
@Bean
@ConditionalOnProperty(name="redisson.master-name")
RedissonClient redissonSentinel() {
Config config = new Config();
SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redssionProperties.getSentinelAddresses())
.setMasterName(redssionProperties.getMasterName())
.setTimeout(redssionProperties.getTimeout())
.setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize())
.setSlaveConnectionPoolSize(redssionProperties.getSlaveConnectionPoolSize()); if(redssionProperties.getPassword() != null && !"".equals(redssionProperties.getPassword())) {
serverConfig.setPassword(redssionProperties.getPassword());
}
return Redisson.create(config);
} /**
* 单机模式自动装配
* @return
*/
@Bean
@ConditionalOnProperty(name="redisson.address")
RedissonClient redissonSingle() {
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redssionProperties.getAddress())
.setTimeout(redssionProperties.getTimeout())
.setConnectionPoolSize(redssionProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize()); if(redssionProperties.getPassword() != null && !"".equals(redssionProperties.getPassword())) {
serverConfig.setPassword(redssionProperties.getPassword());
} return Redisson.create(config); } /**
* 装配locker类,并将实例注入到RedissLockUtil中
* @return
*/
@Bean
DistributedLocker distributedLocker(RedissonClient redissonClient) {
RedissonDistributedLocker locker = new RedissonDistributedLocker();
locker.setRedissonClient(redissonClient);
RedissLockUtil.setLocker(locker);
return locker;
} }

  8、暴露接口 TestController

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import com.redlock.util.RedissLockUtil; /**
* 测试类
* @author ko
*
*/
@RestController
public class TestController { // private static final Logger LOG = Logger.getLogger(BootApplication.class.getName());
// LOG.log(Level.INFO, "All procn"); private final String _lock = "_lock"; static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String getCurrentDate(){
return sdf.format(new Date());
} @RequestMapping(value = "/testlock",method=RequestMethod.GET)
public String testlock(String name) { new Thread(new Runnable() { @Override
public void run() { RedissLockUtil.lock(_lock, TimeUnit.MINUTES, 10); System.out.println(getCurrentDate()+" "+name+" begin...");
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
System.out.println(getCurrentDate()+" "+name+" "+i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getCurrentDate()+" "+name+" end..."); RedissLockUtil.unlock(_lock);
}
}).start(); return "testlock";
} }

  9、微服务启动类 BootApplication

@SpringBootApplication
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}

三、启动演示

  复制项目,第二个服务的端口改为8071,启动两个服务,先在浏览器里输入http://localhost:8070/testlock?name=zhang,3s后再输入http://localhost:8071/testlock?name=wang,3s后再输入http://localhost:8070/testlock?name=zhang1,3s后再输入http://localhost:8071/testlock?name=wang1,如果没有锁机制,打印的数据应该是交叉的,反之,同一时刻只会打印一次的请求,不会出现交叉打印数据的情况。

官方文档:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

Spring Cloud分布式微服务系统中利用redssion实现分布式锁的更多相关文章

  1. Spring Boot + Spring Cloud 构建微服务系统(八):分布式链路追踪(Sleuth、Zipkin)

    技术背景 在微服务架构中,随着业务发展,系统拆分导致系统调用链路愈发复杂,一个看似简单的前端请求可能最终需要调用很多次后端服务才能完成,那么当整个请求出现问题时,我们很难得知到底是哪个服务出了问题导致 ...

  2. Spring Cloud分布式微服务云架构集成项目

    Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的.在学习Spring Clo ...

  3. Spring Cloud分布式微服务云架构

    分布式.微服务.云架构 JAVA语言开发.跨平台.高性能.高可用.安全.服务化.模块化.組件化.驱动式开发模式 commonservice eurekaNetflix 云端服务发现,一个基于 REST ...

  4. Spring Boot + Spring Cloud 构建微服务系统(九):配置中心(Spring Cloud Config)

    技术背景 如今微服务架构盛行,在分布式系统中,项目日益庞大,子项目日益增多,每个项目都散落着各种配置文件,且随着服务的增加而不断增多.此时,往往某一个基础服务信息变更,都会导致一系列服务的更新和重启, ...

  5. 【SFA官方翻译】Spring WebFlux和Spring Cloud进行响应式微服务开发

    源码,修正一些错误: https://github.com/bigben0123/sample-spring-cloud-webflux 原创 SpringForAll社区 2018-05-18 作者 ...

  6. Spring Boot + Spring Cloud 构建微服务系统(十):配置中心(Spring Cloud Bus)

    技术背景 我们在上一篇讲到,Spring Boot程序只在启动的时候加载配置文件信息,这样在GIT仓库配置修改之后,虽然配置中心服务器能够读取最新的提交信息,但是配置中心客户端却不会重新读取,以至于不 ...

  7. Spring Boot + Spring Cloud 构建微服务系统(七):API服务网关(Zuul)

    技术背景 前面我们通过Ribbon或Feign实现了微服务之间的调用和负载均衡,那我们的各种微服务又要如何提供给外部应用调用呢. 当然,因为是REST API接口,外部客户端直接调用各个微服务是没有问 ...

  8. Spring Boot + Spring Cloud 构建微服务系统(四):容错机制和熔断(Hystrix)

    雪崩效应 在微服务架构中,由于服务众多,通常会涉及多个服务层级的调用,而一旦基础服务发生故障,很可能会导致级联故障,进而造成整个系统不可用,这种现象被称为服务雪崩效应.服务雪崩效应是一种因“服务提供者 ...

  9. Spring Boot + Spring Cloud 构建微服务系统(一):服务注册和发现(Consul)

    使用Consul提供注册和发现服务 什么是 Consul Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其它分布式服务注册与发现的方案,Consul ...

随机推荐

  1. Android开发你不知道的TIPS

    1.Space space是Android 4.0中新增的一个控件,它实际上可以用来分隔不同的控件,其中形成一个空白的区域.这是一个轻量级的视图组件,它可以跳过Draw,对于需要占位符的任何场景来说都 ...

  2. linux打包压缩常用命令

    打包: zip   gzip  bzip2 tar  xz     //rar zip 包 zip   xxx.zip     test.c  压缩 unzip  xxx.zip            ...

  3. Android特效专辑(十)——点击水波纹效果实现,逻辑清晰实现简单

    Android特效专辑(十)--点击水波纹效果实现,逻辑清晰实现简单 这次做的东西呢,和上篇有点类似,就是用比较简单的逻辑思路去实现一些比较好玩的特效,最近也是比较忙,所以博客更新的速度还得看时间去推 ...

  4. github搭建个人网站

    1. 注册账号: 地址: https://github.com/  输入账号.邮箱.密码,然后点击注册按钮.  2. 初始设置 注册完成后,选择Free免费账号完成设置. 2.1 验证邮箱 请打开你的 ...

  5. struts form表单提交action处理之后没有跳转页面

    作为一个ssm新人,对struts的理解也仅仅是书本上一些简单的示例, 对如下这个form进行提交之后,执行完action,并return 一个字符串,在struts配置文件中配置了对应的jsp页面, ...

  6. Linux input子系统分析

    输入输出是用户和产品交互的手段,因此输入驱动开发在Linux驱动开发中很常见.同时,input子系统的分层架构思想在Linux驱动设计中极具代表性和先进性,因此对Linux input子系统进行深入分 ...

  7. os X下mds_stores占用大量cpu的解决办法

    有时候发现, MacOS中, 有个叫做mds_stores的进程占了好多CPU, 于是要阻止这个行为, 据说这是MacOS在建索引然后只要把这个索引的关掉就好了 sh-3.2# mdutil -a - ...

  8. LeetCode(62)-Two Sum

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  9. 恶补web之六:javascript知识(1)

    javascript(下称js)是一种轻量级编程语言,它可以插入html页面然后由浏览器执行. document.write("<h1>...</h1>") ...

  10. 分布式Ruby解决之道

    其实用Druby很久了,今天需要完成一个进程数据同步的机制,我需要的不是运行速度快,不是用 linux / mac 下的扩展,而是独立,快速开发效率,方便最简单的Ruby环境可运行,可以吗? DRb( ...