服务器反应慢,秒杀设计

目录

服务器反应慢

线上服务器cup飙升,如果定位Java代码?

服务器变慢如何诊断处理?

线上接口负载剧增,快扛不住了,解决方法是什么?

秒杀设计

从全局角度如何设计一个秒杀系统

秒杀活动里遇到的问题

如何设计百万并发场景里的枪优惠券

如何设计春节抢红包的金额的算法。

如果设计订单超时自动取消

时间轮


服务器反应慢

线上服务器cup飙升,如果定位Java代码?

使用top命令找到CPU高的进程

使用SP-MP命令找到进程下CPU高的线程ID

printf命令把tid转换16进制数

使用jstack命令输出线程运行状态日志信息。

服务器变慢如何诊断处理?

CPU利用率

CPU利用率过高,说明服务器当前处理的指令比较多,当cup处理不过来的时候,指令执行效率就会下降,用户感觉程序处理变慢了。解决方法查看线上服务器cup飙升,如果定位Java代码。

CPU利用率过低,说明程序使用资源过低,可以增加线程数量提升程序性能。

磁盘io效率

程序运行过程里会直接或间接磁盘io操作,例如程序直接读写磁盘文件,或者依赖第三方组件对磁盘进程持久化存储,此时磁盘io效率就会对程序产生影响。

使用iostat命令查看,如果磁盘负载较高,可以针对性优化。例如,使用缓存减少io次数,使用顺序写代替随机写,减少寻址开销,使用mmap,减少内存拷贝次数

内存瓶颈

内存是一块临时存储数据的组件,所有CPU指令都需要在内存里读写,内存的合理使用减少程序和磁盘io的频率,减少网络io频率,提升io性能。

jvm对内存合理分配能够避免频繁的GC,当内存使用率高的时候,可以使用dump命令检查jvm内存,使用mat工具分析找出大对象,排查是否存在内存泄漏。如果堆内对象正常,可能是堆外内存被大量使用,这个时候使用pmap检查进程内存分配情况,如果CPU和内存使用正常,这时使用jstat查看cg日志,分析用户线程暂停时间,gc次数等指标.

线上接口负载剧增,快扛不住了,解决方法是什么?

增加缓存。因为增加缓存是解决系统性能问题的最快速,最高效的方案,他能够快速提升系统的吞吐量,但是需要修改源代码。零时的解决方案是增加节点,将程序部署到新的节点上,在流量入口增加限流和分发,但是增加节点会增加成本。

当接口负载扛不住的时候,可以优先增加缓存缓解负载压力,例如将读取频繁的数据写到缓冲区里,将动态页面静态化。如果压力还是很大,再增加限流策略,例如消息队列,如果压力过大,在考虑增加服务节点。

秒杀设计

从全局角度如何设计一个秒杀系统

秒杀是电商系统常见业务模式,为了吸引用户刺激消费而设计的一种促销活动。例如整点秒杀,单个商品秒杀。

特点,

1.瞬时流量大,秒杀活动结束后流量消失,所以不能用堆机器的方式提高QPS成本太高。QPS,queries per second,每秒能够发出的查询数量,是衡量服务器性能的指标,用来评估系统处理高并发的能力。

2.秒杀商品库存量少,但是抢购的人多。

3.在秒杀时间没有到之前,刷新量非常大,导致静态资源访问剧增。

秒杀活动前的准备工作,运营策划一场秒杀活动,盘点秒杀商品的库存,防止活动中出现资源没有准备好的情况,然后在秒杀中台创建秒杀活动,入录秒杀数据。使用缓存完成交互,例如库存数量,商品编号。业务方根据实际情况对秒杀活动进行评估,压力测试。

秒杀活动里遇到的问题

1.需要满足高并发,响应快,用户量很大,并发量很高,对服务的要求是抗的住并发。我们根据压力测试的结果,提前准备好服务器。测量tps瓶颈点,看看是否到达一个好的状态,在压测的过程里对,提前对代码薄弱点做优化。Redis数据预加载,配置专用mq,前端页面静态化,cdn加速,带宽扩展,服务器集群负载均衡配置。这样一套组合下来可以支持高并发场景里的快速响应。

2.防止超卖。因为秒杀的是精品,需要防止由于技术原因导致超卖,库存变负数。在秒杀活动之前把数据同步到Redis里,在开始活动的时候,用户进行抢购,我们通过操作Redis对商品库存进行减扣,把减扣的消息发送到消息队列里,之后交给具体的业务系统进行处理,例如,订单,支付服务等,在处理完成之后,再和MySQL数据库进行交互,完成库存减扣的数据同步。由于库存先从Redis更新再同步到数据库,如果同一个时间有多个用户抢单,就会减扣多个库存,当抢单的数量超过Redis的缓存的库存数量时,就出现了超卖问题。如何避免超卖问题?把减扣库存的操作,分2个步骤完成,判断库存是否充足和减库存,这2个动作使用lua脚本执行,保证这2个操作的原子性,避免超卖。

少买问题,库存减扣成功但是交易失败,导致用户购买失败,例如Redis减扣的库存,但是减扣成功的消息没有发送到业务系统进行后续处理,导致订单生成失败。如何解决?在消息队列里设计一个重试策略,例如,消息发送失败之后,再3次重试,如果超过重试次数消息发送还是没有成功,将消息持久化到磁盘,使用补偿机制来轮询,直到发送成功再进行后续的业务处理。

3.防止恶意刷单,防止机器人恶意抢单,导致真正的用户抢不到。使用限流解决。秒杀是一种很快就结束的活动,不用担心因为限流影响用户体验。限流具体有2种策略,1.用户ID限流 ,例如一个ID1s内只能请求10次 2.同一个IP地址限流,例如,一个IP地址最大只能请求10次。做了限流之后防止一些无效的请求发送的服务器,从而减轻服务器压力。隐藏秒杀的连接,避免爬虫爬取到,对秒杀连接进行加密处理,只有时间到了才可以真实连接。例如不能以递增的方式来构建URL,避免找到规律提前拼接好。

4.页面访问量大,提前将页面静态化。资源静态化将URL唯一化处理,对页面提前缓存,保证用户在请求url的时候,不再解析请求头和重组Http,直接找到静态资源返回即可,不与后台服务做数据交互,提高页面访问效率。另外可以将静态资源放在cdn上。cdn通过就近分发原理,可以提高资源的响应速度和命中率。还可以开启资源压缩减少传输数据量,提高速度。

5秒杀入口开关设计,活动开始之前把按钮隐藏或禁用,或者显示为秒杀倒计时,在秒杀活动开始前再开放,这样可以限制一些无效请求发送到后端,减轻的服务器流量压力。

6.订单的后续逻辑设置为异步。将秒杀成功的消息放入mq里,后续服务可以慢一些反馈给用户。

7.订单失败补偿。在用户秒杀成功后,必须保证订单处理一定成功,不能因为程序原因,导致订单丢失,我们使用mq方式进行驱动,如果消费失败,就发起重试,还需要有报警机制,保证及时监控到预警。

8.服务降级。由于技术或人为原因,导致秒杀价格设置错误。例如1元一个iPhone。这种情况我们需要及时止损,不再允许用户下单。提前设置好降级开关,通知用户,例如秒杀活动已经结束。出现了技术性错误,服务器出现故障,导致大量请求无法处理。这种情况是我们意料不到的。这个时候开启服务降级及时止损。虽然会造成一些投诉,但是我们可以通过手动补偿优惠券,红包等方式安抚用户。

如何设计百万并发场景里的枪优惠券

在618,双11期间,商家会在某个时间点发送大量优惠券。抢到优惠券之后,用户下单的时候,可以减扣支付金额。

抢券,在活动发布之前把优惠券的库存存储到Redis里面,之后抢券的整个过程和缓存交互。保证抢券的速度快。

业务效验

通用业务逻辑处理,优惠券是否在有效期内,是否在在本平台发放,用户是否具有领取权限。

个性业务逻辑处理,数据库交互,rpc交互,这些操作比较耗时。

把不耗时的业务逻辑放在前面,让他抵挡大部分请求,然后再进行耗时操作。例如,规定每个用户只能领取一次,在领券之前,判断用户是否重复领券,若没有领券,才能减扣优惠券的数量,将优惠券发送到用户账号。

重复领券,使用Redis的zset操作或者布隆过滤器,使用lua脚本保证这些操作的原子性。

扣减券的库存,因为一直有人在抢券,所以券的库存数量一直在发生变化,怎么同步到数据库?他是可以接受延迟的,可以使用定时任务定时读取Redis里的数据同步到数据库里。

追加券的库存,使用mq将追加的库存数量同步到Redis。

发送业务mq,在扣减库存成功之后,我们通过业务系统发送一条mq消息,交给后续业务进一步处理,例如,记录这个券被谁领取了,这样的业务可以设计成异步执行,因为可以接受延迟。

发券到账

如何设计春节抢红包的金额的算法。

春节的时候,平台推出的抢红包活动。抢红包的设计流程。

1.设置红包的总金额和红包个数

2.提前计算出每个红包的金额

3.分享红包,用户抢红包

抢红包和秒杀下单的场景类似。在红包发出去后,用户看到的是抢红包和晒红包的过程。抢到的红包类似在后台事先分配好一个商品。在我们发红包的时候,相当于发放了一个虚拟商品,也会生成一个订单。在生成订单之后,就会调用支付平台的支付接口。完成支付之后,红包就创建好了。每个红包有一个唯一的标识码,方便系统识别。

在红包发出去之前,系统根据设置好的红包个数和总金额,预先生成每个红包的金额,并且给每一个红包设置一个令牌。用户在抢红包的时候,只要读取计算好的结果即可。

这时可以把红包发送的微信群里,用户可以开始抢红包,例如100元10个红包,就会生成10个令牌,先抢到的用户获得一个令牌,并且获取一个对应的金额。

金额算法,随机法,二倍均值法,每次都从保底金额0.01元到最大值的区间取值。最大值=红包的剩余金额/剩余红包的个数*2,(0.01,m/n*2)

如果设计订单超时自动取消

使用时间轮来轮询超时订单,时间轮算法,采用环状数组+链表来管理延迟任务,计算出订单的超时时间,再加入时间轮里。

使用死信队列,利用mq里的延迟消息功能,为新的订单设置一个超时投递时间,再把消息发送的mq服务器。消息发送到mq服务器后不会立刻投递,到达延时时间后再投递,此时投递出去的消息相当于一个取消订单的通知。

时间轮

是一种用来存储定时任务的环状数组,工作原理,2部分组成,一个是环状数组,一个是遍历环状数组的指针。定义一个固定长度的环状数组,数组的每一个元素代表一个时间刻度,假设是1s,如果长度是8就代表8s,然后有一个指针按照顺时间方向无限循环遍历这个数组,每隔最小时间单位前进一个数组索引,这个指针转一圈代表8s,转2圈代表16s,数组里的的元素是用来存储定时任务的容器。当我们向时间轮里添加一个定时任务的时候,根据定时任务的执行时间计算出数组下标。有可能在某个时间刻度上存在多个定时任务,这时采用双向链表的方式存储。

当指针指向某个数组的时候,就会把这个数组里存储的任务取出来,遍历链表逐个执行里面的任务,如果某个定时任务的执行时间大于数组所表示的长度,使用一个圈数来表示该任务延迟执行时间。

使用时间轮管理定时任务的好处,

1.降低定时任务的添加和删除的时间复杂度,提高性能

2.保证每次执行定时任务的时间复杂度都是O1,在定时任务密集的情况下,性能好

缺点,对于执行时间严格的任务,时间轮不合适,因为时间轮算法的精度取决于最小时间单元的粒度,假设1s为一个时间刻度,那么小于1s的任务无法被时间轮调度。

相关推荐
凡人叶枫8 分钟前
Effective C++ 条款28:避免使用 handles 指向对象内部
linux·服务器·开发语言·c++·嵌入式开发
技术小结-李爽9 分钟前
【工具】Maven的下载、安装、使用
java·maven
AI帮小忙10 分钟前
Debian系linux操作系统里安装OpenClaw
linux·运维·debian
极创信息12 分钟前
Linux挖矿病毒深度清理实战教程,从进程隐藏、Rootkit驻留到彻底根除
java·大数据·linux·运维·安全·tomcat·健康医疗
努力成为AK大王17 分钟前
并发编程的核心挑战、优化方案与核心知识点总结
java·开发语言·数据库
云烟成雨TD21 分钟前
Agent Scope Java 2.x 系列【10】技能(Skill)
java·人工智能·agent
摇滚侠25 分钟前
SpringMVC 入门到实战 DispatcherServlet 源码解读 92-95
java·后端·spring·maven·intellij-idea
键盘歌唱家1 小时前
Spring AI 入门分享:它和“直接调 API“到底差在哪
java·人工智能·spring
志栋智能1 小时前
超自动化巡检剧本(Playbook):运维经验的数字化封装
运维·自动化
宸丶一1 小时前
Day 10:LangGraph - Agent 的图执行引擎
java·windows·python