分布式——分布式锁全套代码实现(zk,redisson,redis等)

分布式——分布式锁全套代码实现(zk,redisson,redis等),第1张

分布式——分布式锁全套代码实现(zk,redisson,redis等)

文章目录
  • 1、乐观锁,悲观锁
  • 2、Redis分布式锁(setnx+lua)自动释放锁
  • 3、Zookeeper实现分布式锁
  • 4、Zookeeper的Curator实现分布式锁
  • 5、Spring集成Redisson原生
  • 6、SpringBoot集成Redisson

1、乐观锁,悲观锁

乐观锁:版本号,也就是version字段;时间戳 AtomicInteger相关类
悲观锁:for update 对标单体的Synchronized,ReentrantLock

2、Redis分布式锁(setnx+lua)自动释放锁

pom

 
    org.springframework.boot
    spring-boot-starter-data-redis
		2.1.7.RELEASE        

application.properties

spring.redis.host=localhost
spring.redis.password=123456

工具类

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.Redisscript;
import org.springframework.data.redis.core.types.Expiration;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Slf4j
public class RedisLock implements AutoCloseable {

    private RedisTemplate redisTemplate;
    private String key;
    private String value;
    //单位:秒
    private int expireTime;

    public RedisLock(RedisTemplate redisTemplate,String key,int expireTime){
        this.redisTemplate = redisTemplate;
        this.key = key;
        this.expireTime=expireTime;
        this.value = UUID.randomUUID().toString();
    }

    
    public boolean getLock(){
        RedisCallback redisCallback = connection -> {
            //设置NX
            RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
            //设置过期时间
            Expiration expiration = Expiration.seconds(expireTime);
            //序列化key
            byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
            //序列化value
            byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);
            //执行setnx *** 作
            Boolean result = connection.set(redisKey, redisValue, expiration, setOption);
            return result;
        };

        //获取分布式锁
        Boolean lock = (Boolean)redisTemplate.execute(redisCallback);
        return lock;
    }

    public boolean unLock() {
        String script = "if redis.call("get",KEYS[1]) == ARGV[1] thenn" +
                "    return redis.call("del",KEYS[1])n" +
                "elsen" +
                "    return 0n" +
                "end";
        Redisscript redisscript = Redisscript.of(script,Boolean.class);
        List keys = Arrays.asList(key);

        Boolean result = (Boolean)redisTemplate.execute(redisscript, keys, value);
        log.info("释放锁的结果:"+result);
        return result;
    }


    @Override
    public void close() throws Exception {
        unLock();
    }
}

加锁

@Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("redisLock")
    public String redisLock(){
        log.info("我进入了方法!");
        try (RedisLock redisLock = new RedisLock(redisTemplate,"redisKey",30)){
            if (redisLock.getLock()) {
                log.info("我进入了锁!!");
                Thread.sleep(15000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("方法执行完成");
        return "方法执行完成";
    }
3、Zookeeper实现分布式锁

pom


		org.apache.zookeeper
		zookeeper
		3.4.14

工具类(自动释放锁)

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

@Slf4j
public class ZkLock implements AutoCloseable, Watcher {

    private ZooKeeper zooKeeper;
    private String znode;

    public ZkLock() throws IOException {
        this.zooKeeper = new ZooKeeper("localhost:2181",
                10000,this);
    }

    public boolean getLock(String businessCode) {
        try {
            //创建业务 根节点
            Stat stat = zooKeeper.exists("/" + businessCode, false);
            if (stat==null){
                zooKeeper.create("/" + businessCode,businessCode.getBytes(),
                        ZooDefs.Ids.OPEN_ACL_UNSAFE,
                        CreateMode.PERSISTENT);
            }

            //创建瞬时有序节点  /order/order_00000001
            znode = zooKeeper.create("/" + businessCode + "/" + businessCode + "_", businessCode.getBytes(),
                    ZooDefs.Ids.OPEN_ACL_UNSAFE,
                    CreateMode.EPHEMERAL_SEQUENTIAL);

            //获取业务节点下 所有的子节点
            List childrenNodes = zooKeeper.getChildren("/" + businessCode, false);
            //子节点排序
            Collections.sort(childrenNodes);
            //获取序号最小的(第一个)子节点
            String firstNode = childrenNodes.get(0);
            //如果创建的节点是第一个子节点,则获得锁
            if (znode.endsWith(firstNode)){
                return true;
            }
            //不是第一个子节点,则监听前一个节点
            String lastNode = firstNode;
            for (String node:childrenNodes){
                if (znode.endsWith(node)){
                    zooKeeper.exists("/"+businessCode+"/"+lastNode,true);
                    break;
                }else {
                    lastNode = node;
                }
            }
            synchronized (this){
                wait();
            }

            return true;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
    
    @Override
    public void close() throws Exception {
        zooKeeper.delete(znode,-1);
        zooKeeper.close();
        log.info("我已经释放了锁!");
    }

    @Override
    public void process(WatchedEvent event) {
        if (event.getType() == Event.EventType.NodeDeleted){
            synchronized (this){
                notify();
            }
        }
    }
}

代码实现:

 @RequestMapping("zkLock")
    public String zookeeperLock(){
        log.info("我进入了方法!");
        try (ZkLock zkLock = new ZkLock()) {
            if (zkLock.getLock("order")){
                log.info("我获得了锁");
                Thread.sleep(10000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("方法执行完成!");
        return "方法执行完成!";
    }
4、Zookeeper的Curator实现分布式锁

pom


        org.apache.zookeeper
        zookeeper
        3.4.14
    
    
        org.apache.curator
        curator-recipes
        4.2.0
    

实例化对象

 @Bean(initMethod="start",destroyMethod = "close")
    public Curatorframework getCuratorframework() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        Curatorframework client = CuratorframeworkFactory.newClient("localhost:2181", retryPolicy);
        return client;
    }

代码实现

  @Autowired
    private Curatorframework client;

    @RequestMapping("curatorLock")
    public String curatorLock(){
        log.info("我进入了方法!");
        InterProcessMutex lock = new InterProcessMutex(client, "/order");
        try{
            if (lock.acquire(30, TimeUnit.SECONDS)){
                log.info("我获得了锁!!");
                Thread.sleep(10000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                log.info("我释放了锁!!");
                lock.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        log.info("方法执行完成!");
        return "方法执行完成!";
    }
5、Spring集成Redisson原生

pom


   org.redisson
   redisson
   3.16.7
 

配置类

@Bean
    public RedissonClient redissonClient(){
        Config config=new Config();
        config.useSingleServer().setAddress("redis://192.168.73.130:6379");
        return Redisson.create(config);
    }

使用

//引用
@Autowired 
private RedissonClient redisson;

//代码中使用
		RLock rLock = redisson.getLock("order");
        try {
            rLock.lock(30, TimeUnit.SECONDS);
            log.info("我获得了锁!!!");
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            log.info("我释放了锁!!");
            rLock.unlock();
        }
6、SpringBoot集成Redisson

pom


        org.redisson
        redisson-spring-boot-starter
        3.13.6
    

添加:redisson.xml文件



    
        
    

启动类中添加

@importResource("classpath:redisson.xml")*

代码中使用

@Autowired
    private RedissonClient redisson;

    @RequestMapping("redissonLock")
    public String redissonLock() {
        RLock rLock = redisson.getLock("order");
        log.info("我进入了方法!!");
        try {
            rLock.lock(30, TimeUnit.SECONDS);
            log.info("我获得了锁!!!");
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            log.info("我释放了锁!!");
            rLock.unlock();
        }
        log.info("方法执行完成!!");
        return "方法执行完成!!";
    }

下面是本人的公众号:(有兴趣可以扫一下,文章会同步过去)

我是小白弟弟,一个在互联网行业的小白,立志成为一名架构师
https://blog.csdn.net/zhouhengzhe?t=1

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5690371.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存