redis实战教程(一)-分布式锁

来源:互联网 发布:手机淘宝怎么查看消费 编辑:程序博客网 时间:2024/05/21 09:52

主要用到setnx函数,原理如下:

命令格式

SETNX key value

将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。

返回值

返回整数,具体为
- 1,当 key 的值被设置
- 0,当 key 的值没被设置

例子

redis> SETNX mykey “hello”
(integer) 1
redis> SETNX mykey “hello”
(integer) 0
redis> GET mykey
“hello”
redis>

使用SETNX实现分布式锁

多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。



package net.csdn.redis;import java.util.concurrent.TimeUnit;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;public class RedisDemo {private static JedisPool pool;private static String redisServerIp = "192.168.0.43";private static String redisPassord = "MMHlive2016";private static int connectTimeout = 20 * 1000;// 2秒/** * 建立连接池 真实环境,一般把配置参数缺抽取出来。 *  */private static void createJedisPool() {// 建立连接池配置参数JedisPoolConfig config = new JedisPoolConfig();// 设置最大连接数config.setMaxActive(10000);// 设置最大阻塞时间,记住是毫秒数millisecondsconfig.setMaxWait(connectTimeout);// 设置空间连接config.setMaxIdle(500);// 创建连接池pool = new JedisPool(config, redisServerIp, 6379, connectTimeout, redisPassord);}/** * 在多线程环境同步初始化 */private static synchronized void poolInit() {if (pool == null)createJedisPool();}/** * 获取一个jedis 对象 *  * @return */private static Jedis getJedis() {if (pool == null)poolInit();return pool.getResource();}/** * 归还一个连接 *  * @param jedis */private static void returnRes(Jedis jedis) {pool.returnResource(jedis);}public static long setnx(String key, String val, int timeout) {Jedis jedis = getJedis();long rst = jedis.setnx(key, val);if (rst == 1) {jedis.expire(key, timeout);}returnRes(jedis);return rst;}public static long delete(String sessionId) {Jedis jedis = getJedis();Long rst = jedis.del(sessionId);returnRes(jedis);return rst;}public static boolean tryLock(String key, int timeout) {long nano = System.nanoTime();do { Long i = setnx(key, key, timeout);//System.out.println(i);if (i == 1) {System.out.println(Thread.currentThread().getName()+":获得锁");return true;}if (timeout == 0) {break;}try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}if((System.nanoTime() - nano) > TimeUnit.SECONDS.toNanos(timeout)){break;}} while (true);throw new RuntimeException("获取[" + key + "]锁超时");}public static void main(String[] args) throws Exception {String key="wweerrt";delete(key);int timeout=1000000;new Thread(()->{System.out.println(Thread.currentThread().getName()+":开始加锁");tryLock(key, timeout);}) .start();new Thread(()->{System.out.println(Thread.currentThread().getName()+":开始加锁");tryLock(key, timeout);}) .start();Thread.sleep(100000L);}}

控制台输出:
Thread-1:开始加锁
Thread-2:开始加锁
Thread-1:获得锁



原创粉丝点击