秒杀系统优化思路

将请求尽量拦截在系统上游

充分利用缓存

客户端层

  • 按钮置灰、禁止重复提交
  • js控制,在X 秒内只能提交一次请求

    站点层

  • 通过用户唯一标识uid进行统计和去重,在X 秒内 同一个uid只能透过一次请求

  • 做页面缓存在X 秒内同一个uid请求均返回同样的数据

服务层

  • 将请求转化为队列,像秒杀这类业务的数量固定的,可以把多余的请求直接拦截在队列之外
  • 对于写请求,我们可以通过队列进行分段处理,每次只透有限的写请求到数据层,处理完了再处理下一批,如果库存不足则队列里的都返回已抢光
  • 对于读请求,可以加缓存
  • 业务规则上,可以将用户分时分段,将流量均摊到不同时段

数据库层

  • 可以进行分库分表
  • 归档
  • 主从
  • 集群


分布式ID生成

  • 数据库的ID自增
  • 增加主库,每个主库设置不同的初始值和步长
  • 单点批量ID生成服务
  • UUID,缺点是不能保证递增,作为主键建索引效率低
  • 取当前毫秒数,并发超过1000会重复
  • 类snowflake算法(雪花算法)

image.png

线程数究竟设多少合理

N核服务器,通过执行业务的单线程分析出本地计算时间为x,等待时间为y,则工作线程数(线程池线程数)设置为 N*(x+y)/x,能让CPU的利用率最大化。

单点系统架构的可用性与性能优化

单点系统存在的问题

  • 非高可用:既然是单点,master一旦发生故障,服务就会受到影响
  • 性能瓶颈:既然是单点,不具备良好的扩展性,服务性能总有一个上限,这个单点的性能上限往往就是整个系统的性能上限

如何高可用

  • shadow-master它能够解决高可用的问题,并且故障的转移是自动的,不需要人工介入,但不足是它使服务资源的利用率降为了50%,业内经常使用keepalived+vip的方式实现这类单点的高可用

负载均衡

  • 负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据【均匀】分摊到多个操作单元上执行,负载均衡的关键在于【均匀】。

客户端层->反向代理层

  • 通过“DNS轮询”: DNS-server对于一个域名配置了多个解析ip,每次DNS解析请求来访问DNS-server,会轮询返回这些ip,保证每个ip的解析概率是相同的。这些ip就是nginx的外网ip,以做到每台nginx的请求分配也是均衡的。

反向代理层->站点层

  • 通过nginx 配置实现负载均衡到具体的站点

站点层->服务层

  • 通过Ribbon实现进程内的负载均衡

DNS轮询

  • nginx:一个高性能的web-server和实施反向代理的软件
  • lvs:Linux Virtual Server,使用集群技术,实现在linux操作系统层面的一个高性能、高可用、负载均衡服务器
  • keepalived:一款用来检测服务状态存活性的软件,常用来做高可用
  • f5:一个高性能、高可用、负载均衡的硬件设备(听上去和lvs功能差不多?)
  • DNS轮询:通过在DNS-server上对一个域名设置多个ip解析,来扩充web-server性能及实施负载均衡的技术

接入层负载均衡演变

  • DNS轮询

image.png

  • 通过一个域名匹配多个服务IP来达到负载均衡
  • 缺点:不能保证服务可用性
  • 暴露了太多IP
    • nginx反向代理

image.png

  • 站点层与浏览器层之间加入了一个反向代理层,利用高性能的nginx来做反向代理,nginx将http请求分发给后端多个web-server
  • 缺点:nginx单点问题
    • keepalived

image.png

  • 做两台nginx组成一个集群,分别部署上keepalived,设置成相同的虚IP,保证nginx的高可用
  • 当一台nginx挂了,keepalived能够探测到,并将流量自动迁移到另一台nginx上,整个过程对调用方透明
  • 缺点:资源利用率只有50%
  • lvs/f5

image.png

  • 如果通过nginx可以扩展多个tomcat一样,可以通过lvs来扩展多个nginx
  • 通过keepalived+VIP的方案可以保证可用性

接入层架构要考虑的问题域为:高可用、扩展性、反向代理+扩展均衡 nginx、keepalived、lvs、f5可以很好的解决高可用、扩展性、反向代理+扩展均衡的问题 水平扩展scale out是解决扩展性问题的根本方案,DNS轮询是不能完全被nginx/lvs/f5所替代的

异构服务器如何负载均衡和过载保护

动态权重设置

  • 用一个动态权重来标识每个service的处理能力,默认初始处理能力相同,即分配给每个service的概率相等;
  • 每当service成功处理一个请求,认为service处理能力足够,权重动态+1;
  • 每当service超时处理一个请求,认为service处理能力可能要跟不上了,权重动态-10(权重下降会更快);
  • 为了方便权重的处理,可以把权重的范围限定为[0, 100],把权重的初始值设为60分。

过载保护

  • 什么是过载保护?

    • 互联网软件架构设计中所指的过载保护,是指当系统负载超过一个service的处理能力时,如果service不进行自我保护,可能导致对外呈现处理能力为0,且不能自动恢复的现象。而service的过载保护,是指即使系统负载超过一个service的处理能力,service让能保证对外提供有损的稳定服务。
  • 如何进行过载保护?

    • 通过动态权重,针对那些超时次数到达一定阀值的服务提供一定时间段的请求间隙

高并发优化方案

  • 反向代理层可以通过“DNS轮询”的方式来进行水平扩展;
  • 站点层可以通过nginx来进行水平扩展;
  • 服务层可以通过服务连接池来进行水平扩展;
  • 数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;

高可用优化方案

(1)【客户端层】到【反向代理层】的高可用,是通过反向代理层的冗余实现的,常见实践是keepalived + virtual IP自动故障转移
(2)【反向代理层】到【站点层】的高可用,是通过站点层的冗余实现的,常见实践是nginx与web-server之间的存活性探测与自动故障转移
(3)【站点层】到【服务层】的高可用,是通过服务层的冗余实现的,常见实践是通过service-connection-pool来保证自动故障转移
(4)【服务层】到【缓存层】的高可用,是通过缓存数据的冗余实现的,常见实践是缓存客户端双读双写,或者利用缓存集群的主从数据同步与sentinel保活与自动故障转移;更多的业务场景,对缓存没有高可用要求,可以使用缓存服务化来对调用方屏蔽底层复杂性
(5)【服务层】到【数据库“读”】的高可用,是通过读库的冗余实现的,常见实践是通过db-connection-pool来保证自动故障转移
(6)【服务层】到【数据库“写”】的高可用,是通过写库的冗余实现的,常见实践是keepalived + virtual IP自动故障转移

100亿数据1万属性数据架构设计