java redis 实现抢购秒杀

2018.10.24 今天研究了下抢购秒杀的功能实现

网上查了一大堆 用redis的最多。

主要是通过redis的 watch multi 事务来控制秒杀数量 不超卖。

这里说下自己的感受:

不超卖的话 那就要一个个的来减库存 这样的话 效率上会有点问题 这里上下代码 基本上是再网上抄的 。

我用的是 springboot jedis

我就直接上代码了

Controller层

package com.bicon.basedemo.controller;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.Resource;

import org.omg.CORBA.PRIVATE_MEMBER;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
@RequestMapping("/test")
public class test {

//    @Resource
//    RedisOperation redisOps;

    @Resource
    private JedisPool jedisPool;

    @RequestMapping("/redis")
    public void redisTest() {
        Jedis jedis = jedisPool.getResource();
        final String watchkeys = "watchkeys";
        ExecutorService executor = Executors.newFixedThreadPool(20);  //20个线程池并发数

        jedis.set(watchkeys, "10");//设置起始的抢购数
       // jedis.del("setsucc", "setfail");
        jedis.close();

        for (int i = 0; i < 101; i++) {//设置101个人来发起抢购 模拟101个人抢购
            executor.execute(new MyRunnable(jedisPool));
        }
        executor.shutdown();
    }

     public static String getRandomString(int length) { //length是随机字符串长度
         String base = "abcdefghijklmnopqrstuvwxyz0123456789";
         Random random = new Random();
         StringBuffer sb = new StringBuffer();
         for (int i = 0; i < length; i++) {
             int number = random.nextInt(base.length());
             sb.append(base.charAt(number));
         }
         return sb.toString();
      }
}
MyRunnable 代码
package com.bicon.basedemo.controller;

import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;

public class MyRunnable implements Runnable{

    private JedisPool jedisPool;
    String userinfo;
    String watchkeys = "watchkeys";
    public MyRunnable(JedisPool jedisPoo){
        jedisPool = jedisPoo;
    };

    public void run() {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.watch(watchkeys);// watchkeys

            String val = jedis.get(watchkeys);
            int valint = Integer.valueOf(val);

            if (valint <= 100 && valint>=1) {

                 Transaction tx = jedis.multi();// 开启事务
               // tx.incr("watchkeys");
                tx.incrBy("watchkeys", -1);

                List<Object> list = tx.exec();// 提交事务,如果此时watchkeys被改动了,则返回null

                if (list == null ||list.size()==0) {
                    System.out.println("重新抢购");
                    this.run();
                    return;
                } else {
                    for(Object succ : list){
                         String succuserifo ="succ"+succ.toString() +userinfo ;
                         String succinfo="用户:" + succuserifo + "抢购成功,当前抢购成功人数:"
                                 + (1-(valint-10));
                         System.out.println(succinfo);
                         /* 抢购成功业务逻辑 */
                         jedis.setnx(succuserifo, succinfo);
                    }
                }
            } else {
                    String failuserifo ="kcfail" +  userinfo;
                    String failinfo1="用户:" + failuserifo + "商品被抢购完毕,抢购失败";
                    System.out.println(failinfo1);
                    jedis.setnx(failuserifo, failinfo1);
                    return;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
    }

}

最后是效果

这段代码问题其实还是有的:就是没有按照顺来来抢购

其实我觉得有种方法。就是将请求 存入 kafka中

然后取kafka中前面的数据 一直取到抢购的数量(用户不重复)

这样不就可以了吗,不需要考虑超卖问题啥的。纯属自己的感想。

原文地址:https://www.cnblogs.com/huobi/p/9844755.html

时间: 2024-11-09 02:52:27

java redis 实现抢购秒杀的相关文章

redis实现高并发下的抢购/秒杀功能

1, http://www.cnblogs.com/phpper/p/6716248.html https://www.cnblogs.com/phpper/p/7085663.html https://www.cnblogs.com/TankXiao/p/4045439.html 之前写过一篇文章,高并发的解决思路(点此进入查看),今天再次抽空整理下实际场景中的具体代码逻辑实现吧:抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢? 常规写法:

Java 实现 淘宝秒杀 聚划算 自动提醒 源码

说明 本实例能够监控聚划算的抢购按钮,在聚划算整点聚的时间到达时自动弹开页面(URL自己定义). 可以自定义监控持续分钟数,同时还可以通过多线程加快刷新速度. 源码 package com.itechzero.pricemonitor; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; im

一篇文章教你如何用 Redis 轻松实现秒杀系统的构思

用 Redis 轻松实现秒杀系统的构思 前言: 秒杀系统的架构设计 秒杀系统,是典型的短时大量突发访问类问题.对这类问题,有三种优化性能的思路: **1. 写入内存而不是写入硬盘. 异步处理而不是同步处理. 分布式处理**用上这三招,不论秒杀时负载多大,都能轻松应对.更好的是,Redis能够满足上述三点.因此,用Redis就能轻松实现秒杀系统. 用我这个方案,无论是电商平台特价秒杀,12306火车票秒杀,都不是事:) 下面介绍一下为什么上述三种性能优化思路能够解决秒杀系统的性能问题: 写入内存而

Java实现高并发秒杀API--Service层2

今天完成了整个Java实现高并发秒杀API--Service层的学习: 1.接口的编码以及实现类的逻辑编写 2.利用spring ioc对Service进行管理 3.利用spring声明式事务对事务进行控制: 事务主要配置: <!--配置事务管理器 -->    <bean id="transactionManager"        class="org.springframework.jdbc.datasource.DataSourceTransacti

redis学习 java redis应用

学习redis的总结 :  http://www.runoob.com/redis/redis-tutorial.html     http://www.redis.cn/   一个是菜鸟网站,一个是redis中文网可以进行学习 下面是关于学过redis之后的总结,只是浅显的入门用于对只是的记录 : window :    下载redis  ,,通过cmd 命令行进入 :   执行 redis-server  启动服务端,   然后才能执行redis-cli 启动客户端进行操作   具体的命令可

电商抢购秒杀系统的设计_1_应用场景分析

电商抢购秒杀系统的设计_1_应用场景分析 概述 所谓知已知彼,百战不殆,在开始详细介绍实战中的抢购秒杀系统时,我们了解一些抢购秒杀系统系统面临的尴尬与难点.另外需要说明一点,下面的内容都是在工作中慢慢总结得来,我们团队也是慢慢摸着石头过河,甚至最初的的架构设计并非是抢购秒杀系统. 评估系统处理能力 理论基础:LNMP的并发考虑与资源分配 虽然有基础去评估我们应用系统的处理能力,但是电商购买的业务流程挺复杂,从登录,商品详情,购物车,填写收货地址,选择支付方式,创建订单,完成支付,以及隐含的定时服

用Redis轻松实现秒杀系统

秒杀系统的架构设计 秒杀系统,是典型的短时大量突发访问类问题.对这类问题,有三种优化性能的思路: 写入内存而不是写入硬盘 异步处理而不是同步处理 分布式处理 用上这三招,不论秒杀时负载多大,都能轻松应对.更好的是,Redis能够满足上述三点.因此,用Redis就能轻松实现秒杀系统. 用我这个方案,无论是电商平台特价秒杀,12306火车票秒杀,都不是事:) 下面介绍一下为什么上述三种性能优化思路能够解决秒杀系统的性能问题: 写入内存而不是写入硬盘 传统硬盘的读写性能是相当差的.SSD硬盘比传统硬盘

使用RateLimiter完成简单的大流量限流,抢购秒杀限流

RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率. 通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位时间内的访问量,譬如一些第三方服务会对用户访问量进行限制:限制网速,单位时间内只允许上传下载多少字节等. 下面来看一些简单的实践,需要先引入guava的maven依赖. 一 有很多任务,但希望每秒不超过N个 import com.google.common.util.concurrent.RateLi

Redis案例——商品秒杀,购物车

秒杀案例: 1 <?php 2 header("content-type:text/html;charset=utf-8"); 3 $redis = new redis(); 4 $result = $redis->connect('10.10.10.119', 6379); 5 $mywatchkey = $redis->get("mywatchkey"); 6 $rob_total = 100; //抢购数量 7 if($mywatchkey&