排队
要对流量进行削峰,最容易想到的解决方案就是用消息队列来缓冲瞬时流量,把 同步的直接调用转换成异步的间接推送,中间通过一个队列在一端承接瞬时的流 量洪峰,在另一端平滑地将消息推送出去。在这里,消息队列就像“水库”一 样, 拦蓄上游的洪水,削减进入下游河道的洪峰流量,从而达到减免洪水灾害 的目的。但是,如果流量峰值持续一段时间达到了消息队列的处理上限,例如本机的消息 积压达到了存储空间的上限, 消息队列同样也会被压垮,这样虽然保护了下游的 系统 ,但是和直接把请求丢弃也没多大的区别。就像遇到洪水爆发时,即使是有水库恐怕也无济于事。
除了消息队列,类似的排队方式还有很多,例如:
1. 利用线程池加锁等待也是一种常用的排队方式;
2. 先进先出、先进后出等常用的内存排队算法的实现方式;
3. 把请求序列化到文件中,然后再顺序地读文件(例如基于 MySQL binlog 的同步机制)来恢复请求等方式。
答题
第一个目的是防止部分买家使用秒杀器在参加秒杀时作弊。
第二个目的其实就是延缓请求,起到对请求流量进行削峰的作用,从而让系统能够更好地支持瞬时的流量高峰。
分层过滤
假如请求分别经过 CDN、前台读系统(如商品详情系统)、后台系统(如交易 系统)和数据库这几层,那么:
1.大部分数据和流量在用户浏览器或者 CDN 上获取,这一层可以拦截大部分数据的读取;
2.经过第二层(即前台系统)时数据(包括强一致性的数据)尽量得走Cache,过滤一些无效的请求;
3.再到第三层后台系统,主要做数据的二次检验,对系统做好保护和限流,这样数据量和请求就进一步减少;
4.最后在数据层完成数据的强一致性校验。
分层校验的基本原则
1. 将动态请求的读数据缓存(Cache)在 Web 端,过滤掉无效的数据 读;
2. 对读数据不做强一致性校验,减少因为一致性校验产生瓶颈的问题;
3. 对写数据进行 基于时间的合理分片 ,过滤掉过期的失效请求;
4. 对写请求做限流保护, 将超出系统承载能力的请求过滤掉 ;
5. 对写数据进行强一致性校验,只保留最后有效的数据。
分层校验的目的是:在读系统中,尽量减少由于一致性校验带来的系统瓶颈,但是尽量将不影响性能的检查条件提前,
如用户是否具有秒杀资格、商品状态是否 正常、用户答题是否正确、秒杀是否已经结束、是否非法请求、营销等价物
是否充足等;在写数据系统中,主要对写的数据(如“库存”)做一致性检查,最后 在数据库层保证数据的最终准确性
(如“库存”不能减为负数)。