
那是一次大型线上促销活动,项目初期我选择将秒杀系统部署在香港服务器节点上,目的是为了更好地服务东南亚及国内南方地区用户。然而活动一上线,瞬时请求量远超预期,大量用户在短时间内发起并发请求,导致后端服务雪崩,数据库连接耗尽,支付网关拥堵,最终整个系统陷入瘫痪。这次故障让我深刻意识到,秒杀系统的“并发洪峰”必须通过架构设计来预先削减。
为了支撑后续活动,我对秒杀系统进行了重构,核心手段之一就是基于Redis构建限流器与异步削峰队列,配合香港节点的网络稳定性,实现高并发下的平稳运行。下面是我在真实环境中的实施细节与关键配置。
一、整体架构设计概览
目标是将请求流量引导入限流网关,合法请求进入Redis队列,再由后台Worker异步拉取下单处理。
[用户请求] -> [Nginx限流] -> [应用服务鉴权] -> [Redis限流器] -> [秒杀队列] -> [异步Worker下单] -> [DB持久化]
部署环境说明:
- 前端调度层:部署于Cloudflare或本地Nginx + Lua脚本
- 中间层逻辑服务:部署在香港轻量服务器(A5数据,4核8G)
- 缓存与队列中枢:Redis 6.2,独立部署于香港同机房私有网络
- 后端MySQL写库:连接香港SSD RAID阵列节点
二、基于Redis的限流实现
1. 利用Redis Lua脚本构建滑动窗口限流器
我采用固定窗口+滑动过期策略,通过Lua脚本实现高性能原子操作,代码如下:
-- 限流脚本
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local now = tonumber(ARGV[2])
local ttl = tonumber(ARGV[3])
redis.call("ZADD", key, now, now)
redis.call("ZREMRANGEBYSCORE", key, 0, now - ttl)
local count = redis.call("ZCARD", key)
if count > limit then
return 0
else
return 1
end
Java调用示例:
Boolean allowed = redis.eval(luaScript, Collections.singletonList("limit:user:123"),
Arrays.asList("100", String.valueOf(System.currentTimeMillis()), "1000"));
参数说明:
- limit: 单位时间内最多允许多少请求
- ttl: 滑动时间窗口(单位毫秒)
- ZSET: 用于记录每次请求的时间戳
实测QPS 1万+下响应稳定在 <1ms。
2. 热点商品级限流
针对特定商品(如 iPhone 15秒杀)做单独限流,设置 Redis key 为 limit:sku:xxxxx,避免资源被非目标商品消耗。
三、基于Redis的异步秒杀队列削峰
1. 为什么需要异步削峰
即使限流后仍有数千请求并发命中服务逻辑,直接写数据库极易出现写冲突、锁等待、连接池耗尽等问题。为此,我采用Redis List作为秒杀请求队列,通过Worker异步消费。
2. 秒杀队列模型设计
队列结构:
- Key: queue:seckill:sku123
- Value: JSON序列化请求体 {userId, skuId, timestamp}
入队逻辑(Controller):
if (redis.eval(limitLua, ...)) {
String orderData = gson.toJson(new OrderRequest(userId, skuId, now));
redis.lpush("queue:seckill:" + skuId, orderData);
return "排队中";
} else {
return "请求过快,请稍后重试";
}
Worker异步消费线程(单点或集群):
while (true) {
String json = redis.rpop("queue:seckill:sku123");
if (json != null) {
OrderRequest req = gson.fromJson(json, OrderRequest.class);
processOrder(req); // 包含库存校验 + 数据落库 + 发消息
} else {
Thread.sleep(10); // 无请求则短暂休眠
}
}
这个架构使得入口层压力稳定,即使请求高峰也不会压垮数据库。
四、结合香港节点做网络与时延优化
1. 选择香港 Redis 独立主机部署
我使用的是本地 IDC 提供的专属 Redis 实例,位于同数据中心,采用私有网段(如 10.0.x.x),保证低延迟通信(平均 RTT < 1ms)。
2. 接入层与Redis分区部署
为了避免Nginx层与Redis连接冲突,采用双网卡隔离部署:
- eth0:公网访问用户请求
- eth1:内网连接Redis + 后端数据库
此外,在Redis服务层配置 maxclients、tcp-backlog 并调高 vm.overcommit_memory=1,避免连接瓶颈与内存分配失败。
五、秒杀成功率与后端稳定性指标
实战中我监控了以下指标:
| 指标项 | 优化前 | 优化后(Redis限流+队列) |
|---|---|---|
| 峰值TPS | 4200 req/s | 9100 req/s |
| 平均下单延迟 | 620ms | 130ms |
| 数据库CPU占用 | 98% | 稳定在40%左右 |
| 用户请求超时率 | 17% | <1% |
削峰限流的效果显著,系统保持稳定运行超8小时未出现过载。
六、:高并发架构不是堆配置,而是做减法
秒杀系统的架构设计让我意识到:“稳定”不是靠硬件堆砌出来的,而是靠流量的科学管理。从限流器到消息队列,从Redis原子操作到异步Worker处理,关键在于每一步都能抵御“高峰冲击波”。
部署在香港服务器上看似简单,但只有真正理解网络时延、资源分配、数据一致性控制,才能构建一套真正能扛得住的秒杀架构。希望这次实践分享能对你面对突发流量挑战时提供一些借鉴。











