Sanno限时秒杀商城项目
Dandy1awcoder
这个作者很懒,什么都没留下…
展开
-
超卖现象及解决
本项目的超卖类似于电商的秒杀超卖现象1.不同用户在读请求的时候,发现商品库存足够,然后同时发起请求,进行秒杀操作,减库存,导致库存减为负数。2.同一个用户在有库存的时候,连续发出多个请求,两个请求同时存在,于是生成多个订单。对于第一种超卖现象;(1)最简单的方法,更新数据库减库存的时候,进行库存限制条件,update miaosha_goods set stock_count...原创 2018-07-23 21:14:20 · 9179 阅读 · 5 评论 -
数据库中表的设计
四张表:商品表,秒杀商品表,订单表,秒杀订单,用户表秒杀商品和商品表,分开。原因:为了防止多次活动,若是在每次秒杀活动的时候,设置一个字段来确定秒杀商品,也可以。但是每次都会操作数据库,修改秒杀商品的字段,因为每次秒杀时候。对应的秒杀时间段,秒杀实现,秒杀功能,价格,都不同,时间常了,商品表不易于维护。而且,秒杀商品的个数和普通商品的个数是独立计算的,不同于普通商品的库存字段。/*用户表*/CR...原创 2018-07-15 16:14:40 · 1576 阅读 · 0 评论 -
商品详情页及秒杀倒计时功能
详情页进入:就是前端点击链接,链接中有{goodsId}作为参数,后端@PathVarible 拿到这个id,然后去数据库查询对应的商品信息,并显示的一个功能。这里有一个比较重要的就是秒杀倒计时功能:后端获取秒杀开始时间和结束时间,以及系统当前时间,并定义剩余时间变量和秒杀状态,传给前端。 @RequestMapping(value = "/to_detail2/{goodsId}",pro...原创 2018-07-15 16:30:36 · 3577 阅读 · 0 评论 -
秒杀业务事务处理
@RequestMapping(value = "/do_miaosha")@ResponseBodypublic String Miaosha(MiaoshaUser user, Model model, @RequestParam("goodsId")long goodsId){ /*判断是否登陆*/ if ...原创 2018-07-15 16:41:04 · 1262 阅读 · 1 评论 -
页面缓存、URL缓存、对象缓存
页面缓存优化:这种缓存技术一般用于不会经常变动信息,并且访问次数较多的页面,这样就不用每次都动态加载。商品列表页 页面缓存:1.取缓存 ()2.手动渲染 3.结果输出Thymeleaf 的页面渲染技术。 @ResponseBody @RequestMapping(value = "/to_list",produces = "text/html") public String t...原创 2018-07-15 17:29:17 · 7591 阅读 · 1 评论 -
页面静态化、前后端分离(页面优化)
大概:将页面缓存到客户的浏览器上,当用户访问页面的时候,直接不与服务器有交互,直接从本地缓存中拿取页面,节省网络流量。之前的逻辑:点击链接,访问后端controller 访问业务层,成功获取数据,将数据渲染到html页面再将整个html页面返回给客户显示现在:点击链接,除了第一次访问。访问直接访问用户本地的缓存的html页面 (浏览器会缓存下来静态static下文件),静态资源,然后通过前...原创 2018-07-15 17:40:01 · 5018 阅读 · 1 评论 -
本项目超卖问题解决
超卖现象:1.不同的很多用户,发出请求10个,但是只有5个商品,同一时间访问2.同一用户,在10个商品时,发出2个请求,在stock都成功 第一种:当读库存的时候,正常还有1个,于是2个用户都来就买,就超卖了。1.update的时候加一个限制条件,count>12. 所谓超卖现象举例:比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商...原创 2018-07-24 20:18:24 · 3801 阅读 · 0 评论 -
【Redis】相关的面试问题
1.什么是Redis?一款高性能的key-value缓存数据库。优势:一款基于内存的key-value数据库,整个数据库都在内存中运行操作,每秒可以支持10W左右的读写操作,而且支持数据持久化,还可以支持多种数据结构。缺点:容量受到物理内存的限制。不能做海量数据的高性能读写。适合较少数据的高性能读写。Redis的数据类型及底层数据结构二、数据类型数据类型 可以存储的值...原创 2018-08-03 20:02:37 · 921 阅读 · 0 评论 -
Rabbit MQ 面试题相关
项目中的MQ:#rabbitmqspring.rabbitmq.host=127.0.0.1 主机spring.rabbitmq.port=5672 端口spring.rabbitmq.username=guest 用户名spring.rabbitmq.password=guest 密码spring.rabbitmq.virtual-host=/#\u6D88\u8D...原创 2018-08-03 20:48:26 · 9544 阅读 · 0 评论 -
缓存更新策略以及缓存击穿、雪崩、穿透
本项目使用的更新策略是:cache aside ;简而言之,就是1. 首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。2. 需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。 首先要确定的是使用先更新数据库,再更新缓存的方法(最好淘汰缓存),防止多线程情况下,更新缓存和更新数据库不一致,存在脏数据。原因:先更新数...原创 2018-07-27 21:19:05 · 1098 阅读 · 0 评论 -
项目的亮点和难点
Sanno限时秒杀抢票系统亮点:在高并发情况下的秒杀优化,我们知道当并发数达到一定量的时候,会对数据库服务器带来很大的压力,那么如何缓解这些压力以及提高并发的QPS就是整个项目的重点。(不断的提高QPS)。亮点3个:1.利用缓存减少数据库的压力,以及读取缓存的速度远远快于数据库(网络时延+IO)2.页面静态化技术加快用户访问速度,提高QPS,异步下单增强用户体验,以及内存标记减少R...原创 2018-08-03 15:15:00 · 43970 阅读 · 3 评论 -
分布式Session
背景:对于秒杀服务,实际的应用可能部署在不止一个服务器上,而是分布式的多台服务器,这时候要是用户登录是在第一个服务器,但是操作的时候第二个请求在第二个服务器,就会丢失用户的Session信息,最少你的重新登录。一。分布式Session的几种实现方式1.基于数据库的Session共享2.基于NFS共享文件系统3.基于memcached 的session,如何保证 memcached 本身的高可用性?...原创 2018-07-15 16:08:24 · 795 阅读 · 1 评论 -
JSR303参数校验+全局异常处理
JSR3031.JSR 303 用于对Java Bean 中的字段的值进行验证,使得验证逻辑从业务代码中脱离出来。 2.是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。@RequestMapping("/do_Login")@ResponseBody //这个注解有点厉害 可以将返回值 转化为json 格式 输入 也可以转化为json?public Result<B...原创 2018-07-15 15:34:33 · 4015 阅读 · 3 评论 -
接口优化----Redis预减库存,内存标记
Redis预减库存:主要思路减少对数据库的访问,之前的减库存,直接访问数据库,读取库存,当高并发请求到来的时候,大量的读取数据有可能会导致数据库的崩溃。思路:1.系统初始化的时候,将商品库存加载到Redis 缓存中保存 2.收到请求的时候,现在Redis中拿到该商品的库存值,进行库存预减,如果减完之后库存不足,直接返回逻辑Exception 就不需要访问数据库再去减库存了,如果库存...原创 2018-07-23 21:48:19 · 8021 阅读 · 17 评论 -
接口优化--Rabbit MQ异步下单
Rabbit MQ 消息队列了解一下四种交换机模式:1.Direct 模式 2.Topic 模式 3.Fanout模式(广播模式) 4.Header 模式 (根据header中的键值 进行消息匹配)本项目中使用的是Direct模式。思路:1.当确认秒杀开始,(库存充足,且无重复秒杀)将秒杀请求需要的消息入队(封装),同时给前端返回一个code (0),前端接收到数据后,显示...原创 2018-07-23 22:27:00 · 3463 阅读 · 1 评论 -
安全优化--秒杀接口地址的隐藏
秒杀接口地址隐藏:每次点击秒杀按钮,才会生成秒杀地址,之前是不知道秒杀地址的。不是写死的,是从服务端获取,动态拼接而成的地址。(Http协议是明文传输,透明的,前端无法控制恶意用户进行攻击)安全校验还是要放在服务端,禁止掉这些恶意服务。思路:1.在进行秒杀之前,先请求一个服务端地址,/getmiaoshaPath 这个地址,用来获取秒杀地址,传参为 商品id,在服务端生成随机数(MD5)作...原创 2018-07-24 20:40:41 · 5165 阅读 · 10 评论 -
安全优化---数学公式图形验证码
秒杀接口地址的隐藏可以防止恶意用户通过频繁调用接口来请求的操作,但是无法防止利用按键精灵或者机器人频繁点击按钮来刷接口的操作。而且,对于高并发下,在某一个时间段,也就是刚刚开始秒杀的那一瞬间,迎来的并发量是最大的,如何做到并发量分流也是一种减少数据库以及系统压力的措施。数学图形验证码:1.防机器人刷接口2.分散用户请求 思路:点击秒杀按钮之前,需要输入验证码验证1.生成...原创 2018-07-24 21:13:46 · 2175 阅读 · 1 评论 -
安全优化---接口限流防刷
接口限流防刷:限制同一个用户在限定时间内,只能访问固定次数。思路:每次点击之后,在缓存中生成一个计数器,第一次将这个计数器置1后存入缓存,并给其设定有效期。每次点击后,取出这个值,计数器加一,如果超过限定次数,就抛出业务异常。 String limitURL =request.getRequestURI();//url 是Stringbuffer URI St...原创 2018-07-24 21:46:12 · 4971 阅读 · 0 评论 -
CodeMsg类的定义及好处
** CodeMsg 用于保存 异常码和异常信息,由于失败没有数据返回 * */public class CodeMsg { private int code; private String msg; /**通过静态方法调用CodeMsg对象获取对应error信息 自定义error 信息 * */ /*服务端异常*/ public sta...原创 2018-07-15 13:08:13 · 4091 阅读 · 0 评论 -
Redis/Jedis配置,集成及相关知识点
1.配置依赖Jedis :jedis就是集成了redis的一些命令操作,封装了redis的java客户端。提供了连接池管理。一般不直接使用jedis,而是在其上在封装一层,作为业务的使用。该项目就是在Jedis提供的操作基础上,封装了一层业务层操作。主要几个类:1.RedisConfig RedisPoolFactory 2.RedisService1.RedisConfig :配置Redis连...原创 2018-07-15 13:31:52 · 948 阅读 · 0 评论 -
通用缓存key封装
为什么要这个类?当项目中的模块越来越多的时候,需要存的缓存也越来越多,比如商品Id,订单Id,用户id等,此时若是id出现重复,将给系统带来错误。方法:利用一个前缀来规定不同模块的缓存的key,这样不同模块之间就不会重复。(枚举不好,因为在该类中定义了缓存的时间)。设定一个抽象基类:Baseprefix 用于继承,不同模块的前缀类都继承他。 Keyprefix()接口定义2 个方法/** 抽象类...原创 2018-07-15 13:43:33 · 1320 阅读 · 0 评论 -
两次MD5加密设计
/** 用于生成MD5 密码的工具类 * */public class Md5Util { public static String md5(String input){ return DigestUtils.md5Hex(input);//注意导包为codec中的DigestUtils类 } /*固定盐值*/ private static...原创 2018-07-15 14:53:47 · 7259 阅读 · 3 评论 -
项目中遇到的bug及面试问题总结
1.Redis服务器 can not get resource from pool. 1000个线程并发还能跑,5000个线程的时候出现这种问题,查后台debug日志,发现redis 线程池不够。刚开始设置的是:# redis 配置文件#redisredis.host=127.0.0.1redis.port=6379redis.timeout=300 等待时间 1...原创 2018-08-03 15:50:09 · 49484 阅读 · 5 评论