# 技术架构文档 ## 概述 本文档描述用户管理系统的技术架构设计,包括系统架构、性能优化、缓存策略、数据库优化等,确保系统能够满足 PRD 要求的性能指标: - 支持 10 亿用户规模 - 支持 10 万级并发访问 - API 响应时间 P99 < 500ms - 系统可用性 99.99% --- ## 1. 系统架构 ### 1.1 整体架构 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 负载均衡层 │ │ (Nginx / HAProxy / LVS) │ └──────────────────────────────┬──────────────────────────────────────────┘ │ ┌──────────────────────┼──────────────────────┐ │ │ │ ┌───────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │ CDN 层 │ │ API 网关 │ │ WebSocket │ │ (静态资源) │ │ (路由/限流/鉴权) │ │ (实时通信) │ └────────────────┘ └────────┬────────┘ └─────────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ │ │ ┌───────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │ 应用服务层 │ │ 应用服务层 │ │ 应用服务层 │ │ (多实例) │ │ (多实例) │ │ (多实例) │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ 认证服务 │ │ │ │ 认证服务 │ │ │ │ 认证服务 │ │ │ │ 用户服务 │ │ │ │ 用户服务 │ │ │ │ 用户服务 │ │ │ │ 权限服务 │ │ │ │ 权限服务 │ │ │ │ 权限服务 │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ └───────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ └──────────────────────┼──────────────────────┘ │ ┌──────────────────────┼──────────────────────┐ │ │ │ ┌───────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │ 缓存层 │ │ 缓存层 │ │ 缓存层 │ │ (Redis 集群) │ │ (Redis 集群) │ │ (Redis 集群) │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ 本地缓存 │ │ │ │ 本地缓存 │ │ │ │ 本地缓存 │ │ │ │ 分布式 │ │ │ │ 分布式 │ │ │ │ 分布式 │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ └───────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ └──────────────────────┼──────────────────────┘ │ ┌──────────────────────┼──────────────────────┐ │ │ │ ┌───────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │ 数据库层 │ │ 数据库层 │ │ 数据库层 │ │ (主从复制) │ │ (主从复制) │ │ (主从复制) │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ 主库 │ │ │ │ 主库 │ │ │ │ 主库 │ │ │ │ 从库 1 │ │ │ │ 从库 1 │ │ │ │ 从库 1 │ │ │ │ 从库 2 │ │ │ │ 从库 2 │ │ │ │ 从库 2 │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ └────────────────┘ └─────────────────┘ └─────────────────┘ ``` ### 1.2 单机架构(SQLite) ``` ┌─────────────────────────────────────────┐ │ 用户管理系统 (单实例) │ │ │ │ ┌─────────────────────────────────┐ │ │ │ 应用服务 (Port 8080) │ │ │ │ ┌───────────────────────────┐ │ │ │ │ │ 本地缓存 (L1 Cache) │ │ │ │ │ │ - 用户信息 │ │ │ │ │ │ - 权限信息 │ │ │ │ │ │ - Token 黑名单 │ │ │ │ │ └───────────────────────────┘ │ │ │ │ ┌───────────────────────────┐ │ │ │ │ │ 认证/用户/权限服务 │ │ │ │ │ └───────────────────────────┘ │ │ │ └─────────────────────────────────┘ │ │ │ │ │ ┌───────────────┴───────────────┐ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────────┐ ┌──────────────┐│ │ │ SQLite DB │ │ 可选 Redis ││ │ │ (单文件存储) │ │ (L2 Cache) ││ │ └──────────────────┘ └──────────────┘│ └─────────────────────────────────────────┘ ``` ### 1.3 集群架构(PostgreSQL/MySQL) ``` ┌─────────────────────────────────────────────────────────────────┐ │ 负载均衡 (Nginx) │ └────────────────────────┬────────────────────────────────────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ┌───────▼────────┐ ┌────▼────────┐ ┌─────▼────────┐ │ 应用实例 1 │ │ 应用实例 2 │ │ 应用实例 N │ │ (8080) │ │ (8080) │ │ (8080) │ │ ┌──────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ │ 本地缓存 │ │ │ │ 本地缓 │ │ │ │ 本地缓 │ │ │ │ L1 Cache │ │ │ │ 存 L1 │ │ │ │ 存 L1 │ │ │ └──────────┘ │ │ └────────┘ │ │ └────────┘ │ └───────┬────────┘ └────┬────────┘ └─────┬────────┘ │ │ │ └───────────────┼────────────────┘ │ ┌───────────────┴───────────────┐ │ │ ┌───────▼────────┐ ┌──────────▼────────┐ │ Redis 集群 │ │ PostgreSQL 集群 │ │ (L2 Cache) │ │ ┌─────────────┐ │ │ ┌──────────┐ │ │ │ 主库 │ │ │ │ Master │ │ │ │ (写) │ │ │ │ 哨兵 │ │ │ └─────────────┘ │ │ └──────────┘ │ │ ┌─────────────┐ │ │ ┌──────────┐ │ │ │ 从库 1 │ │ │ │ Slave 1 │ │ │ │ (读) │ │ │ └──────────┘ │ │ └─────────────┘ │ │ ┌──────────┐ │ │ ┌─────────────┐ │ │ │ Slave N │ │ │ │ 从库 N │ │ │ └──────────┘ │ │ │ (读) │ │ └────────────────┘ │ └─────────────┘ │ └───────────────────┘ ``` --- ## 2. 技术栈选择 ### 2.1 后端技术栈 | 层级 | 技术选型 | 说明 | |------|---------|------| | **开发语言** | Go 1.21+ | 高性能、并发能力强、内存占用低 | | **Web 框架** | Gin / Fiber | 轻量级、高性能 | | **数据库驱动** | GORM / sqlx | ORM 和原生 SQL 混合使用 | | **缓存** | Redis (go-redis) | 高性能缓存和分布式锁 | | **配置管理** | Viper | 配置文件和环境变量管理 | | **日志** | Zap | 高性能结构化日志 | | **监控** | Prometheus + OpenTelemetry | 指标收集和链路追踪 | | **限流** | Uber Rate Limit | 令牌桶算法限流 | | **JWT** | golang-jwt/jwt | JWT 生成和验证 | | **密码加密** | golang.org/x/crypto/argon2 | Argon2id 密码哈希 | ### 2.2 前端技术栈(Admin 后台) 当前前端技术栈不再在本文件内独立演化,唯一有效方案见: - `docs/plans/ADMIN_FRONTEND_EXECUTION_PLAN.md` 本文件只保留当前统一结论: | 层级 | 技术选型 | 说明 | |------|---------|------| | **框架** | React 18 + TypeScript | 当前唯一前端框架口径 | | **构建工具** | Vite | 从零启动成本低,构建快 | | **UI 组件库** | Ant Design 5 | 后台场景优先 | | **状态管理** | React Context(仅会话态) | 不引入 Pinia / Redux / Zustand | | **HTTP 客户端** | 原生 `fetch` + 统一请求客户端 | 不再使用 Axios | | **路由** | React Router 6 | 统一受保护路由方案 | | **样式** | CSS Modules + CSS Variables + AntD Theme Token | 不使用 `styled-components` | 页面范围、类型模型、认证流和 API 服务层一律以 `docs/plans/ADMIN_FRONTEND_EXECUTION_PLAN.md` 为准。 ### 2.3 基础设施 | 组件 | 技术选型 | 说明 | |------|---------|------| | **容器化** | Docker | 应用容器化 | | **编排** | Kubernetes / Docker Compose | 容器编排 | | **负载均衡** | Nginx | HTTP 负载均衡 | | **监控** | Prometheus + Grafana | 指标监控 | | **日志** | ELK (Elasticsearch + Logstash + Kibana) | 日志收集和分析 | | **链路追踪** | Jaeger / Zipkin | 分布式链路追踪 | | **消息队列** | 可选:Kafka / RabbitMQ | 异步消息处理 | --- ## 3. 性能优化方案 ### 3.1 多级缓存架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 多级缓存架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ L1 缓存 │ -> │ L2 缓存 │ -> │ L3 缓存 │ │ │ │ (本地内存) │ │ (Redis) │ │ (数据库) │ │ │ │ │ │ │ │ │ │ │ │ • 用户信息 │ │ • 用户信息 │ │ • 完整数据 │ │ │ │ • 权限信息 │ │ • 权限信息 │ │ • 原始数据 │ │ │ │ • Token │ │ • Session │ │ │ │ │ │ • 热点数据 │ │ • 热点数据 │ │ │ │ │ │ │ │ │ │ │ │ │ │ TTL: 5min │ │ TTL: 30min │ │ TTL: 永久 │ │ │ │ 容量: 1GB │ │ 容量: 64GB │ │ 容量: 10TB │ │ │ │ 命中率: 85%│ │ 命中率: 12% │ │ 命中率: 3% │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ │ │ └──────────────────┼──────────────────┘ │ │ │ │ │ ┌─────▼─────┐ │ │ │ 缓存回源 │ │ │ │ 策略 │ │ │ └───────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### 3.2 L1 本地缓存实现(Go) ```go package cache import ( "sync" "time" ) type CacheItem struct { Value interface{} ExpireTime time.Time } type LocalCache struct { items map[string]*CacheItem mu sync.RWMutex } func NewLocalCache() *LocalCache { cache := &LocalCache{ items: make(map[string]*CacheItem), } // 启动后台清理过期数据 go cache.cleanupExpired() return cache } func (c *LocalCache) Set(key string, value interface{}, ttl time.Duration) { c.mu.Lock() defer c.mu.Unlock() expireTime := time.Now().Add(ttl) c.items[key] = &CacheItem{ Value: value, ExpireTime: expireTime, } } func (c *LocalCache) Get(key string) (interface{}, bool) { c.mu.RLock() defer c.mu.RUnlock() item, exists := c.items[key] if !exists { return nil, false } if time.Now().After(item.ExpireTime) { return nil, false } return item.Value, true } func (c *LocalCache) Delete(key string) { c.mu.Lock() defer c.mu.Unlock() delete(c.items, key) } func (c *LocalCache) cleanupExpired() { ticker := time.NewTicker(1 * time.Minute) defer ticker.Stop() for range ticker.C { c.mu.Lock() now := time.Now() for key, item := range c.items { if now.After(item.ExpireTime) { delete(c.items, key) } } c.mu.Unlock() } } ``` ### 3.3 L2 Redis 缓存策略 ```go package cache import ( "context" "encoding/json" "time" "github.com/redis/go-redis/v9" ) type RedisCache struct { client *redis.Client } func NewRedisCache(addr string) *RedisCache { rdb := redis.NewClient(&redis.Options{ Addr: addr, Password: "", DB: 0, PoolSize: 100, MinIdleConns: 10, }) return &RedisCache{client: rdb} } // 设置缓存 func (r *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error { data, err := json.Marshal(value) if err != nil { return err } return r.client.Set(ctx, key, data, ttl).Err() } // 获取缓存 func (r *RedisCache) Get(ctx context.Context, key string, dest interface{}) error { data, err := r.client.Get(ctx, key).Bytes() if err != nil { return err } return json.Unmarshal(data, dest) } // 缓存回源 func (r *RedisCache) GetOrSet(ctx context.Context, key string, ttl time.Duration, fn func() (interface{}, error), dest interface{}) error { // 尝试从缓存获取 err := r.Get(ctx, key, dest) if err == nil { return nil } if err != redis.Nil { return err } // 缓存未命中,从数据源获取 value, err := fn() if err != nil { return err } // 设置缓存 if err := r.Set(ctx, key, value, ttl); err != nil { // 缓存设置失败不影响主流程 return nil } // 将值赋给 dest data, _ := json.Marshal(value) return json.Unmarshal(data, dest) } ``` ### 3.4 缓存穿透、击穿、雪崩防护 ```go package cache import ( "context" "sync" "time" ) // 缓存穿透防护: 布隆过滤器 type BloomFilter struct { bits []bool size int } func (b *BloomFilter) Add(key string) { // 简化实现,实际使用推荐使用 github.com/bits-and-blooms/bloom idx := hash(key) % b.size b.bits[idx] = true } func (b *BloomFilter) Contains(key string) bool { idx := hash(key) % b.size return b.bits[idx] } // 缓存击穿防护: 单机互斥锁 type SingleFlight struct { mu sync.Mutex calls map[string]*call } type call struct { wg sync.WaitGroup val interface{} err error } func (s *SingleFlight) Do(key string, fn func() (interface{}, error)) (interface{}, error) { s.mu.Lock() if s.calls == nil { s.calls = make(map[string]*call) } if c, ok := s.calls[key]; ok { s.mu.Unlock() c.wg.Wait() return c.val, c.err } c := new(call) c.wg.Add(1) s.calls[key] = c s.mu.Unlock() c.val, c.err = fn() c.wg.Done() s.mu.Lock() delete(s.calls, key) s.mu.Unlock() return c.val, c.err } // 缓存雪崩防护: 随机 TTL func RandomTTL(baseTTL time.Duration, jitter time.Duration) time.Duration { jitterNs := time.Duration(time.Now().UnixNano() % int64(jitter)) return baseTTL + jitterNs } ``` ### 3.5 数据库读写分离 ```go package database import ( "gorm.io/gorm" ) type Cluster struct { Master *gorm.DB Slaves []*gorm.DB mu sync.RWMutex } func NewCluster(master *gorm.DB, slaves []*gorm.DB) *Cluster { return &Cluster{ Master: master, Slaves: slaves, } } // 获取读库 (负载均衡) func (c *Cluster) GetSlave() *gorm.DB { c.mu.RLock() defer c.mu.RUnlock() if len(c.Slaves) == 0 { return c.Master } // 轮询选择从库 idx := time.Now().UnixNano() % int64(len(c.Slaves)) return c.Slaves[idx] } // 写操作使用主库 func (c *Cluster) Write() *gorm.DB { return c.Master } // 读操作使用从库 func (c *Cluster) Read() *gorm.DB { return c.GetSlave() } ``` ### 3.6 数据库连接池优化 ```yaml # database.yml database: # 主库连接池 master: max_open_conns: 100 # 最大打开连接数 max_idle_conns: 20 # 最大空闲连接数 conn_max_lifetime: 1800s # 连接最大存活时间(30分钟) conn_max_idle_time: 600s # 连接最大空闲时间(10分钟) # 从库连接池 slave: max_open_conns: 200 # 从库可以配置更大的连接池 max_idle_conns: 50 conn_max_lifetime: 1800s conn_max_idle_time: 600s ``` ```go // Go 实现 db.SetMaxOpenConns(100) db.SetMaxIdleConns(20) db.SetConnMaxLifetime(30 * time.Minute) db.SetConnMaxIdleTime(10 * time.Minute) ``` --- ## 4. 接口性能优化 ### 4.1 批量操作优化 ```go // 不推荐: 循环查询 func GetUsersBatch(userIDs []int64) ([]*User, error) { var users []*User for _, id := range userIDs { var user User if err := db.First(&user, id).Error; err != nil { return nil, err } users = append(users, &user) } return users, nil } // 推荐: 批量查询 func GetUsersBatch(userIDs []int64) ([]*User, error) { var users []*User if err := db.Where("id IN ?", userIDs).Find(&users).Error; err != nil { return nil, err } return users, nil } ``` ### 4.2 预加载关联数据 ```go // 不推荐: N+1 查询 func GetUsersWithRoles() ([]*User, error) { var users []*User db.Find(&users) for _, user := range users { var roles []Role db.Where("user_id = ?", user.ID).Find(&roles) // N+1 查询 user.Roles = roles } return users, nil } // 推荐: 预加载 func GetUsersWithRoles() ([]*User, error) { var users []*User db.Preload("Roles").Find(&users) // 使用 Preload 一次性加载 return users, nil } ``` ### 4.3 索引优化 ```sql -- 用户登录查询优化 -- 不推荐: 全表扫描 SELECT * FROM users WHERE email = 'john@example.com' AND status = 1; -- 推荐: 创建复合索引 CREATE INDEX idx_email_status ON users(email, status); -- 角色权限查询优化 -- 不推荐: 多次关联查询 SELECT p.* FROM permissions p INNER JOIN role_permissions rp ON p.id = rp.permission_id WHERE rp.role_id IN (SELECT role_id FROM user_roles WHERE user_id = ?); -- 推荐: 优化 SQL 和索引 CREATE INDEX idx_user_roles_user_id ON user_roles(user_id); CREATE INDEX idx_role_permissions_role_id ON role_permissions(role_id); -- 使用 JOIN 优化 SELECT p.* FROM permissions p INNER JOIN role_permissions rp ON p.id = rp.permission_id INNER JOIN user_roles ur ON rp.role_id = ur.role_id WHERE ur.user_id = ?; ``` ### 4.4 分页优化(游标分页) ```go // 不推荐: OFFSET 分页(数据量大时性能差) func GetUsersByPage(page, pageSize int) ([]*User, error) { var users []*User offset := (page - 1) * pageSize if err := db.Offset(offset).Limit(pageSize).Find(&users).Error; err != nil { return nil, err } return users, nil } // 推荐: 游标分页(基于 ID) type PageResult struct { Users []*User `json:"users"` LastID int64 `json:"last_id"` HasMore bool `json:"has_more"` } func GetUsersByCursor(lastID int64, pageSize int) (*PageResult, error) { var users []*User query := db.Order("id ASC").Limit(pageSize + 1) if lastID > 0 { query = query.Where("id > ?", lastID) } if err := query.Find(&users).Error; err != nil { return nil, err } hasMore := len(users) > pageSize if hasMore { users = users[:pageSize] } var lastIDResult int64 if len(users) > 0 { lastIDResult = users[len(users)-1].ID } return &PageResult{ Users: users, LastID: lastIDResult, HasMore: hasMore, }, nil } ``` --- ## 5. 并发处理优化 ### 5.1 协程池 ```go package worker import ( "sync" ) type Task func() type WorkerPool struct { tasks chan Task workers int wg sync.WaitGroup } func NewWorkerPool(workers int, taskQueueSize int) *WorkerPool { return &WorkerPool{ tasks: make(chan Task, taskQueueSize), workers: workers, } } func (p *WorkerPool) Start() { for i := 0; i < p.workers; i++ { p.wg.Add(1) go p.worker() } } func (p *WorkerPool) worker() { defer p.wg.Done() for task := range p.tasks { task() } } func (p *WorkerPool) Submit(task Task) { p.tasks <- task } func (p *WorkerPool) Stop() { close(p.tasks) p.wg.Wait() } ``` ### 5.2 批量并发查询 ```go package service import ( "sync" ) func BatchGetUsers(userIDs []int64) (map[int64]*User, error) { result := make(map[int64]*User) var mu sync.Mutex var wg sync.WaitGroup errChan := make(chan error, len(userIDs)) // 创建协程池 pool := worker.NewWorkerPool(10, 1000) pool.Start() defer pool.Stop() for _, id := range userIDs { wg.Add(1) pool.Submit(func() { defer wg.Done() user, err := getUserByID(id) if err != nil { errChan <- err return } mu.Lock() result[id] = user mu.Unlock() }) } wg.Wait() close(errChan) // 检查是否有错误 for err := range errChan { if err != nil { return nil, err } } return result, nil } ``` --- ## 6. 性能监控 ### 6.1 Prometheus 指标定义 ```go package metrics import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) var ( // HTTP 请求数 HTTPRequestsTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "path", "status"}, ) // HTTP 请求耗时 HTTPRequestDuration = promauto.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request latency in seconds", Buckets: prometheus.DefBuckets, }, []string{"method", "path"}, ) // 缓存命中率 CacheHitTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "cache_hit_total", Help: "Total number of cache hits", }, []string{"cache_level", "key_pattern"}, ) CacheMissTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "cache_miss_total", Help: "Total number of cache misses", }, []string{"cache_level", "key_pattern"}, ) // 数据库查询耗时 DBQueryDuration = promauto.NewHistogramVec( prometheus.HistogramOpts{ Name: "db_query_duration_seconds", Help: "Database query latency in seconds", Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5}, }, []string{"operation", "table"}, ) // 在线用户数 OnlineUsers = promauto.NewGauge( prometheus.GaugeOpts{ Name: "online_users", Help: "Current number of online users", }, ) // 总用户数 TotalUsers = promauto.NewGauge( prometheus.GaugeOpts{ Name: "total_users", Help: "Total number of users", }, ) ) ``` ### 6.2 中间件集成 ```go package middleware import ( "strconv" "time" "github.com/gin-gonic/gin" "your-project/metrics" ) func PrometheusMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() // 处理请求 c.Next() // 记录指标 duration := time.Since(start).Seconds() status := strconv.Itoa(c.Writer.Status()) metrics.HTTPRequestsTotal.WithLabelValues( c.Request.Method, c.FullPath(), status, ).Inc() metrics.HTTPRequestDuration.WithLabelValues( c.Request.Method, c.FullPath(), ).Observe(duration) } } ``` --- ## 7. 性能目标与调优 ### 7.1 性能目标 | 指标 | 目标值 | 当前值 | 状态 | |------|--------|--------|------| | 并发用户数 | 100,000 | - | 待验证 | | QPS | 100,000 | - | 待验证 | | P50 响应时间 | < 100ms | - | 待验证 | | P99 响应时间 | < 500ms | - | 待验证 | | 缓存命中率 | > 95% | - | 待验证 | | 数据库 QPS | < 10,000 | - | 待验证 | ### 7.2 性能调优清单 - [ ] 启用本地缓存(L1 Cache) - [ ] 配置 Redis 集群(L2 Cache) - [ ] 数据库读写分离 - [ ] 优化数据库索引 - [ ] 批量操作优化 - [ ] 使用游标分页 - [ ] 连接池调优 - [ ] 协程池优化 - [ ] 启用 Gzip 压缩 - [ ] CDN 加速静态资源 - [ ] HTTP/2 支持 - [ ] 数据库查询优化 ### 7.3 压力测试方案 ```bash # 使用 Apache Bench (ab) ab -n 100000 -c 1000 http://localhost:8080/api/v1/users # 使用 wrk wrk -t12 -c400 -d30s http://localhost:8080/api/v1/users # 使用 hey hey -n 100000 -c 1000 http://localhost:8080/api/v1/users ``` --- ## 8. 扩展性设计 ### 8.1 水平扩展 - **无状态设计**: 应用服务不保存状态,支持水平扩展 - **会话管理**: 使用 Redis 存储会话 - **文件存储**: 使用对象存储(OSS/S3) - **消息队列**: 使用 Kafka/RabbitMQ 异步处理 ### 8.2 垂直扩展 - **资源限制**: 根据 QPS 调整资源配置 - **缓存调优**: 增加缓存容量 - **数据库优化**: 增加 CPU/内存,使用更好的存储 --- ## 9. 容灾与高可用 ### 9.1 多机房部署 ``` ┌─────────────────────────────────────────────────────────┐ │ 全局负载均衡 (GSLB) │ └──────────────────┬───────────────┬──────────────────────┘ │ │ ┌──────────▼────┐ ┌──────▼──────────┐ │ 机房 A (北京) │ │ 机房 B (上海) │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ 负载均衡 │ │ │ │ 负载均衡 │ │ │ └────┬─────┘ │ │ └────┬─────┘ │ │ │ │ │ │ │ │ ┌────▼────┐ │ │ ┌────▼────┐ │ │ │ 应用集群│ │ │ │ 应用集群│ │ │ └────┬────┘ │ │ └────┬────┘ │ │ │ │ │ │ │ │ ┌────▼────┐ │ │ ┌────▼────┐ │ │ │Redis集群│ │ │ │Redis集群│ │ │ └─────────┘ │ │ └─────────┘ │ │ ┌────┬────┐ │ │ ┌────┬────┐ │ │ │DB主│DB从│ │ │ │DB主│DB从│ │ │ └────┴────┘ │ │ └────┴────┘ │ └───────────────┘ └───────────────┘ │ │ └───────┬───────┘ │ ┌──────▼──────┐ │ 异地灾备 │ │ (广州) │ └─────────────┘ ``` ### 9.2 数据备份策略 - **实时备份**: 主从复制 - **每日备份**: 全量备份 + 增量备份 - **跨机房备份**: 异地备份 - **加密存储**: 备份数据加密 --- ## 10. 性能优化案例 ### 10.1 登录接口优化 **优化前**: 500ms (P99) ```go // 每次都查询数据库 func Login(username, password string) (*User, error) { var user User db.Where("username = ?", username).First(&user) // 验证密码... return &user, nil } ``` **优化后**: 50ms (P99) ```go // 使用本地缓存 + Redis 缓存 func Login(username, password string) (*User, error) { // L1 缓存查询 if user, ok := l1Cache.Get("user:" + username); ok { return user.(*User), nil } // L2 缓存查询 var user User err := redisCache.GetOrSet(ctx, "user:"+username, 30*time.Minute, func() (interface{}, error) { var u User db.Where("username = ?", username).First(&u) return &u, nil }, &user) if err != nil { return nil, err } // 更新 L1 缓存 l1Cache.Set("user:"+username, &user, 5*time.Minute) return &user, nil } ``` ### 10.2 权限查询优化 **优化前**: 1000ms (P99) ```go // 每次都查询数据库 func GetUserPermissions(userID int64) ([]string, error) { var userRoles []UserRole db.Where("user_id = ?", userID).Find(&userRoles) var permissions []string for _, ur := range userRoles { var rolePermissions []RolePermission db.Where("role_id = ?", ur.RoleID).Find(&rolePermissions) for _, rp := range rolePermissions { var permission Permission db.First(&permission, rp.PermissionID) permissions = append(permissions, permission.Code) } } return permissions, nil } ``` **优化后**: 20ms (P99) ```go // 使用本地缓存 + Redis 缓存 + 批量查询 func GetUserPermissions(userID int64) ([]string, error) { cacheKey := fmt.Sprintf("user:permissions:%d", userID) // L1 缓存查询 if perms, ok := l1Cache.Get(cacheKey); ok { return perms.([]string), nil } // L2 缓存查询 var permissions []string err := redisCache.GetOrSet(ctx, cacheKey, 30*time.Minute, func() (interface{}, error) { // 批量查询角色和权限 var result []struct { PermissionCode string } db.Table("permissions"). Select("permissions.code as permission_code"). Joins("INNER JOIN role_permissions ON role_permissions.permission_id = permissions.id"). Joins("INNER JOIN user_roles ON user_roles.role_id = role_permissions.role_id"). Where("user_roles.user_id = ?", userID). Scan(&result) var codes []string for _, r := range result { codes = append(codes, r.PermissionCode) } return codes, nil }, &permissions) if err != nil { return nil, err } // 更新 L1 缓存 l1Cache.Set(cacheKey, permissions, 5*time.Minute) return permissions, nil } ``` --- ## 11. 性能监控与告警 ### 11.1 核心监控指标 | 指标 | 类型 | 说明 | |------|------|------| | `http_requests_total` | Counter | HTTP 请求总数 | | `http_request_duration_seconds` | Histogram | HTTP 请求耗时 | | `cache_hit_total` | Counter | 缓存命中数 | | `cache_miss_total` | Counter | 缓存未命中数 | | `db_query_duration_seconds` | Histogram | 数据库查询耗时 | | `online_users` | Gauge | 在线用户数 | | `total_users` | Gauge | 总用户数 | ### 11.2 告警规则 ```yaml groups: - name: user-ms-alerts rules: # 高错误率告警 - alert: HighErrorRate expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.01 for: 5m annotations: summary: "高错误率告警" # 高响应时间告警 - alert: HighResponseTime expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 0.5 for: 5m annotations: summary: "P99 响应时间超过 500ms" # 低缓存命中率告警 - alert: LowCacheHitRate expr: rate(cache_hit_total[5m]) / (rate(cache_hit_total[5m]) + rate(cache_miss_total[5m])) < 0.9 for: 10m annotations: summary: "缓存命中率低于 90%" ``` --- ## 12. 总结 本技术架构文档定义了用户管理系统的完整技术方案,包括: 1. **系统架构**: 单机(SQLite)和集群(PostgreSQL/MySQL)两种架构 2. **多级缓存**: L1 本地缓存 + L2 Redis 缓存 + L3 数据库 3. **性能优化**: 批量操作、预加载、索引优化、游标分页 4. **并发处理**: 协程池、批量并发查询 5. **监控告警**: Prometheus 指标、告警规则 6. **扩展性**: 水平扩展、垂直扩展 7. **高可用**: 多机房部署、数据备份 通过以上优化,系统能够达到 PRD 要求的性能指标: - 10 亿用户规模 - 10 万级并发 - P99 响应时间 < 500ms - 99.99% 可用性 --- *本文档持续更新中,如有疑问请联系技术团队。*