Redis实现分布式锁

  1. 普通方式

    1. 直接看代码

      1. package com.whereta.jedis;
        
        import org.springframework.stereotype.Component;
        import redis.clients.jedis.Jedis;
        import redis.clients.jedis.JedisPool;
        
        import javax.annotation.Resource;
        import java.util.Calendar;
        import java.util.Date;
        import java.util.concurrent.TimeUnit;
        
        /**
         * Created by vincent on 15-10-14.
         */
        @Component("jedisLock")
        public class JedisLock {
        
            public class CacheName {
                public static final String ADD_BEAN_AFTER_CHECK_LOCK_KEY = "ADDBeanAfterCheckLock";
            }
        
            @Resource
            private JedisPool jedisPool;
        
            public void addBeanAfterCheck(int userId) {
                Jedis jedis = jedisPool.getResource();
        
                Calendar calendar = Calendar.getInstance();
                calendar.set(Calendar.MILLISECOND, 0);
                Date calendarTime = calendar.getTime();
                long time = calendarTime.getTime();
                //以用户id为key,不同用户调用同一个方法不会加锁
                String key = CacheName.ADD_BEAN_AFTER_CHECK_LOCK_KEY + ":" + userId;
                try {
                    if (jedis != null) {
                        Long lock = jedis.setnx(key, time + "");
                        while (lock == 0) {
                            TimeUnit.MILLISECONDS.sleep(50);
                            lock = jedis.setnx(key, time + "");
                        }
                        //设置超时时间
                        jedis.expire(key, 3);
                    }
        
                    //自己的业务逻辑处理
        
        
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    if (jedis != null) {
                        jedis.del(key);
                        jedis.close();
                    }
                }
            }
        
        
        }
    2. 示例中以用户id为key加锁:不同用户访问该方法的时候不会排斥等待

    3. 锁机制的实现利用了Redis的setnx方法:如果数据库里key存在了则不存储数据,返回0

    4. redis的该方法是线程安全的,可以放心使用

  2. aop方式

    1. 示例代码

      1. package com.whereta.jedis;
        
        import org.aspectj.lang.ProceedingJoinPoint;
        import org.aspectj.lang.annotation.Around;
        import org.aspectj.lang.annotation.Aspect;
        import org.springframework.stereotype.Component;
        import redis.clients.jedis.Jedis;
        import redis.clients.jedis.JedisPool;
        
        import javax.annotation.Resource;
        import java.util.Calendar;
        import java.util.Date;
        import java.util.concurrent.TimeUnit;
        
        /**
         * Created by vincent on 15-10-14.
         */
        @Aspect
        @Component
        public class JedisLockAop {
        
        
            @Resource
            private JedisPool jedisPool;
        
        
            @Around("execution(public * com.heli.core.pay.soaservice.impl.*.*(..))")
            public Object serviceAOP(ProceedingJoinPoint point) {
                Object proceed = null;
                Jedis jedis = jedisPool.getResource();
        
                Calendar calendar = Calendar.getInstance();
                calendar.set(Calendar.MILLISECOND, 0);
                Date calendarTime = calendar.getTime();
                long time = calendarTime.getTime();
                //请求参数数组
                Object[] args = point.getArgs();
        
                //key可以自定义
                String key = JedisLock.CacheName.ADD_BEAN_AFTER_CHECK_LOCK_KEY + ":" + args[0];
                try {
                    if (jedis != null) {
                        Long lock = jedis.setnx(key, time + "");
                        while (lock == 0) {
                            TimeUnit.MILLISECONDS.sleep(50);
                            lock = jedis.setnx(key, time + "");
                        }
                        //设置超时时间
                        jedis.expire(key, 3);
                    }
                    //用户业务处理
                    proceed = point.proceed();
                    return proceed;
                } catch (Throwable throwable) {
                    throw new RuntimeException(throwable);
                } finally {
                    if (jedis != null) {
                        jedis.del(key);
                        jedis.close();
                    }
                }
        
            }
        
        }
    2. 使用Spring Aop的环绕方法

    3. 具体key值可以自定义涉及,譬如:ip,时间等


你可能感兴趣的:(Redis实现分布式锁)