Redis学习 利用javaweb与jedis模拟秒杀

我们都知道,秒杀案例是电商项目最不可少的功能之一,在秒杀案例里会出现一系列的问题,比如超卖问题(不加事务的秒杀),库存遗留(施加乐观锁之后)问题。

首先讲解下悲观锁和乐观锁:悲观锁是每一次只能有一个命令去操作这个数据或者是资源,其他想要操作这个资源的命令无法操作,因为资源被上了悲观锁,只有第一个事务提交结束后悲观锁被打开,下一个事务才能继续操作这个资源。注意悲观锁甚至不允许读操作!!!而与悲观锁不同的乐观锁则是每一个事务都能够操作这个资源,但是!!!同一时间能改变资源的只有一个事务,所以乐观锁机制会给资源上一个操作标志,每一个时刻事务操作的资源标志如果等于当前资源的操作标志,就可以对它进行操作,如果不同就只能重新获取当前操作标志的资源进行操作。这就保证了可以对当前数据资源进行读取,但是数据如果在多用户的情况下实时访问的场景的话,系统实时更新数据资源的能力直接决定其他用户读取资源的正确性。

另外watch命令是监视key,监视的key相当于在这部分数据上加上了乐观锁,行锁。

测试步骤:

1、设计JedisPoolUntil类与getUid类

2、设置service层(在seckillServiceImpl类里书写秒杀具体逻辑代码)

3、设计servlet层实现web响应

1、设计JedisPoolUntil类与getUid类

JedisPoolUntil类,采取池子可以有效的处理一定请求量带来的等待超时问题的出现!

public class JedisPoolUntil {
    private static JedisPool jedisPool = null;

    public static JedisPool getJedisPool() {
        if (jedisPool == null) {
            synchronized (JedisPoolUntil.class) {
                if (jedisPool == null) {

                    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
                    jedisPoolConfig.setMaxTotal(200);
                    jedisPoolConfig.setMaxIdle(32);
                    jedisPoolConfig.setBlockWhenExhausted(true);
                    jedisPoolConfig.setTestOnBorrow(false);

                    jedisPool = new JedisPool(jedisPoolConfig,"192.168.20.150",6379);
                }
            }
        }
        return jedisPool;
    }

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

getUid类,随机生成user的id模拟秒杀用户多的情况

/*得到随机的用户id*/
public class getUid {
    public static String Uid(){
        String uid = "user:";
        Random random = new Random();
        for (int i=0; i<=3;i++){
            uid += random.nextInt(1,9);
        }
        return uid;
    }
}

2、设置service层

SecKillServiceImpl类实现具体的业务逻辑操作

public class seckillServiceImpl implements seckillService{
    /*池化解决超时问题*/
    JedisPool jedisPool = JedisPoolUntil.getJedisPool();
    @Override
    public Boolean seckill() {
        Jedis resource = jedisPool.getResource();
        resource.auth("hlc");

//        1 判断库存容量是否为 0
        if (resource.get("kcKey") == null ){
            System.out.println("秒杀活动结束!");
            return false;
        }
//        2 给库存乐观锁,防止并发情况导致数据异常
        resource.watch("kcKey");
//        3 启动事务
        Transaction multi = resource.multi();
        try {
            multi.decr("kcKey");
            multi.sadd("user",getUid.Uid());
            multi.exec();
            System.out.println("秒杀成功!");
            return true;
        }catch (Exception e){
            e.printStackTrace();
            multi.discard();
            return false;
        }
    }
}

3、设计servlet层实现web响应

在web.xml文件别忘记注册这个servlet类,当然如果采用springboot来测试,对于web层开发与redis操作来说会更简单。不过javaweb确实也挺好的,除了代码量稍微大一点,业务逻辑都需要自行配置环境之外也没啥缺点(好像确实javaweb又重又不好用!!!)

public class seckillServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        seckillService seckillService = new seckillServiceImpl();
        Boolean seckill = seckillService.seckill();
        if (seckill){
            request.setAttribute("message","你已秒杀成功!");
            request.getRequestDispatcher("success.jsp").forward(request,response);
        }else {
            request.setAttribute("message","秒杀失败!");
            request.getRequestDispatcher("error.jsp").forward(request,response);
        }
    }
}

测试结果:

 

 

 当然我这个是单机操作,没法模拟并发,我们可以通过postman测试,也可以在Linux虚拟机上利用ab命令测试,如果ab命令用不了,就要下载一下这个工具了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ForestSpringH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值