一,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"));
}
}