分布式、高并发、高性能场景(抢购、秒杀、抢票、限时竞答)数据一致性解决方案

技术指标:

PV(Page View, 页面浏览量)在千万级别
QPS(Query Per Second, 每秒处理请求数)在百万级别
数据量在千亿级别
接口响应速度不能超过150毫秒
用户提交请求到页面呈现不能超过3秒

架构设计:
1. 从LAMP架构转为面向服务架构(服务可以用多种开发语言实现,不受一种开发语言限制)
2. 对海量数据做Sharding分片,分库分表
3. 从有状态服务改为无状态接口服务(便于分布式部署)
4. 精心设计的数据层(存储、压缩、索引)
5. 分布式系统最终瓶颈(CPU、内存、存储、网络)
6. 日志服务化,每个服务可以用不同的开发语言,考虑多种开发语言的兼容性,定义标准化的日志是把分布在不同机器上的日志关联起来的唯一且有效的办法
7. 对请求入口做负载均衡后再到达应用层

页面优化:
1. 静态文件压缩,优化HTTP请求连接数,以减少宽带需求,让页面更快加载出来
2. 静态资源做CDN部署
3. 前后端做数据分离,让搜索服务解耦,在高并发情况下更灵活做负载均衡(前端使用Vue.js、AngularJs等,数据来源可以不限编程语言)
4. 后端数据大部分来自缓存,加载快,给用户更快的体验

后端编码:
1. 高并发多线程写入同一个文件的时候,会存现“线程安全”的问题,导致结果和预期不一致,常用的方法是给代码逻辑加上“锁”。
2. 秒杀和抢购的场景中,还有另外一个问题,就是“超发(超卖)”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

数据层架构优化:
1. 商品详情、商品库存等,可以放在缓存(redis集群),避免频繁去数据库取数据,提高商品信息的读能力
2. 数据库读写分离,分库分表实现负载均衡
3. 如果数据库有查询缓存功能,则使用数据库查询缓存功能(Query Cache功能,如果使用,记得定时清理碎片:Flush Query Cache)
4. 其他数据库细节优化(参考其他网络文章)

系统层优化:
1. 修改linux内核参数,适应高并发场景(具体参考网络相关文章)

业务优化:
秒杀和抢购收到了“海量”的请求,实际上里面的水分是很大的。有很多是第三方抢购辅助工具发送的请求,这些都是属于作弊的手段。

作弊方法和防御方法:
1. 作弊行为:同一个帐号,一次性发出多个请求
防御方法:在程序入口处,1个帐号只允许接收一个请求,其他请求过滤。或者,自己实现一个服务,将同一个账号的请求放入一个队列中,处理完一个,再处理下一个。

2. 多个账号,一次性发送多个请求
很多帐号注册功能,在发展早期是没有任何限制的,很容易就能注册很多个帐号。因此,一些特殊的工作室会编写自动注册脚本,积累一大批“僵尸帐号”(微博中的僵尸粉),数量庞大,专门做各种“刷”的行为,如抢购、刷票、转发抽奖等。
防御方法:
1).使用创新的验证码,比如回答问题或者执行某些简单的操作,把真实的用户和辅助工具区分来开。
2).直接禁止IP,虽然可能导致误伤,但是在实际场景中可以获得很好的效果。

3. 多个帐号,多个IP发送不同请求
“灰色工作室”发现单机IP请求频率被控制后,他们有的新的进攻方案:不断变换IP。(IP来源有随机代理IP、被植入木马的肉鸡,数量庞大等)
防御方法:这种场景下的请求,已经很难分辨出真实用户或辅助工具。通常只能通过设置业务门槛来限制这种请求,或者通过帐号行为的“数据挖掘”来提前清理它们。
僵尸帐号有一些共同的特征,就是帐号很可能属于同一号码段,甚至是连号,活跃度不高,等级低,资料不全等。根据这些特点,适当设置参与门槛,例如限制参与的帐号等级等。通过这些方法,也可以过滤掉一部分僵尸帐号。
(黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等)

系统瓶颈/灾难预案:
1. 最简单的就是有降级的预案,流量超过系统容量后,先把哪些功能砍掉, 需要有明确的优先级 。
2. 线上全链路压测,就是把现在的流量放大到我们平常流量的五倍甚至十倍(比如下线一半的服务器,缩容而不是扩容),看看系统瓶颈最先发生在哪里。我们之前有一些例子,推测系统数据库会先出现瓶颈,但是实测发现是前端的程序先遇到瓶颈。
3. 搭建分布式系统,搭建在线Docker集群, 所有业务共享备用的Docker 集群资源,这样可以极大的避免每个业务都预留资源,但是实际上流量没有增长造成的浪费。

 

结语:我们的挑战都一样,就是数据量,bigger and bigger,用户体验是faster and faster,业务是more and more。

 

总结: 

1. 面向服务架构(不限开发语言)
2. 有状态服务改为无状态接口服务(便于分布式部署)
3. 海量数据分片,分库,分表(阿里云RDS开启读写分离)
4. 前端静态资源做CDN中转
5. 最终硬件瓶颈(CPU、内存、存储、网络)
6. 日志服务化(把分布在不同机器上的日志关联起来的唯一且有效的办法)
7. 对请求入口做负载均衡后再到达应用层

 

个人总结-大数据高并发场景数据库方便解决方案


场景评估:用户量估计1亿,日数据量几千万,总日志数据几亿条
第一期
1,垂直字段拆分,大表拆分小表base+extent
2,使用内存数据库Redis存放热门数据以提高性能和减少数据库负载
3,优化索引设计,查询分析优化
4,优化数据库配置文件
5,使用MySQL 8,提高性能
6,读写分离,数据库主从配置,降低数据库锁的频率,提高数据库总体性能
7,升级硬件,使用固态硬盘和高频率处理器提升MySQL的IO性能和数据处理能力
第二期
1,水平拆分,单库水平拆分表,可拆分99个表,每表一千万,一共支持10亿条数据。考虑联合查询问题,增加冗余字段,设计关联关系映射索引表,自增长起始编号累加
2,采用微服务思维,在业务层面上垂直切分,将不相关的业务的数据库分隔,每个库只承担业务的一部分数据,这样整体的可用性就能提高。比如商品库,用户库,订单库,日志库,统计库,归档库等。
3,前后台数据库分离,冷热分离,每天定时抽取数据同步
4,使用Sphinx搜索引擎

当数据量很庞大的时候,尽量避免COUNT等操作!一定要的话也可以选择计算粗略值

 

参考文章:

https://www.cnblogs.com/soundcode/p/5590710.html (保证分布式系统数据一致性的6种方案)
http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency (分布式系统事务一致性解决方案)
https://zhuanlan.zhihu.com/p/21994882 (分布式系统理论基础 - 一致性、2PC和3PC)
https://www.zhihu.com/question/50176389/answer/119724104 (网络游戏如何保证数据一致性?)
https://coolshell.cn/articles/10910.html (分布式系统的事务处理)
https://blog.csdn.net/zhoudaxia/article/details/38067003 (如何解决秒杀的性能问题和超卖的讨论)
http://www.cnblogs.com/wangrudong003/p/7111789.html (.NetCore+Jexus代理+Redis模拟秒杀商品活动)
http://www.cnblogs.com/zhenghui317/p/5577345.html (千万级规模高性能、高并发的网络架构经验)
http://mt.sohu.com/it/d20170403/131798804_255931.shtml (去哪儿网机票搜索系统的高并发架构设计是怎样的?)
http://blog.csdn.net/xiaemperor/article/details/38234979 (NodeJS优缺点及适用场景讨论)
http://www.cnblogs.com/dinglang/p/6133501.html (缓存在高并发场景下的常见问题)
http://blog.csdn.net/qq_34341290/article/details/53316173 (高并发抢购思路)
http://blog.csdn.net/jimlong/article/details/47805047 (PHP解决抢购、秒杀、抢楼、抽奖等阻塞式高并发库存防控超量的思路方法)
http://www.jb51.net/article/100050.htm (php结合redis实现高并发下的抢购、秒杀功能的实例)

 

版权声明:本文采用署名-非商业性使用-相同方式共享(CC BY-NC-SA 3.0 CN)国际许可协议进行许可,转载请注明作者及出处。
本文标题:高并发高性能场景(抢购、秒杀、抢票、限时竞答)解决方案
本文链接:http://www.cnblogs.com/sochishun/p/7003190.html
本文作者:SoChishun (邮箱:14507247#qq.com | 博客:http://www.cnblogs.com/sochishun/)
发表日期:2017年6月13日

posted on 2017-06-13 19:55  sochishun  阅读(7323)  评论(0编辑  收藏  举报