秒杀最早来自天猫双 11 各种商品的促销活动中, 现在已经有很多业务场景在使用, 比如抢红包, 抢票等其特点有三高: 瞬时并发高, 数据一致性高, 热点更新频度高这样三高的场景下往往给数据库造成极大的压力, 大量更新数据库中的同一行, 这样必然会产生锁等待, 导致数据库的性能急剧下降的问题, 很容出现雪崩效应
记得有一年春节, 一个电视台定时在整点发放红包, 结果由于压力太高, 导致更新数据库红包数额的请求全部堆积, 业务全部挂掉, 面对这样的情况我们当时也束手无策
面对秒杀业务的场景, 数据库成为了底层系统中最重要的瓶颈点, 阿里经过几年的沉淀也诞生了很多的技术手段来进行优化主要包括以下几个方面:
1 业务流程优化
2 访问来源优化
3 流量控制
业务流程优化
以淘宝的交易订单为例, 在共享服务平台模式下, 订单创建流程需要调用超过 200 个服务, 如果以严格的顺序调用的方式, 哪怕每一个服务调用都控制在 20ms 以内, 那么完成一个订单也需要 4s 的时间, 远远超过了用户的忍耐极限
另外, 顺序调用会导致对系统资源的过度占用, 给服务器整体的吞吐量产生巨大影响
因此, 对于有严格先后顺序的服务保持顺序调用, 对于能够同步执行的服务均采用异步化的方式处理
从数据库层面, 实现的核心技术就是采用数据库事务的异步化也就是将大事务拆分成小事务, 同样根据以上原则, 进行相对异步化处理 (在该过程中, 最重要的是要控制程序或者业务异常时, 不会导致结果不一致, 或支持有效的回滚和重试机制)
访问来源优化
在传统的数据库访问中, 一次 SSD 盘数据访问在几十微秒, 一次 SATA 盘数据访问在几十毫秒, 而内存数据库的操作时间是纳秒级的, 因此通过缓存技术改变业务访问的数据来源从而提高系统性能和吞吐量的技术被各大企业的互联网应用广泛使用
淘宝在业务的发展过程中, 也不断通过缓存技术的研究和应用的改进高性能
早期通过缓存实现应用分布式 session, 以避免应用实例间会话的复制, 后来发展为将缓存用于业务去重判断交易快照图片索引等场景, 最后 替换数据库在业务交易处理中的职能缓存在业务中扮演越来越重要的角色
流量控制
接下来我们重点讲一下底层数据所做的优化当大量的并发更新同一条记录时, 使用排队的方式来保证高并发下热点记录更新依然能保持较好的性能, 为 threads_running 设置一个硬上线, 当并发超过此值是, 拒绝执行 sql, 保护 MySQL, 我们将这个称之为高水位限流, 这样就给数据库加上了一层限流的功能, 使得数据库不被瞬间的高爆发请求打爆
高水位限流实现:
监控系统 status 变量 threads_running, 当满足拒绝条件, 拒绝执行 sql, 返回用户: MySQL Server is too busy, 判断逻辑在 dispatch_command 中, sql 解析之后
增加的系统 variables:
1.threads_running_ctl_mode: 限流的 sql 类型, 有两个取值:[ALL | SELECTS], 默认 SELECTS, 设置为 ALL 需谨慎
2.threads_running_high_watermark: 限流水位值, 只有 threads_running 超过此值才会触发, 默认值为 max_connections, 当 set global threads_running_high_watermark=0 时自动设置为 max_connections
拒绝必要条件:
1..threads_running 超过 threads_running_high_watermark
2..threads_running_ctl_mode 与 sql 类型相符
以下情况不拒绝:
1. 用户具有 super 权限
2.sql 所在事务已经开启
3.sql 为 commit/rollback
阿里云的 RDS 已经集成了阿里秒杀场景下的参数优化, 所以如果你的应用场景中具有大量并发更新同一行记录的场景, 可以打开数据库的限流参数: threads_running_ctl_mode 和 threads_running_high_watermark 来保护数据库, 让数据库平稳过渡
下面我们来看一则生产案例
从上图中看到该数据库的活跃连接数最高的时候到达了 1W, 通过 show processlist 可以看到大量的并发更新
我们来看一下数据库并发更新的 TPS 有多大:
可以看到数据库中的活跃连接数非常高, 每秒的 update 非常不稳定
我们在把限流开关打开后看一下性能表现:
- mysql> set global rds_threads_running_high_watermark=300;
- Query OK, 0 rows affected (0.00 sec)
- mysql> set global rds_threads_running_ctl_mode='all';
- Query OK, 0 rows affected (0.00 sec)
从上图可以明显的观察到, 通过打开数据库的限流开关, 数据库的活跃连接数在 300 左右, 同时数据库的 TPS 也没有再出现很大的波动, 这样很好的保护住了 DB
双 11 至今为止发展为中国乃至全球最成功的大型促销活动用户对系统性能的极致追求业务的巨大压力给整个系统的建设和运维管控都提出了很高的要求而阿里正是在这样的大促秒杀活动中, 积累了相当丰富的架构设计经验和平台开发能力
来源: https://yq.aliyun.com/articles/438702