Redis从入门到精通-Redis-事物和锁机制-超时和超卖问题解决

一、超卖问题

二、利用乐观锁淘汰用户,解决超卖问题。

三、代码

复制代码
package com.atguigu;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;

import java.io.IOException;
import java.util.List;

/**
 *
 */
public class SecKill_redis_advance {

    public static void main(String[] args) {
        Jedis jedis =new Jedis("192.168.117.134",6379);
        System.out.println(jedis.ping());
        jedis.close();
    }

    //秒杀过程
    public static boolean doSecKill(String uid,String prodid) throws IOException {
        //1 uid和prodid非空判断
        if(uid == null && prodid == null){
               return false;
        }

        //2 连接redis
        //通过连接池得到jedis对象
        JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
        Jedis jedis = jedisPoolInstance.getResource();

        //3 拼接key
        // 3.1 库存key
        String kcKey="sk:"+prodid+":qt";

        // 3.2 秒杀成功用户key
        String userKey="sk:"+prodid+":user";

        //监视库存 加乐观锁

        jedis.watch(kcKey);

        //4 获取库存,如果库存null,秒杀还没有开始
        String kcVal = jedis.get(kcKey);

        if(kcVal == null){
            System.out.println("秒杀还没有开始,请等待。");
            jedis.close();
            return false;
        }


        // 5 判断用户是否重复秒杀操作
        Boolean sismember = jedis.sismember(userKey, uid);
        if(sismember){
            System.out.println("已经秒杀过了,不能重复秒杀");
            jedis.close();
            return false;
        }
        //6 判断如果商品数量,库存数量小于1,秒杀结束
        int intKcVal = Integer.parseInt(kcVal);
        if(intKcVal<=0){
            System.out.println("秒杀结束");
            jedis.close();
            return false;
        }

        //7 秒杀过程
        //使用事务
        Transaction multi = jedis.multi();

        //组队操作
        multi.decr(kcKey);
        multi.sadd(userKey,uid);
        List<Object> result = multi.exec();
        if(result == null && result.size() ==0){
            System.out.println("事物中秒杀失败");
            jedis.close();
            return false;
        }
        
        System.out.println("秒杀成功");
        return true;
    }
}
复制代码

四、测试

1、设置库存。

2、ab工具模拟测试

ab -n 1000 -c 100 -k -p /ab/postfile -T application/x-www-form-urlencoded http://192.168.10.1:8080/Seckill/doseckill

 

五、连接超时,使用连接池

复制代码
package com.atguigu;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {
    private static volatile JedisPool jedisPool = null;

    private JedisPoolUtil() {
    }

    public static JedisPool getJedisPoolInstance() {
        if (null == jedisPool) {
            synchronized (JedisPoolUtil.class) {
                if (null == jedisPool) {
                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    poolConfig.setMaxTotal(2000);
                    poolConfig.setMaxIdle(32);
                    poolConfig.setMaxWaitMillis(100*1000);
                    poolConfig.setBlockWhenExhausted(true);
                    poolConfig.setTestOnBorrow(true);  // ping  PONG
                 
                    jedisPool = new JedisPool(poolConfig, "192.168.117.134", 6379, 60000 );
                }
            }
        }
        return jedisPool;
    }

    public static void release(JedisPool jedisPool, Jedis jedis) {
        if (null != jedis) {
            jedisPool.returnResource(jedis);
        }
    }

}
复制代码

 

本文作者:KwFruit

本文链接:https://www.cnblogs.com/mangoubiubiu/p/15810279.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   KwFruit  阅读(68)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起