电商系统架构设计:从单体到微服务

0 阅读2分钟

核心模块

模块功能
用户中心注册、登录、个人信息
商品中心商品管理、分类、SKU
订单中心下单、支付、退款
库存中心库存管理、扣减、预占
支付中心支付渠道、回调、对账
营销中心优惠券、满减、秒杀

单体架构

├── app/
│   ├── Http/Controllers/
│   │   ├── UserController.php
│   │   ├── ProductController.php
│   │   ├── OrderController.php
│   │   └── PaymentController.php
│   ├── Models/
│   ├── Services/
│   └── Repositories/
├── database/
└── routes/

适用场景:  初创期,日订单 < 1 万

微服务架构

                    ┌─────────────┐
                    │   Gateway   │
                    └──────┬──────┘
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
   ┌──────────┐     ┌──────────┐     ┌──────────┐
   │ 用户服务  │     │ 商品服务  │     │ 订单服务  │
   └────┬─────┘     └────┬─────┘     └────┬─────┘
        │                │                │
   ┌────▼─────┐     ┌────▼─────┐     ┌────▼─────┐
   │  MySQL   │     │  MySQL   │     │  MySQL   │
   └──────────┘     └──────────┘     └──────────┘

数据库设计

用户表

CREATE TABLE users (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    phone VARCHAR(20UNIQUE,  
    password VARCHAR(255),  
    nickname VARCHAR(50),  
    avatar VARCHAR(255),  
    status TINYINT DEFAULT 1,  
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP  
);

商品表

CREATE TABLE products (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    name VARCHAR(200),  
    category_id INT,  
    brand_id INT,  
    price DECIMAL(10,2),  
    market_price DECIMAL(10,2),  
    stock INT DEFAULT 0,  
    sales INT DEFAULT 0,  
    status TINYINT DEFAULT 1,  
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,  
    INDEX idx_category (category_id),  
    INDEX idx_status_sales (status, sales)  
);  
  
CREATE TABLE product_skus (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    product_id BIGINT,  
    specs JSON,  
    price DECIMAL(10,2),  
    stock INT DEFAULT 0,  
    INDEX idx_product (product_id)  
);

订单表

CREATE TABLE orders (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    order_no VARCHAR(32UNIQUE,  
    user_id BIGINT,  
    total_amount DECIMAL(10,2),  
    pay_amount DECIMAL(10,2),  
    discount_amount DECIMAL(10,2DEFAULT 0,  
    status TINYINT DEFAULT 0,  
    pay_time TIMESTAMP NULL,  
    ship_time TIMESTAMP NULL,  
    finish_time TIMESTAMP NULL,  
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,  
    INDEX idx_user (user_id),  
    INDEX idx_status (status),  
    INDEX idx_created (created_at)  
);  
  
CREATE TABLE order_items (  
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  
    order_id BIGINT,  
    product_id BIGINT,  
    sku_id BIGINT,  
    product_name VARCHAR(200),  
    sku_specs JSON,  
    price DECIMAL(10,2),  
    quantity INT,  
    INDEX idx_order (order_id)  
);

下单流程

1. 校验商品和库存
2. 计算价格(优惠券、满减)
3. 预扣库存
4. 创建订单
5. 发送延迟消息(超时取消)
6. 返回支付信息

代码实现


<?php  
class OrderService  
{  
    public function create(int $userId, array $items, ?int $couponId = null): Order  
    {  
        return DB::transaction(function () use ($userId, $items, $couponId) {  
            // 1. 校验商品  
            $products$this->validateProducts($items);  
              
            // 2. 预扣库存  
            foreach ($items as $item) {  
                $locked$this->inventoryService->lock(  
                    $item['sku_id'],  
                    $item['quantity']  
                );  
                if (!$locked) {  
                    throw new Exception('库存不足');  
                }  
            }  
              
            // 3. 计算价格  
            $amounts$this->calculateAmount($products, $items, $couponId);  
              
            // 4. 创建订单  
            $order = Order::create([  
                'order_no' => $this->generateOrderNo(),  
                'user_id' => $userId,  
                'total_amount' => $amounts['total'],  
                'discount_amount' => $amounts['discount'],  
                'pay_amount' => $amounts['pay'],  
                'status' => OrderStatus::PENDING  
            ]);  
              
            // 5. 创建订单项  
            foreach ($items as $item) {  
                $product = $products[$item['product_id']];  
                OrderItem::create([  
                    'order_id' => $order->id,  
                    'product_id' => $item['product_id'],  
                    'sku_id' => $item['sku_id'],  
                    'product_name' => $product->name,  
                    'price' => $product->price,  
                    'quantity' => $item['quantity']  
                ]);  
            }  
              
            // 6. 发送延迟消息  
            $this->mq->publishDelayed('order_timeout', [  
                'order_id' => $order->id  
            ], 30 * 60 * 1000);  
              
            return $order;  
        });  
    }  
      
    private function generateOrderNo(): string  
    {  
        return date('YmdHis') . str_pad(mt_rand(1999999), 6'0', STR_PAD_LEFT);  
    }  
}

库存扣减

方案对比

方案优点缺点
下单减库存简单恶意下单占库存
支付减库存不占库存超卖风险
预扣库存平衡实现复杂

预扣库存实现

<?php  
class InventoryService  
{  
    // 预扣库存  
    public function lock(int $skuId, int $quantity): bool  
    {  
        $key"inventory:lock:{$skuId}";  
          
        // Lua 脚本保证原子性  
        $script = <<<LUA  
        local stock = redis.call('hget', KEYS[1], 'stock')  
        local locked = redis.call('hget', KEYS[1], 'locked')  
        if tonumber(stock) - tonumber(locked) >= tonumber(ARGV[1]) then  
            redis.call('hincrby', KEYS[1], 'locked', ARGV[1])  
            return 1  
        end  
        return 0  
        LUA;  
          
        return (bool) Redis::eval($script, 1$key$quantity);  
    }  
      
    // 确认扣减(支付成功)  
    public function confirm(int $skuId, int $quantity): void  
    {  
        $key = "inventory:lock:{$skuId}";  
        Redis::hincrby($key, 'stock', -$quantity);  
        Redis::hincrby($key, 'locked', -$quantity);  
          
        // 同步到数据库  
        ProductSku::where('id'$skuId)->decrement('stock'$quantity);  
    }  
      
    // 释放库存(取消/超时)  
    public function release(int $skuId, int $quantity): void  
    {  
        $key = "inventory:lock:{$skuId}";  
        Redis::hincrby($key, 'locked', -$quantity);  
    }  
}

订单状态机

待支付 ──支付成功──▶ 已支付 ──发货──▶ 已发货 ──确认收货──▶ 已完成
  │                    │
  │超时/取消           │退款
  ▼                    ▼
已取消               已退款



<?php
class OrderStatus
{
    const PENDING0;   // 待支付
    const PAID1;      // 已支付
    const SHIPPED2;   // 已发货
    const COMPLETED3// 已完成
    const CANCELLED4// 已取消
    const REFUNDED5;  // 已退款
    
    public static function canTransition(int $from, int $to): bool
    {
        $transitions = [
            self::PENDING => [self::PAIDself::CANCELLED],
            self::PAID => [self::SHIPPEDself::REFUNDED],
            self::SHIPPED => [self::COMPLETEDself::REFUNDED],
        ];
        
        return in_array($to, $transitions[$from] ?? []);
    }
}

总结

模块关键点
商品SKU 设计、库存同步
订单状态机、幂等性
库存预扣机制、Redis + DB
支付异步回调、对账

电商系统是综合性很强的项目,后续会深入讲解支付、秒杀等模块。