代购转运系统崩了三次后,我学到的 SLA 设计教训

举报
云上老码农 发表于 2026/05/28 12:10:04 2026/05/28
【摘要】 双十一凌晨支付回调全挂,根源不是技术问题而是 SLA 设计缺陷。文章总结三个教训:单点架构扛不住故障、不做限流会被 1688 封 IP、汇率无缓冲利润一晚上亏光。附 PHP 限流队列和汇率缓冲检测代码实现。核心观点:SLA 要写在代码里,降级比完美重要,监控比开发优先。

去年双十一,凌晨两点,手机震了。

不是订单提醒——是报警群。代购转运系统的支付回调全挂了。我翻了个身,没继续睡。因为我知道,这一翻,可能就是几万块的损失。

那是我做代购系统第三年,自认为系统够稳了。结果 1688 的 API 签名算法一过期,十几个订单卡在“已支付未采购”状态。客户在群里 @我,客服电话被打爆。最惨的是,有个客户囤了十几单的日用品,等着转运到东京,结果系统卡了两天。

后来复盘,发现根本不是技术问题,是 SLA 设计的问题。

第一个教训:别把单点当高可用

我们最早的系统架构很简单:一台服务器跑所有服务,数据库也在一台机器上。当时觉得,代购转运嘛,又不是银行,崩了就重启呗。

结果有次服务器硬盘坏了,数据恢复花了三天。那三天,客户在群里骂,我们在机房哭。

后来学乖了:数据库做主从,应用层做负载均衡,关键服务做冗余。但最核心的教训是——别等出事了才想高可用,成本不是问题,信任才是。

第二个教训:API 限流不是限制,是保护

做代购转运,最怕的就是 1688 接口限流。有次我们一个活动,瞬间涌入几百单,系统疯狂调 1688 的采购接口。结果 1688 直接把我们 IP 封了,所有订单都卡在“采购中”。

那之后我们做了个简单的限流队列:每秒最多调 10 次接口,超出的排队。虽然下单慢了点,但至少不会全崩。

就像餐厅后厨的动线设计,以前靠经验,现在靠系统规划。订单管理也是一个道理。

第三个教训:汇率缓冲不是可有可无

这个教训最贵。

有次日元突然升值,我们没做汇率缓冲,所有订单的利润直接被吃掉。客户按之前的汇率付款,我们按新的汇率采购,一单亏几十块。几百单下来,一个月白干。

后来在系统里加了汇率缓冲机制:设置一个汇率波动范围,超出范围自动暂停下单,通知人工确认。虽然偶尔会延迟,但至少不亏钱。

现在怎么做

后来上了套系统,对账不用熬夜了。叫什么不重要,好用就行。

但核心还是那几个原则:

  1. SLA 不是写在纸上的,是写在代码里的——99.9%的可用性,意味着一年只能崩 8 小时。你算过自己系统能撑多久吗?

  2. 降级比完美更重要——支付回调失败?先让订单进入待处理队列,别让客户干等。采购接口限流?先保存订单,等恢复后自动重试。

  3. 监控比开发更重要——没有报警的系统,等于没有保险的车。你永远不知道什么时候会出事。

技术实现的几个关键点

// 简单的限流队列实现
class RateLimiter
{
    private int $maxCalls;
    private int $period;
    private array $calls = [];

    public function __construct(int $maxCalls = 10, int $period = 1)
    {
        $this->maxCalls = $maxCalls;
        $this->period = $period;
    }

    public function canCall(): bool
    {
        $now = time();
        // 清理过期记录
        $this->calls = array_filter($this->calls, fn($t) => $t > $now - $this->period);
        if (count($this->calls) < $this->maxCalls) {
            $this->calls[] = $now;
            return true;
        }
        return false;
    }
}
// 汇率缓冲检测
function checkExchangeRateBuffer(float $currentRate, float $baseRate, float $bufferPercent): array
{
    $diff = abs($currentRate - $baseRate) / $baseRate * 100;
    if ($diff > $bufferPercent) {
        return [
            'status' => 'paused',
            'message' => "汇率波动超过{$bufferPercent}%,需人工确认",
            'currentRate' => $currentRate,
            'baseRate' => $baseRate,
        ];
    }
    return [
        'status' => 'normal',
        'message' => '汇率在安全范围内',
    ];
}

最后说一句

晚上十点,你刚躺下,手机震了。现在——你翻个身,继续睡。

能做到这一点的系统,才是好系统。

关于作者

老张,十年跨境系统架构师。做过代购转运、反向海淘、跨境支付。踩过的坑比写过的代码多。现在主要研究如何让系统少崩几次,让自己多睡几小时。

本文首发于华为云开发者社区,内容仅代表作者个人经验分享。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。