• 使用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);
            }
        }
    }
    
    
    
    
        
  • 相关阅读:
    汇编Ring 3下实现 HOOK API
    软件调试之INT 3讲解
    Delphi逆向
    XoftSpy 4.13的注册算法分析
    反调试技术揭秘
    jmp && call && ret 特权级转移 & 进程调度
    PHP Warning: Module 'modulename' already loaded in Unknown on line 0
    PhpStorm和PHPstudy配置调试参数(Xdebug),问题描述Error. Interpreter is not specified or invalid. Press “Fix” to edit your project configuration.
    php 安装xdebug进行调试(phpstorm)
    Windows下PHP多线程扩展pthreads的安装
  • 原文地址:https://www.cnblogs.com/lifan12589/p/13502036.html
Copyright © 2020-2023  润新知