订单流程设计
订单流程图
- 如何在高并发下,保证数据的唯一性?例如某商品同时有上百个定单, 如何保证定单下单成功的同时,保证库存正确
我也是想的队列或者加锁,都是串行的方式,如果数据量再大,客服端可能就响应慢
以尝试将库存扣减和下单分开,下单可以先创建成中间态订单,异步减库存,减成功再改订单状态
。热点库存在扣减时可以累加减。减少并发。读写分离,读可以缓存,异步更新。
一致的呢 只是把一个动作改成了N个动作,可以分压
秒杀系统套路 读写分离 拆单 分流
按我们的观察,如果你只做hash查询与操作还可以没啥问题, 如果你做keys等等这种操作, 这就是噩梦。 所以阿里出了个什么规范
不允许这种操作就是这种道理。用的cluster模式
java 应用优化
- log42j 异步打日志
- 定位慢sql 优化代码逻辑
- 优化 jvm 参数
- 将Servlet容器变成Undertow
- http 换成 scoket (不太现实 php 调java) dubbo rpc 调用 :改动量过大
- 去除 springapplication componentscan 通过 @Bean @Import 方式 加载bean
- 去除 springboot 的 无用的 依赖 提高 应用加载速度
- 内网 交互 避免网络带来的影响 延迟 抖动 等
- 应用 单独部署 配置 高配服务器
优化方案
redis 缓存 近几天 订单 提高查询速度
缓存 穿透: 布隆 过滤器 缓存null 值
缓存雪崩: 事前 做高可用限流 服务降级 sentinel 热点参数 限流 等 方案
事中:
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
解决方案
缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
针对 Redis 服务不可用的情况:
- 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
- 限流,避免同时处理大量的请求。
针对热点缓存失效的情况:
- 设置不同的失效时间比如随机设置缓存的失效时间。
- 缓存永不失效。
缓存击穿
处理
2 把 java 代码分布式锁 改成 mq 队列 去 创建 订单流水 和减库存
通过 topic 的 队列数量 保证 半有序消息的 吞吐量 和 有序性
常见redis 用法
- 按prefix+活动+商品做key,值就是剩余库存数。下单时直接dec,当发现dec的返回值小于等于0说明没抢到。
抢到的再走下单的流程。
这就实现了redis的快速判断。
也有人按订单先成生成好,放在mysql里。其他信息是空的。然后把订单号放在redis的一个队列里,每次下单取一个订单号去update。这样数据库不会锁
php也可以查询按prefix+活动+商品做key这个值,发现少于0就别抢了。
无货状态最好是写在前端的js里,没货就别刷了。如果可以补货,一分钟才刷一次。
如果可能有货。也限制10秒才能刷一次。这样减少到服务端的流量。
基本原理就是在业务交易的链路上,层层堵截,缓存和卸载流量,让真正的流量跑到服务器和数据库去。让无用流量尽早返回。 - 高并发下 库存扣减
1 内存表分库分表
- 在 mysql Innodb 内核 热点 数据行 数据行合并 锁 ,减少行锁 时间
2 超高 并发下 redis 分桶
https://developer.aliyun.com/article/754897