秒杀系统是一个并发量要求高、负载均衡要求高的、业务场景简单可是逻辑稍微复杂的系统,因此常常会做为面试高级后端开发的面试题。主要考察的就是对问题的拆解、分析、解决,以及架构设计的能力。前端
服务端是一个潜在的考察点,仍是有不少问题须要解决的。有些网上给出的设计方案没有对这块作详细考虑。mysql
客户端限流(在浏览器上行不通)web
客户端作必定控制来限流(好比几率),防止刷单,减小成功次数,显示在排队,实际上没发网络请求面试
前端展现redis
秒杀按钮展现要有个定时器,涉及到先后端时钟同步的问题sql
校对时间差后端
获取服务端时间,客户端时间 - 服务端时间,比较获得差值,用这种方法来同步。然而注意到网络是有开销的,这个开销须要想办法消除。不然这种毫秒级甚至秒级的时间差,会影响到秒杀的公平性。浏览器
若是这个同步是很长时间以前同步的呢,可能时间过了好久后已经相差较多了。缓存
若是客户修改系统时间怎么办服务器
这一层要考虑限流问题,以及防止恶意刷量的问题。首先限流要尽可能在上层去作,以最大程度减小后端系统的压力。其次,要避免用户找到url,不停的大量发送网络请求,或者在活动前就发送,这样也是有问题的。
限流
这属于分布式限流,通常采用 redis 来作限流,能够用令牌桶来作
防止提早刷 url
这个能够在服务端根据系统时间来决定要不要处理,也能够用一个随机的网址来保证没法模拟 url 请求(这个点还比较模糊)
并且这里涉及到服务端各服务器的时钟同步
同一个 url
这里能够用 redis 记录或者本地记录来进行计数过滤,保证用户每秒发送请求响应次数不超过一个阈值
悲观锁
性能比较差
乐观错
性能好些
缓存
缓存来保存库存量,减小访问 mysql 带来的并发,用 redis 能够作到
可是若是在拿到资格后出现问题,怎么办?在缓存里已经被减掉了,这时须要归还资格,不然卖出的数就会少,这个错误可能会出如今生单,订单入库的阶段,直到入库,这个资格才能算做完全被消费掉
mysql 更合适,有惟一键的限制,hbase 存放海量数据
同步仍是异步的问题
同步
好处,等待结果写入库里,彻底闭环
异步
可能会写入失败,丢失订单信息,由于订单详情是要尽快展现给用户的,因此一旦失败,该取消此次秒杀的结果,仍是继续认为成功,是比较棘手的问题。异步出错了,可能能够修复,可是也可能会一直出错,重试无效。这种应该归还,而后把结果通知给用户。若是异步默认生单成功,可是怎么也写不进去,那就会有问题了。(这块每太想清楚)
先说说异步作法
交由本地线程池处理
占用 service 层资源
发送 kafka
减小了 service 层资源占用,可是要保证 kafka 可靠,这里须要保证 有副本,ack -> ALL,replica 设置>1
如何保证同一个用户只能下一个单
由于资源被占用后,后续不必定生单成功,因此若是资源没了,不该该直接展现秒杀结束
server 端时间同步