Skip to content

Ledger 系统架构设计

架构概述

Ledger 模块采用现代化的微服务架构设计,基于 清洁架构领域驱动设计 原则,确保系统的可扩展性、可维护性和可测试性。整个系统设计面向移动端应用场景,支持高并发、低延迟的服务需求。

核心设计原则

1. 清洁架构 (Clean Architecture)

  • 依赖倒置: 高层模块不依赖低层模块,双方都依赖抽象
  • 接口隔离: 面向接口编程,所有外部依赖通过接口抽象
  • 单一职责: 每个模块职责单一,边界清晰
  • 开闭原则: 对扩展开放,对修改封闭

2. 可测试性优先

  • 100% 可测试: 消除所有不可测试的代码层
  • 依赖注入: 通过 Wire 框架实现自动依赖注入
  • 接口抽象: 所有外部依赖都可被 Mock 替换
  • TDD 驱动: 测试驱动开发,保证代码质量

3. 高性能设计

  • 多级缓存: 本地缓存 + Redis 集群
  • 异步处理: 消息队列 + 工作池
  • 连接复用: 数据库和 Redis 连接池优化
  • 读写分离: 主从架构,查询性能优化

系统分层架构

核心组件设计

1. API 网关层

负责请求路由、限流、认证和负载均衡。

主要职责:

  • 请求路由和负载均衡
  • API 限流和熔断保护
  • 统一认证和授权
  • 请求日志和监控

技术选型:

  • 负载均衡: Nginx/Kong Gateway
  • 限流算法: 令牌桶 + 滑动窗口
  • 监控: Prometheus + Grafana
  • 日志: ELK Stack

2. 表现层 (Presentation Layer)

处理外部请求,协议转换和数据验证。

HTTP API Server (Gin)

go
// HTTP 服务器配置
type HTTPServer struct {
    engine     *gin.Engine
    middleware []gin.HandlerFunc
    config     *HTTPConfig
}

// 中间件链
func setupMiddleware() []gin.HandlerFunc {
    return []gin.HandlerFunc{
        middleware.Recovery(),
        middleware.Logger(),
        middleware.CORS(),
        middleware.RateLimiter(),
        middleware.Authentication(),
        middleware.RequestID(),
        middleware.Metrics(),
    }
}

gRPC API Server

go
// gRPC 服务器配置
type GRPCServer struct {
    server      *grpc.Server
    interceptors []grpc.UnaryServerInterceptor
    config      *GRPCConfig
}

// 拦截器链
func setupInterceptors() []grpc.UnaryServerInterceptor {
    return []grpc.UnaryServerInterceptor{
        recovery.UnaryServerInterceptor(),
        logging.UnaryServerInterceptor(logger),
        metrics.UnaryServerInterceptor(),
        tracing.UnaryServerInterceptor(),
        ratelimit.UnaryServerInterceptor(limiter),
        auth.UnaryServerInterceptor(authFunc),
    }
}

3. 应用层 (Application Layer)

协调领域对象,实现业务用例。

服务接口设计

go
// 账本服务接口
type LedgerService interface {
    CreateLedger(ctx context.Context, req *CreateLedgerRequest) (*Ledger, error)
    GetLedger(ctx context.Context, id string) (*Ledger, error)
    UpdateLedger(ctx context.Context, req *UpdateLedgerRequest) (*Ledger, error)
    DeleteLedger(ctx context.Context, id string) error
    ListLedgers(ctx context.Context, req *ListLedgersRequest) (*ListLedgersResponse, error)
}

// 交易服务接口
type TransactionService interface {
    CreateTransaction(ctx context.Context, req *CreateTransactionRequest) (*Transaction, error)
    GetTransaction(ctx context.Context, id string) (*Transaction, error)
    UpdateTransaction(ctx context.Context, req *UpdateTransactionRequest) (*Transaction, error)
    DeleteTransaction(ctx context.Context, id string) error
    ListTransactions(ctx context.Context, req *ListTransactionsRequest) (*ListTransactionsResponse, error)
    BatchCreateTransactions(ctx context.Context, req *BatchCreateTransactionsRequest) (*BatchCreateTransactionsResponse, error)
}

依赖注入配置

go
// Wire 依赖注入配置
//go:build wireinject
// +build wireinject

func InitializeLedgerService(
    config *Config,
    db *gorm.DB,
    redis redis.Cmdable,
    kafkaProducer *kafka.Producer,
) (*LedgerService, error) {
    wire.Build(
        // Repository 层
        repository.NewLedgerRepository,
        repository.NewTransactionRepository,
        repository.NewTagRepository,
        repository.NewBudgetRepository,
        
        // Service 层
        service.NewLedgerService,
        service.NewTransactionService,
        service.NewBudgetService,
        service.NewNotificationService,
        
        // Infrastructure 层
        cache.NewCacheManager,
        queue.NewMessageProducer,
        external.NewExternalServiceClient,
    )
    
    return &LedgerService{}, nil
}

4. 领域层 (Domain Layer)

包含业务逻辑和领域对象。

聚合根设计

go
// 账本聚合根
type Ledger struct {
    id          LedgerID
    name        string
    description string
    currency    Currency
    ownerID     UserID
    settings    LedgerSettings
    createdAt   time.Time
    updatedAt   time.Time
    version     int64 // 乐观锁版本号
}

// 业务方法
func (l *Ledger) UpdateSettings(settings LedgerSettings) error {
    l.settings = settings
    l.updatedAt = time.Now()
    l.recordEvent(NewLedgerSettingsUpdatedEvent(l.id, settings))
    
    return nil
}

// 交易聚合根
type Transaction struct {
    id              TransactionID
    ledgerID        LedgerID
    type_           TransactionType
    amount          Money
    description     string
    note            string
    tags            []Tag
    transactionDate time.Time
    createdAt       time.Time
    updatedAt       time.Time
    version         int64
}

// 业务方法
func (t *Transaction) UpdateAmount(newAmount Money) error {
    if newAmount.IsZero() {
        return ErrInvalidAmount
    }
    
    oldAmount := t.amount
    t.amount = newAmount
    t.updatedAt = time.Now()
    
    t.recordEvent(NewTransactionAmountChangedEvent(
        t.id, t.ledgerID, oldAmount, newAmount,
    ))
    
    return nil
}

领域事件设计

go
// 领域事件接口
type DomainEvent interface {
    EventID() string
    EventType() string
    AggregateID() string
    OccurredAt() time.Time
    Version() int
}

// 交易创建事件
type TransactionCreatedEvent struct {
    eventID       string
    transactionID string
    ledgerID      string
    amount        Money
    type_         TransactionType
    occurredAt    time.Time
    version       int
}

// 事件处理器
type TransactionEventHandler struct {
    budgetService    BudgetService
    notificationSvc  NotificationService
    analyticsService AnalyticsService
}

func (h *TransactionEventHandler) Handle(event DomainEvent) error {
    switch e := event.(type) {
    case *TransactionCreatedEvent:
        return h.handleTransactionCreated(e)
    case *TransactionUpdatedEvent:
        return h.handleTransactionUpdated(e)
    default:
        return nil
    }
}

5. 基础设施层 (Infrastructure Layer)

实现技术细节和外部依赖。

仓储模式实现

go
// 仓储接口
type LedgerRepository interface {
    Save(ctx context.Context, ledger *Ledger) error
    FindByID(ctx context.Context, id LedgerID) (*Ledger, error)
    FindByUserID(ctx context.Context, userID UserID) ([]*Ledger, error)
    Delete(ctx context.Context, id LedgerID) error
    Count(ctx context.Context, criteria *LedgerCriteria) (int64, error)
}

// GORM 实现
type gormLedgerRepository struct {
    db    *gorm.DB
    cache CacheManager
}

func (r *gormLedgerRepository) Save(ctx context.Context, ledger *Ledger) error {
    model := r.toModel(ledger)
    
    // 乐观锁检查
    result := r.db.WithContext(ctx).
        Where("id = ? AND version = ?", model.ID, model.Version-1).
        Updates(model)
    
    if result.RowsAffected == 0 {
        return ErrOptimisticLockConflict
    }
    
    // 更新缓存
    go r.cache.Set(r.cacheKey(ledger.ID()), ledger, time.Hour)
    
    return result.Error
}

缓存管理器

go
// 多级缓存管理
type CacheManager interface {
    Get(ctx context.Context, key string) (interface{}, error)
    Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error
    Delete(ctx context.Context, key string) error
    InvalidatePattern(ctx context.Context, pattern string) error
}

type multiLevelCacheManager struct {
    localCache  *bigcache.BigCache    // L1: 本地缓存
    redisCache  redis.Cmdable         // L2: 分布式缓存
    serializer  Serializer            // 序列化器
}

func (c *multiLevelCacheManager) Get(ctx context.Context, key string) (interface{}, error) {
    // L1: 本地缓存
    if data, err := c.localCache.Get(key); err == nil {
        return c.serializer.Deserialize(data)
    }
    
    // L2: Redis 缓存
    if data, err := c.redisCache.Get(ctx, key).Bytes(); err == nil {
        value, err := c.serializer.Deserialize(data)
        if err == nil {
            // 回写本地缓存
            go c.localCache.Set(key, data)
        }
        return value, err
    }
    
    return nil, ErrCacheMiss
}

中间件架构设计

基于 Kratos 框架的中间件设计模式:

中间件实现示例

go
// 限流中间件
func RateLimiterMiddleware(limiter ratelimit.Limiter) gin.HandlerFunc {
    return func(c *gin.Context) {
        userID := getUserID(c)
        key := fmt.Sprintf("user:%s", userID)
        
        if !limiter.Allow(key) {
            c.JSON(http.StatusTooManyRequests, gin.H{
                "error": "rate limit exceeded",
                "retry_after": limiter.RetryAfter(key),
            })
            c.Abort()
            return
        }
        
        c.Next()
    }
}

// 熔断中间件
func CircuitBreakerMiddleware(breaker circuitbreaker.CircuitBreaker) gin.HandlerFunc {
    return func(c *gin.Context) {
        err := breaker.Execute(func() error {
            c.Next()
            
            if c.Writer.Status() >= 500 {
                return fmt.Errorf("server error: %d", c.Writer.Status())
            }
            return nil
        })
        
        if err != nil {
            if errors.Is(err, circuitbreaker.ErrOpenState) {
                c.JSON(http.StatusServiceUnavailable, gin.H{
                    "error": "service temporarily unavailable",
                })
            }
        }
    }
}

数据流架构

部署架构

性能特性

1. 吞吐量目标

  • HTTP API: 5,000 QPS (单实例 1,500 QPS)
  • gRPC API: 10,000 QPS (单实例 3,000 QPS)
  • 数据库写入: 2,000 TPS
  • 缓存读取: 50,000 OPS

2. 延迟目标

  • API 响应时间: P99 < 200ms
  • 数据库查询: P95 < 50ms
  • 缓存访问: P99 < 5ms
  • 消息队列延迟: < 10ms

3. 可用性目标

  • 服务可用性: 99.9% (8.76小时/年)
  • 数据持久性: 99.999999999% (11个9)
  • 故障恢复时间: < 15分钟
  • 数据备份: 每小时备份,保留30天

扩展性设计

1. 水平扩展

  • 无状态服务: 所有服务都设计为无状态,支持自动扩缩容
  • 数据分片: 支持按用户ID或账本ID进行数据分片
  • 缓存分布: Redis 集群支持数据分布和故障转移
  • 消息队列: Kafka 分区支持消息并行处理

2. 垂直扩展

  • 服务拆分: 支持按业务功能拆分为独立微服务
  • 数据库分离: 读写分离,按业务拆分数据库
  • 专用缓存: 不同业务使用独立的缓存实例
  • 异步解耦: 通过消息队列实现服务间异步通信

3. 地理分布

  • 多区域部署: 支持跨区域部署和数据同步
  • CDN 加速: 静态资源通过 CDN 分发
  • 就近路由: 根据用户地理位置路由到最近的服务节点
  • 数据合规: 支持数据本地化存储要求

安全架构

1. 网络安全

  • TLS 加密: 所有外部通信使用 TLS 1.3
  • VPC 隔离: 服务部署在私有网络中
  • 防火墙: 严格的入站和出站规则
  • DDoS 防护: 云厂商 DDoS 防护服务

2. 应用安全

  • 身份认证: JWT Token + Refresh Token 机制
  • 权限控制: RBAC 基于角色的访问控制
  • API 限流: 多维度限流策略
  • 输入验证: 严格的参数验证和 SQL 注入防护

3. 数据安全

  • 加密存储: 敏感数据 AES-256 加密
  • 访问审计: 完整的数据访问日志
  • 备份加密: 备份数据加密存储
  • 数据脱敏: 开发测试环境数据脱敏

监控和可观测性

1. 指标监控

  • 业务指标: 交易量、用户活跃度、预算使用率
  • 技术指标: QPS、延迟、错误率、资源使用率
  • 基础设施: CPU、内存、磁盘、网络使用情况
  • 告警机制: 基于阈值和趋势的智能告警

2. 日志管理

  • 结构化日志: JSON 格式的结构化日志
  • 链路追踪: 分布式请求链路追踪
  • 集中收集: ELK Stack 日志聚合分析
  • 日志分级: ERROR、WARN、INFO、DEBUG 分级

3. 链路追踪

  • 分布式追踪: Jaeger 全链路追踪
  • 性能分析: 请求耗时分解和瓶颈识别
  • 依赖分析: 服务依赖关系图谱
  • 错误诊断: 异常请求快速定位

质量保证

1. 代码质量

  • 代码覆盖率: > 90%
  • 静态检查: golint、go vet、gosec
  • 代码审查: 强制 PR Review
  • 文档同步: 代码变更同步更新文档

2. 测试策略

  • 单元测试: 所有业务逻辑单元测试
  • 集成测试: API 和数据库集成测试
  • 性能测试: 压力测试和基准测试
  • 安全测试: 渗透测试和安全扫描

3. 持续集成

  • 自动构建: 代码提交自动触发构建
  • 自动测试: 构建后自动运行测试套件
  • 自动部署: 测试通过后自动部署到测试环境
  • 回滚策略: 部署失败自动回滚

这个架构设计确保了 Ledger 模块具备工业级的可靠性、性能和可维护性,为移动端财务管理应用提供稳定可靠的后端服务支撑。

基于 MIT 许可证发布