搜索
您的当前位置:首页正文

Redis3构建分布式锁-Redisson

来源:二三娱乐

1.不加锁达不到下要的结果,num最后总有丢掉

package com.mxy.epe.redislock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class TestRedisLocker implements Runnable {

    private static final int count = 500;
    private static CountDownLatch latch = new CountDownLatch(count);
    private static long num = 0;
    private static AtomicInteger atomici = new AtomicInteger(0);

    public static void main(String[] args) {
        TestRedisLocker j = new TestRedisLocker();
        long stime = System.currentTimeMillis();
        for (int i = 0; i < count ; i++) {
            new Thread(j).start();
        }
        
        try {
            latch.await();
            System.out.println(num + "::" + atomici.get());
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        System.out.println((System.currentTimeMillis() - stime));
    }

    public void run() {
        for (int i = 0; i < 3; i++) {
            num += 1;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        atomici.getAndIncrement();
        latch.countDown();
    }

}

2.代码锁

ReentrantLock或synchronized解决单进程的资源安全问题,效率会比分布式锁高,缺点除单进程外还不容易做到指定某个条件。


package com.mxy.epe.redislock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class TestRedisLocker implements Runnable {

    private static final int count = 500;
    private static CountDownLatch latch = new CountDownLatch(count);
    private static long num = 0;
    private static AtomicInteger atomici = new AtomicInteger(0);

    public static void main(String[] args) {
        TestRedisLocker j = new TestRedisLocker();
        long stime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            new Thread(j).start();
        }
        
        try {
            latch.await();
            System.out.println(num + "::" + atomici.get());
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        System.out.println((System.currentTimeMillis() - stime));
        System.out.println(rl.redisson.isShutdown());
    }

    public void run() {
        synchronized(TestRedisLocker.class) {
            for (int i = 0; i < 3; i++) {
                num += 1;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        atomici.getAndIncrement();
        latch.countDown();
    }

}


3.Redisson

RedLock能做到我需要的功能,给每个用户一把锁保证其资源安全。
  A渠道商的积分余额1000,在同一时间提交20个请求每个消费100积分,在积分为0时必须不能被超支,但是这里只是针对A渠道商的积分,B渠道商可以正常消费他的积分,因此AB需各自的同步锁,RedLock可以很好做到。
  分布式锁毕竟还是涉及网络连接,无法做到和代码锁那样的效率。

maven依赖

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

Redisson实现


package com.mxy.epe.redislock;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.util.concurrent.TimeUnit;

/**
 * 
 * Type Name : RedLock 
 * Description : redlock分布式锁 
 * Author : ThingLin Create
 * Date : 2017年10月26日 Version :
 *
 * History: (Version) Author Date Annotation
 */
public class RedLock {

    private final static String LOCKER_PREFIX = "lock:";
    
    /**
     * 加锁等待时长ms
     */
    private final long waitTime = 500;
    
    /**
     * 默认锁持有时长s
     */
    private final int defaultLeaseTime = 1; 

    private RedissonClient redisson;

    public RedLock(String ip,int port,String password) {
        Config config = new Config();
        config.useSingleServer().setAddress(ip+":"+port).setPassword(password);
        redisson = Redisson.create(config);
    }

    /**
     * 
     * Description :
     * Author :ThingLin
     * Create Date : 2017年10月27日
     * History: (Version) Author Date Annotation 
     * @param resourceName 资源名称
     * @return
     * @throws InterruptedException
     */
    public boolean lock(String resourceName) throws InterruptedException {
        return lock(resourceName, defaultLeaseTime);
    }

    public boolean lock(String resourceName, long lockTime) throws InterruptedException {
        RLock lock = redisson.getLock(LOCKER_PREFIX + resourceName);
        return lock.tryLock(waitTime, lockTime, TimeUnit.SECONDS);
    }

    public void unlock(String resourceName) {
        RLock lock = redisson.getLock(LOCKER_PREFIX + resourceName);
        lock.unlock();
    }
    
}


测试使用


package com.mxy.epe.redislock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class TestRedisLocker implements Runnable {

    private static final int count = 500;
    private static CountDownLatch latch = new CountDownLatch(count);
    private static long num = 0;
    private static long sum = 0;
    private static AtomicInteger atomici = new AtomicInteger(0);
    private static RedLock rl = new RedLock("127.0.0.1", 6379, "123456qq");

    public static void main(String[] args) {
        TestRedisLocker j = new TestRedisLocker();
        long stime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            Thread thread = new Thread(j);
            thread.setName(i + "");
            thread.start();
        }
        try {
            latch.await();
            System.out.println(sum+"::"+num + "::" + atomici.get());
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println((System.currentTimeMillis() - stime));
    }

    public void run() {
        // 用线程名称模拟下不同用户,在服务生产环境用用户id区别
        int threadid = Integer.parseInt(Thread.currentThread().getName());
        if (threadid % 2 == 0) {
            try {
                rl.lock("dddd"); //用户A 的资源锁(resourceName)名称dddd
                for (int i = 0; i < 3; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num += 1;
                }
                rl.unlock("dddd");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            try {
                rl.lock("bbbb");//用户A 的资源锁(resourceName)名称bbbb
                for (int i = 0; i < 3; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    sum += 1;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            rl.unlock("bbbb");
        }

        atomici.getAndIncrement();
        latch.countDown();
    }

}


Top