02 - 电商平台(微服务架构)¶
目标: 掌握微服务架构,能设计高并发电商系统
时间: 8-12周
难度: ⭐⭐⭐⭐⭐
🎯 项目概述¶
业务场景¶
技术架构¶
Text Only
前端:
- React + TypeScript
- Redux Toolkit + RTK Query
- Ant Design Pro
后端(微服务):
- API Gateway: Kong / Spring Cloud Gateway
- 用户服务: Go / Java Spring Boot
- 商品服务: Go / Java Spring Boot
- 订单服务: Go / Java Spring Boot
- 库存服务: Go / Java Spring Boot
- 支付服务: Go / Java Spring Boot
- 搜索服务: Elasticsearch
- 推荐服务: Python + TensorFlow
基础设施:
- 数据库: MySQL(主从)+ Redis Cluster
- 消息队列: RabbitMQ / Kafka
- 缓存: Redis Cluster
- 搜索引擎: Elasticsearch
- 容器化: Docker + Kubernetes
- 监控: Prometheus + Grafana
📚 服务拆分¶
服务划分原则¶
Text Only
按业务领域拆分:
1. 用户服务 (User Service)
- 用户注册/登录
- 用户信息管理
- 权限管理
2. 商品服务 (Product Service)
- 商品信息管理
- 商品分类
- 商品搜索
3. 订单服务 (Order Service)
- 订单创建
- 订单状态管理
- 订单查询
4. 库存服务 (Inventory Service)
- 库存管理
- 库存扣减/释放
- 库存预警
5. 支付服务 (Payment Service)
- 支付处理
- 退款处理
- 支付状态查询
6. 购物车服务 (Cart Service)
- 购物车管理
- 购物车合并
7. 搜索服务 (Search Service)
- 商品搜索
- 搜索建议
- 筛选过滤
8. 推荐服务 (Recommendation Service)
- 个性化推荐
- 热门商品
- 相关推荐
9. 通知服务 (Notification Service)
- 短信通知
- 邮件通知
- 站内信
🏗️ 核心功能实现¶
1. 用户服务¶
Go
// user-service/main.go
package main
import (
"time"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey"`
Username string `gorm:"uniqueIndex;size:50"`
Email string `gorm:"uniqueIndex;size:100"`
Password string `gorm:"size:255"`
Phone string `gorm:"size:20"`
Status int `gorm:"default:1"`
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
// 连接数据库
dsn := "user:password@tcp(127.0.0.1:3306)/user_db?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移
db.AutoMigrate(&User{})
r := gin.Default()
// 注册
r.POST("/api/v1/users/register", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// 密码加密
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
user.Password = string(hashedPassword)
result := db.Create(&user)
if result.Error != nil {
c.JSON(500, gin.H{"error": result.Error.Error()})
return
}
c.JSON(201, gin.H{
"id": user.ID,
"username": user.Username,
"email": user.Email,
})
})
// 登录
r.POST("/api/v1/users/login", func(c *gin.Context) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
var user User
result := db.Where("username = ?", req.Username).First(&user)
if result.Error != nil {
c.JSON(401, gin.H{"error": "Invalid credentials"})
return
}
// 验证密码
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
if err != nil {
c.JSON(401, gin.H{"error": "Invalid credentials"})
return
}
// 生成JWT
token := generateJWT(user.ID)
c.JSON(200, gin.H{
"token": token,
"user": gin.H{
"id": user.ID,
"username": user.Username,
},
})
})
r.Run(":8081")
}
2. 订单服务(分布式事务)¶
Go
// order-service/main.go
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/segmentio/kafka-go"
"gorm.io/gorm"
)
// Saga模式实现分布式事务
type OrderSaga struct {
db *gorm.DB
kafkaWriter *kafka.Writer
}
func (s *OrderSaga) CreateOrder(ctx context.Context, req CreateOrderRequest) error {
// 1. 创建订单(本地事务)
order := Order{
UserID: req.UserID,
TotalAmount: req.TotalAmount,
Status: "PENDING",
}
tx := s.db.Begin()
if err := tx.Create(&order).Error; err != nil {
tx.Rollback()
return err
}
// 2. 发送扣减库存消息
inventoryMsg := map[string]interface{}{ // interface定义行为契约
"order_id": order.ID,
"items": req.Items,
}
msgBytes, _ := json.Marshal(inventoryMsg)
err := s.kafkaWriter.WriteMessages(ctx, kafka.Message{
Key: []byte(fmt.Sprintf("order-%d", order.ID)),
Value: msgBytes,
Topic: "inventory-deduct",
})
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
// 库存扣减成功回调
func (s *OrderSaga) OnInventoryDeducted(ctx context.Context, orderID uint) error {
// 更新订单状态为已支付
return s.db.Model(&Order{}).Where("id = ?", orderID).Update("status", "PAID").Error
}
// 库存扣减失败补偿
func (s *OrderSaga) OnInventoryDeductFailed(ctx context.Context, orderID uint) error {
// 取消订单
return s.db.Model(&Order{}).Where("id = ?", orderID).Update("status", "CANCELLED").Error
}
3. 秒杀系统(高并发)¶
Go
// seckill-service/main.go
package main
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/redis/go-redis/v9"
"github.com/segmentio/kafka-go"
"gorm.io/gorm"
)
type SeckillService struct {
redisClient *redis.Client
db *gorm.DB
kafkaWriter *kafka.Writer
// 本地库存缓存
localStock map[string]int64
mu sync.RWMutex
}
// 预热库存到Redis
func (s *SeckillService) PreheatStock(productID string, stock int64) error {
key := fmt.Sprintf("seckill:stock:%s", productID)
return s.redisClient.Set(context.Background(), key, stock, 24*time.Hour).Err()
}
// 秒杀下单
func (s *SeckillService) Seckill(ctx context.Context, userID, productID string) (bool, error) {
// 1. 用户限流(一个用户只能秒杀一次)
userKey := fmt.Sprintf("seckill:user:%s:%s", productID, userID)
exists, err := s.redisClient.Exists(ctx, userKey).Result()
if err != nil || exists > 0 {
return false, fmt.Errorf("already participated")
}
// 2. 扣减Redis库存(Lua脚本保证原子性)
stockKey := fmt.Sprintf("seckill:stock:%s", productID)
luaScript := `
local stock = tonumber(redis.call('get', KEYS[1]))
if stock == nil or stock <= 0 then
return 0
end
redis.call('decr', KEYS[1])
return 1
`
result, err := s.redisClient.Eval(ctx, luaScript, []string{stockKey}).Result()
if err != nil || result.(int64) == 0 {
return false, fmt.Errorf("out of stock")
}
// 3. 标记用户已参与
s.redisClient.Set(ctx, userKey, 1, 24*time.Hour)
// 4. 异步创建订单(发送到消息队列)
orderMsg := map[string]string{
"user_id": userID,
"product_id": productID,
}
msgBytes, _ := json.Marshal(orderMsg)
// 发送到Kafka异步处理
s.kafkaWriter.WriteMessages(ctx, kafka.Message{
Value: msgBytes,
Topic: "seckill-order",
})
return true, nil
}
// 异步处理订单
func (s *SeckillService) ProcessSeckillOrder(ctx context.Context, msg kafka.Message) error {
var orderMsg map[string]string
json.Unmarshal(msg.Value, &orderMsg)
// 创建订单
order := Order{
UserID: orderMsg["user_id"],
ProductID: orderMsg["product_id"],
Status: "PAID", // 秒杀直接支付
}
return s.db.Create(&order).Error
}
🎯 项目检查点¶
- 完成所有服务的开发
- 实现分布式事务
- 完成秒杀功能
- 实现服务治理
- 完成监控告警
- 通过压力测试
这个项目完成后,你将掌握微服务架构的核心技能! 🚀