Redis分布式锁实现

一,Jedis分布式锁实现——单点

    1,Jar包引入

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
    </dependency>

    2,单例模式实现Jedis获取

/**
 * Redis单点构建初始化
 * @return Jedis客户端
 */
public static Jedis createJedisSingle() {
	if (null == jedisPool) {
		synchronized (JedisConnectionUtils.class) {
			if (null == jedisPool) {
				JedisPoolConfig config = new JedisPoolConfig();
				config.setMaxTotal(10);
				jedisPool = new JedisPool(config, "192.168.91.129", 6379);
			}
		}
	}
	return jedisPool.getResource();
}

    3,锁获取和释放实现

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import java.util.UUID;

/**
 * 基于Redis单点服务进行分布式锁处理
 * 应用Jedis客户端的watch命令保证原子性
 * @author pj_zhang
 * @create 2018-11-05 21:42
 **/
public class DistributedSingleLockUtils {

    /**
     * 获取锁
     * @param lockName 锁名称
     * @param lockTime 锁过期时间
     * @param outLockTime 获取锁时间
     * @return
     */
    public static String getLock(String lockName, Long lockTime, Long outLockTime) {
        // 获取唯一锁标识
        String lockIdentify = UUID.randomUUID().toString();
        // 拼接锁KEY
        String lockKey = "lock:" + lockName;
        // 获取锁超时时间, 秒数
        Integer lockTimeSecond = Integer.valueOf(String.valueOf(lockTime / 1000));
        Jedis jedis = null;
        try {
            // 获取jedisCluster
            jedis = JedisConnectionUtils.createJedisSingle();
            // 根据加锁时间, 进行加锁
            Long endTime = System.currentTimeMillis() + outLockTime;
            while (System.currentTimeMillis() < endTime) {
                // 设置值成功, 定时时间跑完后, 会自动删除该KEY
                // setnx 不存在返回1, 存在则返回0
                if (jedis.setnx(lockKey, lockIdentify) == 1) {
                    // 设置定时时间
                    jedis.expire(lockKey, lockTimeSecond);
                    // 获取锁成功, 返回锁标识
                    return lockIdentify;
                }
                // 获取锁未成功, 线程沉睡后继续获取
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return null;
    }

    /**
     * 释放锁
     * @param lockName 锁名称
     * @param lockIdentify 锁唯一标识
     * @return
     */
    public static boolean releaseLock(String lockName, String lockIdentify) {
        String lockKey = "lock:" + lockName;
        Jedis jedis = null;
        boolean isRelease =false;
        try {
            jedis = JedisConnectionUtils.createJedisSingle();
            while (true) {
                // 使用watch命令, 保证原子性
                jedis.watch(lockName);
                if (null != lockIdentify && lockIdentify.equals(jedis.get(lockKey))) {
                    Transaction transaction = jedis.multi();
                    transaction.del(lockName);
                    if (transaction.exec().isEmpty()) {
                        continue;
                    }
                    isRelease = true;
                }
                jedis.unwatch();
                break;
            }
        } finally {
            jedis.close();
        }
        return isRelease;
    }

}

    4,多线程测试

public static void testJedisSingle() {
	for (int i = 0; i < 10; i++) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					String identify = DistributedSingleLockUtils.getLock("zpj", 2000L, 2000L);
					if (null != identify) {
						System.out.println(Thread.currentThread().getName() + "获取锁成功 : " + identify);
					} else {
						continue;
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					boolean result = DistributedSingleLockUtils.releaseLock("zpj", identify);
					if (result) {
						System.out.println(Thread.currentThread().getName() + "释放锁成功 : " + identify);
						break;
					}
				}
			}
		}, "Thread_" + i).start();
	}
}

二,Jedis分布式锁实现——集群

    1,单例获取实现JedisCluster获取

/**
 * redis集群构建初始化
 * @return JedisCluster客户端
 */
public static JedisCluster createJedisCluster() {
	if (null == jedisPool) {
		synchronized (JedisConnectionUtils.class) {
			if (null == jedisPool) {
				JedisPoolConfig config = new JedisPoolConfig();
				config.setMaxTotal(10);
				Set<HostAndPort> lstHostAndPort = new HashSet<>(10);
				lstHostAndPort.add(new HostAndPort("192.168.91.128", 6379));
				lstHostAndPort.add(new HostAndPort("192.168.91.128", 6380));
				lstHostAndPort.add(new HostAndPort("192.168.91.129", 6379));
				lstHostAndPort.add(new HostAndPort("192.168.91.129", 6380));
				lstHostAndPort.add(new HostAndPort("192.168.91.130", 6379));
				lstHostAndPort.add(new HostAndPort("192.168.91.130", 6380));
				jedisCluster = new JedisCluster(lstHostAndPort, config);
			}
		}
	}
	return jedisCluster;
}

    2,锁获取和释放实现(锁获取和单点基本一致,释放锁时候原子性保证不一致,JedisCluster不支持watch命令)

import redis.clients.jedis.JedisCluster;

import java.io.IOException;
import java.util.UUID;

/**
 * 基于Redis集群进行分布式锁处理
 * 应用LUA脚本保证原子性
 **/
public class DistributedClusterLockUtils {

    /**
     * 获取锁
     * @param lockName 锁名称
     * @param lockTime 锁过期时间
     * @param outLockTime 获取锁时间
     * @return
     */
    public static String getLock(String lockName, Long lockTime, Long outLockTime) {
        // 获取唯一锁标识
        String lockIdentify = UUID.randomUUID().toString();
        // 拼接锁KEY
        String lockKey = "lock:" + lockName;
        // 获取锁超时时间, 秒数
        Integer lockTimeSecond = Integer.valueOf(String.valueOf(lockTime / 1000));
        JedisCluster jedisCluster = null;
        try {
            // 获取jedisCluster
            jedisCluster = JedisConnectionUtils.createJedisCluster();
            // 根据加锁时间, 进行加锁
            Long endTime = System.currentTimeMillis() + outLockTime;
            while (System.currentTimeMillis() < endTime) {
                // 设置值成功, 定时时间跑完后, 会自动删除该KEY
                // setnx 不存在返回1, 存在返回0
                if (jedisCluster.setnx(lockKey, lockIdentify) == 1) {
                    // 设置定时时间
                    jedisCluster.expire(lockKey, lockTimeSecond);
                    // 获取锁成功, 返回锁标识
                    return lockIdentify;
                }
                // 获取锁未成功, 线程沉睡后继续获取
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                jedisCluster.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 释放锁
     * @param lockName 锁名称
     * @param lockIdentify 锁唯一标识
     * @return
     */
    public static boolean releaseLock(String lockName, String lockIdentify) {
        String lockKey = "lock:" + lockName;
        JedisCluster jedisCluster = null;
        boolean isRelease =false;
        try {
            while (true) {
                // 获取连接
                jedisCluster = JedisConnectionUtils.createJedisCluster();
                // 集群状态下, 使用LUA脚本保证原子性
                String luaScript = " if redis.call('get', KEYS[1]) == ARGV[1] " +
                        " then return redis.call('del', KEYS[1]) " +
                        " else return 0 end ";
                long eval = (long) jedisCluster.eval(luaScript, 1, lockKey, lockIdentify);
                if (0L < eval) {
                    isRelease = true;
                    break;
                }
                continue;
            }
        } finally {
            try {
                jedisCluster.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return isRelease;
    }

}

    3,多线程测试

三,Redisson分布式锁实现

    1,Jar包引入

<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
    <dependency>
      <groupId>org.redisson</groupId>
      <artifactId>redisson</artifactId>
      <version>3.8.2</version>
    </dependency>

    2,多线程测试(已经进行完整的获取锁和释放锁封装)

         * 单点和集群模式只在获取Redisson客户端时存在不同

package com.gupao.redis.lock.jedis;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.TimeUnit;

/**
 * 基于Redisson客户端实现分布式锁
 **/
public class DistributedRedissonLockUtils {

    public static void main(String[] args) {
        Config config = new Config();
        // 集群模式
        config.useClusterServers().addNodeAddress("redis://192.168.91.128:6379",
                "redis://192.168.91.128:6380",
                "redis://192.168.91.129:6379",
                "redis://192.168.91.129:6380",
                "redis://192.168.91.130:6379",
                "redis://192.168.91.130:6380");
        // 单点模式
        // config.useSingleServer().setAddress("redis://192.168.91.130:6379");
        final RedissonClient redissonClient = Redisson.create(config);
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        while (true) {
                            RLock rLock = redissonClient.getLock("myTest");
                            boolean lockResult = rLock.tryLock(20l, TimeUnit.SECONDS);
                            if (lockResult) {
                                System.out.println(Thread.currentThread().getName() + "获得锁成功");
                                Thread.sleep(100);
                                rLock.unlock();
                                System.out.println(Thread.currentThread().getName() + "释放锁成功");
                                break;
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "Thread_" + i).start();
        }
    }

}

四,布隆过滤器(基于google.guava)

    1,Jar包引入

<!-- guava提供的布隆过滤器 -->
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>27.0-jre</version>
    </dependency>
  </dependencies>

    2,功能实现

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import redis.clients.jedis.*;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class BloomFilterTest {

    public static void main(String[] args) {
        BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), 10000000, 0.00001);
        bloomFilter.put("test");
        System.out.println(bloomFilter.mightContain("test"));
    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值