redis 分布式获取锁 以及事务的运用?小白进阶

redis

使用Java操控Redis事务命令

// 开启事务Transaction transaction = jedis.multi();// 提交事务transaction.exec();// 放弃事务transaction.discard();// 监控键jedis.watch("balance", "debt");// 放弃所有被监控的键jedis.unwatch();

使用 WATCH 命令可以监控键,如果被监控的键,在 EXEC 之前被修改,那么事务会放弃执行(注意:事务中的命令在 exec命令后才开始执行)

EXEC 执行以后,无论事务是否执行成功,都会放弃对所有键的监控。



public class RedisLock {    private final JedisPool jedisPool;    private static final Logger logger = Logger.getLogger(RedisLock.class);     public RedisLock(JedisPool jedisPool) {        this.jedisPool = jedisPool;    }     /**     *     * @param locaName  锁的key     * @param acquireTimeout  尝试获取锁超时时间     * @param timeout   key的超时时间     * @return 锁标识     */    public String lockWithTimeout(String locaName,                                  long acquireTimeout, long timeout) {        Jedis conn = null;        String retIdentifier = null;        try {            // 随机生成一个value            String identifier = UUID.randomUUID().toString();    //如果identifier存在则成功获取到锁,否则表明该锁已经被其他线程占用            // 锁名,即key值            String lockKey = "lock:" + locaName;            // 超时时间,上锁后超过此时间则自动释放锁            int lockExpire = (int)(timeout / 1000);            // 获取连接            conn = jedisPool.getResource();            // 获取锁的超时时间,超过这个时间则放弃获取锁            long end = System.currentTimeMillis() + acquireTimeout;            while (System.currentTimeMillis() < end) {                       if (conn.setnx(lockKey, identifier) == 1) {                    conn.expire(lockKey, lockExpire);                    // 返回value值,用于释放锁时间确认                    retIdentifier = identifier;                    return retIdentifier;                }                // 返回-1代表key没有设置超时时间,为key设置一个超时时间                if (conn.ttl(lockKey) == -1) {                    conn.expire(lockKey, lockExpire);                }                 try {                    Thread.sleep(10);                } catch (InterruptedException e) {                    Thread.currentThread().interrupt();                    logger.error("RedisLock中断异常",e);                }                        }        } catch (JedisException e) {            logger.error("RedisLock获取锁异常",e);        } finally {            if (conn != null) {                conn.close();            }        }        return retIdentifier;    }     /**     * 释放锁     * @param lockName   锁的key     * @param identifier     释放锁的标识     * @return     */    public boolean releaseLock(String lockName, String identifier) {        Jedis conn = null;        String lockKey = "lock:" + lockName;        boolean retFlag = false;        try {            conn = jedisPool.getResource();            while (true) {                    //watch 命令会标记一个或多个键                      // 监视lock,准备开始redis事务                    //如果multi事务中被标记的键,在提交事务之前被修改了,那么事务就会失败。                    conn.watch(lockKey);                    // 通过前面返回的value值判断是不是该锁,若是该锁,则删除,释放锁                    if (identifier.equals(conn.get(lockKey))) {                              // multi 标记一个事务块的开始。                              Transaction transaction = conn.multi();                              transaction.del(lockKey);                              // exec 执行所有事务块内的命令。                              List results = transaction.exec();                              if (results == null) {                                  continue;                              }                              retFlag = true;                    }                    //放弃所有被监控的键                    conn.unwatch();                    break;            }        } catch (JedisException e) {            logger.error("RedisLock释放锁异常",e);        } finally {            if (conn != null) {                conn.close();            }        }        return retFlag;    }}            
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章