Redian新闻
>
Redis队列实现Java版秒杀系统(无脚本、可用于生产)

Redis队列实现Java版秒杀系统(无脚本、可用于生产)

公众号新闻

本文系转载,原作者:控场的朴哥

原文地址:blog.csdn.net/weixin_43074462/article/details/103756536


写在前面

需求是做一个秒杀系统,比如大家来抢100台手机,先到先得。

查阅了网上很多用redis实现秒杀的demo(java语言),竟然没一个能用的!!!

有些是php的,没闲心研究了,现在说说为什么不能用:

  • 绝大多数的DEMO都是基于redis的watch特性的事务实现①,
  • 个别是基于redis分布式锁实现②。
  • 当然还有些用了脚本的,我也没仔细看是lua还是调用redis指令,哪有那个闲心去研究哇。

照顾一下小白,分析一下为什么这几种实现不行

1.基于watch特性的 不靠谱 实现

其实这两种实现方式,完全可以理解为乐观锁(watch)和悲观锁(加分布式锁)

watch事务,相当于是乐观锁,这种方法在并发情况下极为不靠谱,假设有100个人同时尝试秒杀,那么极端情况下,有99个人都会失败,只有一个能修改成功。

然而demo里甚至没写如果修改失败了就重试这个功能,那显然这失败的99个人,已经提示失败了,过一会回来,发现还剩了90多。那我是怎么失败的?我替他们问问了。

并且使用这种方式实现呢,在并发量较大的时候,过多的重试线程应该会严重影响服务器性能。

2.基于用redis做个分布式锁的 不靠谱 实现

这种实现方式相当于一个悲观锁,每次执行减减操作之前,在redis中存入一个k,v键值对,使用特定的名称,并且使用setNX特性,确保抢锁没有安全问题,并在使用完成后释放锁。那么问题是,在100个人秒杀时,只有一个人抢到锁,剩下99个人怎么办?

demo里同样没写个重试,抢不到锁就失败,醉了,不过就算写重新抢锁的机制,那么几十个上百个线程不断抢锁,想想是个挺恐怖的事,更别提高并发了。

基于脚本的实现 不靠谱 实现

作为一个C系语言开发,我看不太懂,看不懂就是不靠谱,出了问题都不知道改哪里,你说靠不靠谱

正题:使用spring操作redis的list队列实现

我用的是springboot的StringRedisTemplate,至于如何整合jedis到spring等等,去查阅其他文章吧,我就不重复写了。

贴工具类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Collection;

@Service
public class RedisServiceImpl<Timplements RedisService<T{
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //添加字符串并设置过期时间
    @Override
    public void addString(String key, String value, Duration duration) {
        stringRedisTemplate.opsForValue().set(key, value, duration);
    }

    //查找字符串
    @Override
    public String findString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    //根据Key删除
    @Override
    public Boolean deleteByKey(String key) {
        return stringRedisTemplate.delete(key);
    }

 //在队列尾部减少一个对象
    @Override
    public String removeOneEntryOnListRight(String listName) {
        return stringRedisTemplate.opsForList().rightPop(listName);
    }

 //在队列头部新增对象
    @Override
    public Long addEntriesOnListLeft(String listName, Collection<String> args) {
        return stringRedisTemplate.opsForList().leftPushAll(listName, args);
    }

}

解释一下哈 这个类的父类是我自己写的service层,不是提供好的

主要使用的是最后两个方法,最后一个方法,在队列头部新增对象,如果没有这个队列,他会创建出来这个队列,然后将一个集合统统塞到这个redis队列中。倒数第二个方法每调用一次,会删除队列中最后一个元素,然后返回这个元素的值,如果队列中已经没有元素了(队列已经没了)那么他会返回null,他们都是原子操作。

如此,每个请求都无需经过加锁操作,直接利用redis的单线程特性,即可实现高并发下的秒杀:请求到达redis,redis会逐个执行,每一次执行要么返回一个值,要么返回null。很显然,返回值的就是抢到了,返回null的就是没抢到。而且可以灵活的为这个队列新加入一些元素(老板发话再加100台)或者直接把这个队列删了(老板说不行,不卖了)都不会对代码产生任何影响。

其中对应的redis操作指令分别是:

  • 在队列左侧新增:lpush
  • 在队列右侧消费:rpop

老板不卖了:del (笑)

接下来贴出十分简单的使用方法

先贴在任务开始时向redis中插入一个大队列

List<String> entriesList = new LinkedList<>();
   for (int i = 0; i < 100; i++){
       entriesList.add("某个商品");
   }
   redisService.addEntriesOnListLeft("队列名",entriesList);

突然想到这个实现即使秒杀100台不同型号的手机(并且在秒到时就通知用户秒到的是啥),也不用改代码。

每次秒杀执行:

String redisResult = redisService.removeOneEntryOnListRight("队列名");
    if (null == redisResult) {
        //说明没抢到
    }else{
 //说明抢到了 执行抢到逻辑
}

突然发现这个实现看起来甚至比那些所谓的秒杀demo还简单

但他既没有并发问题,也没有为了解决并发问题而衍生的性能问题。

虽然没经过测试,不过我认为就算秒杀10万台,放到redis队列里,应该也占用不了多少内存。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
这项抛光技术,可用于SiC和GaN中国南方心衰队列:HFrEF占22%,17%的患者在5年内死亡业界首个适用于固体系统的神经网络波函数,登上Nature子刊消息队列原理和选型:Kafka、RocketMQ 、RabbitMQ 和 ActiveMQ下一代北斗可用于太空“导航”纸吸管、可机洗购物袋用起来!加拿大禁塑令今日生效:7年实现零塑料在美国271.害人害己一日团 |️ 大小白熊都来啦!69元!可用于户外、露营、居家、车里都可以用,特别是宝宝的玩具,超实物,超需要~可翻领、可V领、可高领,这件半拉链毛衣简直太好穿了!包容显瘦,时尚慵懒,轻松hold住各种风格!当我误把开房的心路历程发到好友QQ群后(无法撤回)Gut:六大研究队列近80万人研究结果表明:采用并保持健康生活方式或能预防高达60%的炎性肠病病例的发生钱学森的“回国观感”For Gen-Z, Entrepreneurship Represents a Ticket to FreedomHunan Shuts Access to Forest Areas to Prevent More Wildfires走资派邓小平窃国大盗乱世奸雄国家高性能医疗器械创新中心牵头研发我国首台国产体外膜肺氧合系统(ECMO)获批上市苗条女孩更要补!近3万人队列研究证实:每天多摄入25克蛋白质,或将降低14%髋骨骨折风险!AI求解偏微分方程新基准登NeurIPS,发现JAX计算速度比PyTorch快6倍,LeCun转发:这领域确实很火最新综述:详细分析14种可用于时间序列预测的损失函数SpringBoot 整合 Groovy 脚本,实现动态编程她故事|无手无脚的奇迹女画家:从街头艺人逆袭成王室御用画师习大帝也不是一无是处,治好了朋友的抑郁​GENIUS: 根据草稿进行文本生成的预训练模型,可用于多种NLP任务的数据增强赔偿35万美元:美国华人都来签一下请愿(无须捐款)《流浪2》《中国乒乓》等一大波春节档华语电影上映!而我们恰好有$14.5的半价电影票!可用于任意Hoyts任意电影Nature公布2023年最值得关注的七项新技术,5项属于生物医学领域Costco一月门店特价实拍:我不信你只买一板电池(无损纯净版)艳遇《流浪地球2》中国电影工业新高度,片中的太空电梯够不够科学?(无剧透)老药新用,这种降压药可用于延长寿命、减缓衰老可信、可爱、可敬的中国秒杀系统设计套路,一套带走《Nature》麻省理工学院研究垂直堆叠LED,用于高分辨率数字屏幕?白卡资金可用于买食物?这些州已获批高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。