使用redis分布式锁 更改数据库 和更新redis缓存 + 锁续命 demo

测试样例:

package com...redis.redisSuo.demo;

import com...redis.RedisPoolUtils;
import com...redis.redisSuo.JedisSuoUtils;
import redis.clients.jedis.Jedis;
import...RecordSet;
import...SQL;

import java.util.UUID;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class demo {

    private static RedisPoolUtils redisPoolUtils = new RedisPoolUtils();
    private final static String  key = "keys";
    private static final int  Thread_num   = 20;
    private static final CyclicBarrier cb = new CyclicBarrier(Thread_num);

    public static void sendThreads() throws InterruptedException {
        Thread [] threads = new Thread[Thread_num];
        for(int i=0;i<Thread_num;i++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        cb.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    String res = getKey(key);
                    System.out.println(res);

                }
            });
            threads [i] = thread;
            thread.start();
        }
        for(Thread thread : threads){
            thread.join();
        }
        System.out.println("执行结束======");

    }

    public static void main(String[] args) throws InterruptedException {
        sendThreads();

    }


    public static String getKey(String key) {



        String redisKey = key;
        String lockKey = "locks:"+key;
        String lockRequestId = UUID.randomUUID().toString();
        System.out.println(Thread.currentThread().getName() + "lockRequestId--->"+lockRequestId);
        Jedis jedis = redisPoolUtils.getResource();

        try {

            while (true) {

                //获取分布式锁,时间设为3秒
                boolean getLock = JedisSuoUtils.tryGetDistributedLock(jedis, lockKey, lockRequestId, 3000);
                System.out.println(Thread.currentThread().getName() + "获取锁的结果:--->" + getLock);
                if (getLock) {

                    int count = 1;
                    String st_fj_id = key;
                    String updateSql = "update dang_fj set count = count-? where st_fj_id = ? and count>=1";
                    Object[] updateObject = new Object[] {count,st_fj_id};
                    RecordSet updateRs  = SQL.execute(updateSql,updateObject);
                    int number = updateRs.TOTAL_RECORD_COUNT;
                    //影响行数
                    System.out.println("数据库影响行数:"+number);

                    if(number==1){
                        String counts = "";
                        String selectSql = "select * from dang_fj where st_fj_id = ?";
                        Object[] selectObject = new Object[]{key};
                        RecordSet selectRs = SQL.execute(selectSql, selectObject);
                        while (selectRs.next()) {
                            counts = selectRs.getString("COUNT");
                        }
                        System.out.println("数据库剩余---->"+counts);
                        String redisRs = jedis.setex(redisKey,60*60,counts);
                        System.out.println("更改redis结果--->:"+redisRs);
                        return Thread.currentThread().getName() + "去数据库拿结果~~~~:" + counts;
                    }else {
                        return Thread.currentThread().getName() + "更改数据库失败~~~~";
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //不论结果如何,一定要释放锁
            boolean releaseLock = JedisSuoUtils.releaseDistributedLock(jedis, lockKey, lockRequestId);
            jedis.close();
            System.out.println(Thread.currentThread().getName()+"释放锁的结果:--->"+releaseLock);
        }
        return Thread.currentThread().getName()+"最后结果lockRequestId--->"+lockRequestId;
    }

}

加锁解锁 工具类:

package com...redis.redisSuo;

import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * @author 
 * @date 2019/8/10
 */
public class JedisSuoUtils {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 尝试获取分布式锁
     *
     * @param jedis      Redis客户端
     * @param lockKey    锁
     * @param requestId  请求标识
     * @param expireTime 超期时间, 单位毫秒
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        return LOCK_SUCCESS.equals(result);
    }

    /**
     * 释放分布式锁
     *
     * @param jedis     Redis客户端
     * @param lockKey   锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        return result.equals(RELEASE_SUCCESS);

    }
}

锁续命小demo:

    // 加锁后开始调用方法 :开个子线程,原来时间30,每隔30/3,重置为30
    LockService.renewLock(lock.intern(),driverId,30);



接口:
package com....service;

public interface LockService {

    /**
     * 续约
     * @param key
     * @param value
     * @param time
     */
    public void Lock(String key , String value , int time);





实现:
package com.....impl;

import com.....LockService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;


@Service
public class LockServiceImpl implements LockService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    @Async
    public void Lock(String key, String value, int time) {
        String v = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(v) && v.equals(value)){
            System.out.println("进入续命操作... "+key+"  "+value);
            int sleepTime = time / 3;
            try {
                Thread.sleep(sleepTime * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            redisTemplate.expire(key,time,TimeUnit.SECONDS);
            Lock(key,value,time);
        }
    }
}




    
原文地址:https://www.cnblogs.com/lifan12589/p/13502036.html