高并发性能调优
原来写了一些关于性能优化的,这次根据新学习的知识做一些补充。
首先看一下牛客给的答案:
1、提高CPU并发计算能力
(1)多进程&多线程
(2)减少进程切换,使用线程,考虑进程绑定CPU
(3)减少使用不必要的锁,考虑无锁编程
(4)考虑进程优先级
(5)关注系统负载
2、改进I/O模型
(1)DMA技术
(2)异步I/O
(3)改进多路I/O就绪通知策略,epoll
(4)Sendfile
(5)内存映射
(6)直接I/O
1、硬件设施
集群:多个服务器,每个服务器配备多个cpu;
磁盘:大容量磁盘;
服务器升级;
2、并发用户
是指同一时刻于服务器进行交互的在线用户数量,交互就是进行数据的传输和访问;
1 )进行负载均衡;
Nginx实现负载均衡。Nginx基于进程fork,为每个连接fork一个单独的进程处理,不需要加锁。
2)数据库集群、库表散列
也就是分库分表。
应用程序中的业务和功能模块不同而将数据库进行分离,不同模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,例如用户表,按照用户ID进行表散列,能够降低成本提升系统的性能和扩展性。
4)图片服务器分离
图片与界面分离,独立使用图片服务器,降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问而崩溃。
5)镜像
镜像解决不同网络接入商和地域带来的用户访问速度差异,数据进行定时更新或者实时更新。
6)缓存
Java开发就可以调用MemoryCache对一些数据进行缓存和通讯共享。
数据存到Redis进行缓存。
7)HTML静态化
静态化可以实现高效、消耗小,实现避免大量数据库访问请求;
采用HttpClient页面静态化技术对首页进行信息的缓存,HttpClient直接把jsp页面的数据拿过来以流的形式生成静态页面。
8)禁止外部盗链:外部网站的图片或者文件岛链往往带来大量的负载压力,因此应严格限制外部对自身图片或者文件的盗链;
8) CDN加速技术
9)异步读取,异步编程
10)创建线程池,数据持久化
11)拆分业务,多个线程完成一个事情
12)优化IO读写机制
13)优化数据库存储
14)优化数据库
A、数据库读写分离
大多数数据库读多写少。实现读写分离。mycat中间件对数据库进行读写分离,一般两个主负责写,从负责读。
主数据库处理事务的增删改操作,从数据库处理select;
B、添加索引
添加相关索引,减少查询使用null进行查询,少用 !<>查询,索引失效会进行全局搜索;
3、重启与过载保护
如果系统出现崩溃,贸然重启可能导致更长时间的预热;
秒杀和抢购的场景,就需要过载保护,如果检测到系统满负载状态,拒绝请求也是一种保护措施。将过载保护设置再CGI入口处,快速将用户请求进行返回。
4、作弊手段:进攻和防守
秒杀和抢购中的海量请求,实际由很多事刷票工具,或者其他的自动请求脚本,这种作弊手段需要考虑
1)同一个账户,一次性多个请求
一次性上百甚至更多请求,实际是破坏性访问。多个并发请求通过负载均衡服务器,分配到内网多台web服务器,首先向存储发送查询请求,然后在,某个请求成功写入记录的时间差内,其他请求获取查询到的结果都是“没有次记录”,这里就存在问题。
应对:程序入口,一个账户只允许接受1个请求,其他请求过滤。通过Redis内存缓存服务,写入一个标志位(只允许一个请求写成功,再加上乐观锁)。或者同一个账户的请求放入一个队列中,处理完一个,才能下一个。
2)多个账户,一次性多个请求
通过注册大量账户来获得概率提升;
应对:检测指定机器IP请求频率,发现高频IP,弹出验证码,或者直接禁用;
A、弹出验证码,有效防止自动脚本的识别;
B、禁止IP,可能会出现错误判断;
3)多个账户,不同IP发送不同请求
做成随机IP服务。
应对:和真实用户请求基本一致,通过设置业务门槛来限制这种请求,或者账户行为的“数据挖掘”来提前清理这些数据。
一般僵尸账户一般连号,活跃度不高,等级低,资料不齐全等等。设置相应的门槛,来进行清理。
5、高并发下数据安全
MySQL数据库自带锁机制,大规模并发场景,不推荐使用MySQL。
1)悲观锁
修改数据的时候,采取锁定状态,排斥外在请求的修改,如果遇到加锁状态就必须等待;但是高并发中,可能出现一直等待,多个连接增大响应时间,陷入异常。
2)FIFO队列
采用先进先出原则,但是高并发下,可能队列瞬间满了,也会陷入异常,设计极大的队列,但是如果用户量过大,也会导致异常;
3)乐观锁
采用版本号更新,这个数据所有请求都有资格修改,但是会获得一个该数据的版本号,只有版本号渡河才能修改更新,其他则返回抢购识别。不过增加了CPU的计算开销,但是相对较好的解决方案。
还没有评论,来说两句吧...