秒杀系统总结

1.前言

大学毕业设计,秒杀系统设计了花费了很多心思。
未来几天也要准备考研面试,难免会被问到过去写过的项目。
所以计划对毕业设计中的内容进行全面的复盘。
如果你有设计一个秒杀系统的想法,而又不知从何开始,你可以看下去。
如果你希望他指导你的实际项目开发,那这篇文章大概率不适合你。

2.系统组成部分概述

系统是分布式系统,主要使用的技术栈是springcloud(使用的阿里巴巴开发的组件nacos sentinal,也可以更换传统组件,这无关紧要),springboot,redis,rabbitmq,mysql。
系统分为多个服务,其中包括:电商服务,基于雪花算法的唯一ID生成服务,秒杀请求处理服务,邮件发送及数据落库服务,秒杀定时启动服务。
其中最为重要的是秒杀请求处理服务,秒杀定时启动与关闭服务,后续着重介绍展开介绍以上两个服务。
以下所展示的代码只做讲解,复制粘贴并无效果。具体使用的第三方库文件可自行百度。

3.秒杀请求处理服务讲解

之所以从该服务开始讲起,是因为它是整个秒杀项目的入口。
你可以把自己想象成一个具体参与秒杀的客户。
你的一次点击就从这里开始
/*
* 使用令牌桶算法进行限流
* 令牌桶算法从应用的角度来说就是服务端设置一个阈值,代表当前服务可以处理的请求数量。这一步主要是为了防止单机接收大量请求导致服务宕机。
*
* */if(!rateLimiter.tryAcquire(2,TimeUnit.SECONDS)){return "请求超时,可再次尝试";}
/*
* 这里进行第一次访问redis
*
* 1.防止缓存穿透(缓存穿透是某些黑客可能会操控大量计算机发出请求,这些请求所请求的响应数据并不存在,此时大量请求访问redis还访问数据库,导致数据库宕机)
* 解决方法:使用布隆过滤器。(布隆过滤器作用:记录数据库中存在的数据,过滤器放在redis中,如果请求的数据不存在于数据库,那么就无需访问数据库)
* 2.获取在redis中所存放的剩余商品库存
*/String num = redisUtil.get("grabcoupon-"+key);//如果获取的数字为null,说明redis中并没有对应的秒杀。就查询以下过滤器,看数据库中有没有对应的秒杀计划if(num == null){//bloomfilter进行过滤if(!redisBloomFilter.contains(key)){return "秒杀不存在或还未开始";}//走到这里就可以查询数据库  通过查数据库决定秒杀是已经结束   还是秒杀还未开始  并返回开始时间return secKillService.validateKey(key).getMessage();}//如果返回值为-1则说明秒杀已经结束。if(Integer.valueOf(num) == -1){return "你手慢了,秒杀已经结束"+key;}
/*
*走到这里,意味着秒杀目前还在进行中。下一步就要考虑扣减库存的操作了。
*库存的扣减是一个需要进行先读后写的操作,因此必须保证这一操作的原子性。
*这里有两个处理办法:
*1.使用分布式锁。(java中内置的锁是不起作用的,java中的锁只能用于管理在JVM中存放的数据,而不能管理不同服务器中的数据)
*2.使用lua脚本。(redis可以使用lua脚本实现将一个包含多步操作的函数视作一个原语的功能)
*///开始抢购   (int) (Math.random()*(10000-1)+1)Long result = null;result = secKillService.seckill(userId, key);//此处函数功能主要是调用lua脚本 内部有查看库存,扣减库存的功能//返回值为0 表示库存为0,秒杀失败if(result == 0){return "你手慢了,秒杀已经结束"+key;}//返回值为1 表示秒杀成功以下步骤在数据库中添加用户实际获得的商品的数据,并且发送邮件给用户,提示其秒杀成功。else if(result == 1){//此处使用消息队列     使用direct方式配置mqSender.sendPerson(secKillService.findGrabCouponMessage(key, userId));return "抢购成功:"+key;}//返回值为2 表示已经秒杀过了,不能够重复进行秒杀。else if(result == 2){return "您已经抢购过了"+key;}//其他情况代表服务器错误    事实上lua脚本内部没有这个选项   但是实际项目中带代码应该及时处理错误情况,或记录日志或直接抛出错误else{return "服务器错误,可尝试再次请求";}}

lua脚本代码(如果打算自行实现秒杀,可以参考以下代码进行简单学习,我也是这样做的,这是我修改后的代码):

local userid=KEYS[1];
local gcid=KEYS[2];
local gcKey='grabcoupon-'..gcid;
local usersKey='SecKill:'..gcid;
local userExists = redis.call("sismember",usersKey,userid);
if tonumber(userExists)==1 then return 2;
end
local num=redis.call("get",gcKey);
if tonumber(num)<=0 then return 0;
else redis.call("decr",gcKey);redis.call("sadd",usersKey,userid);
end
return 1

4.秒杀定时启动与关闭服务讲解

该服务包括秒杀活动的启动和关闭。使用了定时任务插件Quartz(一个第三方库,简单学习以下很好用)。
         //这段代码是写在定时任务中的,到达指定时间服务就会启动。//下面这行代码用于在redis中添加库存redisutil.set("grabcoupon-"+gc.getId(), gc.getCount().toString());//秒杀活动都是有时间限制的,可能只有那几秒的时间用户可以疯狂点击 这里设置一个秒杀时间 5秒Thread.sleep(5000);/**这里需要解决两个问题:*1.防止缓存击穿(缓存击穿主要是指热点数据在redis中突然消失,导致大量请求打到数据库上,导致数据库宕机)*2.防止缓存雪崩(缓存雪崩是指redis中大量数据到期了,请求都访问数据库,导致数据库宕机)*3.必须获取当前redis中剩余的库存,并且将数据状态更新为秒杀已经结束(即 值-1)。这是一个先读后写的操作。*解决方案:*1.redis中存放的库存数据是热点数据。秒杀结束后不直接删除数据,而是将值置为-1。大量请求不会直接访问数据库,而是访问redis,获得值-1。*2.在库存数据设置的到期时间之上在添加一个随机的到期时间*3.获取剩余库存有多种解决方案:使用分布式锁,使用lua脚本,使用redis内置的原子性操作getAndSet(即先获取在更新)*getAndSet操作是最优雅的解决方案,实际运行速度快,实现简单。*/surplus = redisutil.getSet("grabcoupon-"+gc.getId(),"-1");//这里使用getAndSet操作获取剩余的库存surplus并且将库存值更新为-1   此处不删除键值对,为的是防止缓存击穿//这里设置一个300秒以上的过期时间,防止出现缓存雪崩setExpire_flag = redisutil.setExpire("grabcoupon-"+gc.getId(),  (long)(Math.random()*(10-1)+1)+ 300);

5.其他问题思考

当我们将这个服务部署之后也会出现一些新的问题,下面抛出这些问题供读者思考和解决:
1.布隆过滤器是无法删除的,我们应该想办法定期更新它。
2.当我们的服务器支持横向扩展(横向扩展是指通过添加多个服务器提升请求的处理效率)的时候,此时就会出现新的瓶颈,比如某些地方需要自增的key值
3.在分布式项目中,我们该如何验证用户身份呢?

毕业设计回顾:基于分布式的优惠券秒杀系统的设计与实现相关推荐

  1. java公交查询系统开题报告_毕业设计论文-基于JAVA的公交查询系统的设计与实现.doc...

    毕业设计论文-基于JAVA的公交查询系统的设计与实现.doc 还剩 42页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内 ...

  2. 【计算机毕业设计】基于JSP的网上购物系统的设计与实现

    分类号:TP315 U D C:D10621-408-(2007)5883-0 密 级:公 开 编 号:2003214012 学位论文 基于JSP的网上购物系统的设计与实现 基于JSP的网上购物系统的 ...

  3. 【单片机毕业设计】基于单片机的智能灌溉系统的设计

    一.功能简介 题目拓展:基于单片机的土壤湿度控制的设计 基于单片机的农田灌溉系统的设计 基于单片机的智慧农业灌溉的设计 项目编号:mcuclub-hj-011 单片机类型:STC89C52.STM32 ...

  4. 【单片机毕业设计】基于单片机的农田环境监测系统的设计

    一.功能简介 题目拓展:基于单片机的土壤环境监测的设计 基于单片机的智能灌溉系统的设计 基于单片机的智慧农业监测的设计 项目编号:mcuclub-hj-012 单片机类型:STC89C52.STM32 ...

  5. python网络安全毕业设计_基于Python的网络爬虫系统的设计与实现

    2018 年第 12 期 信息与电脑 China Computer&Communication 软件开发与应用 基于 Python 的网络爬虫系统的设计与实现 刘 杰 葛晓玢 闻顺杰 (铜陵职 ...

  6. 基于python的博客设计与开发_GitHub - juanshifanhua/bbs: 毕业设计:基于Python的博客系统的设计与实现...

    个人Blog博客系统 基于"python3.6.5"和"Django2.1"开发的的个人博客系统. 层级结构 cd bbs; tree . ├── bbs │  ...

  7. java-php-python-ssm基于移动端的选课系统的设计与实现服务器端计算机毕业设计

    java-php-python-ssm基于移动端的选课系统的设计与实现服务器端计算机毕业设计 java-php-python-ssm基于移动端的选课系统的设计与实现服务器端计算机毕业设计 本源码技术栈 ...

  8. 用php设计考试论坛,基于PHP的考研论坛系统的设计与实现

    基于PHP的考研论坛系统的设计与实现 南 阳 理 工 学 院本科生毕业设计(论文)学院(系): 软件学院 专 业: 网络工程 学 生: 秦梦霞 指导教师: 耿凯峰 完成日期 2015 年 05 月南阳 ...

  9. python毕业设计开题报告-基于Python的教学互动系统的设计与实现开题报告

    基于Python的教学互动系统的设计与实现开题报告 背景: 在各种信息技术与课堂的不断探索中,我们一直在寻找一个能提高教学效率的方式,同时可以发现要提高教学效率,在课堂教学中必不可少的就是师生间的互动 ...

最新文章

  1. 解读ADC采样芯片(EV10AQ190A)的采样(工作)模式(双通道模式)
  2. Windows与Linux下进程间通信技术比较
  3. 差分进化算法 matlab,差分进化算法之Matlab实现
  4. 我国标准时间授时方法
  5. bt5使用教程----主要是渗透方面
  6. 关于跨团队合作的一些思考
  7. 利用sentinel hub Python开发包查询和下载Sentinel-2等卫星遥感数据
  8. 计算机二级的Word知识点,计算机等级考试二级office基础知识点总结.doc
  9. 一周一个小朋友系列——YOLOV1 paper Analysis
  10. 有什么好玩又能学到知识的编程游戏?
  11. 自己经验AP 月结对账过程
  12. 《高手:精英的见识和我们的时代》思维导图
  13. QFN(Quad Flat No-Lead Package)
  14. 智慧水务解决方案实现了水质实时监控
  15. 写代码好用的截图工具 Snipaste
  16. 工作小工具下载(无病毒)
  17. 基于JAVA药品自动贩卖系统计算机毕业设计源码+系统+数据库+lw文档+部署
  18. html span href,html 中span标签里面都能放那些标签??
  19. JAVA多线程:线程和进程的区别和联系
  20. IBM P780在动态分区中切换磁带机(飘磁带机)与磁带备份rootvg

热门文章

  1. UEditor练习(JSP版)20190603
  2. think php 数据分页,接口数据使用ThinkPHP5的自定义分页
  3. 华为计算机高级模式,华为matepad11可以当电脑用吗 怎么切换设置电脑模式
  4. ERROR ITMS-90725: “SDK
  5. 询问HTG:在Windows 7中移动我的文档,备份Android和多监视器任务栏
  6. 写好开发者文档的八个技巧
  7. Apache IoTDB 高效插入数据的方法
  8. Python中matplotlib.pyplot工具包总结
  9. Android EditText 不自动获取焦点
  10. 『叶问』#39,都有哪些情况可能导致MGR服务无法启动