第9讲:记忆系统的性能优化与基准测试——缓存策略、连接池、批量操作与压测方法论

一、性能优化架构

复制代码
┌──────────────────────────────────────────────────────────────────────────────┐
│                       记忆系统性能优化架构                                      │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│  ┌────────────────────────────────────────────────────────────────────────┐   │
│  │                          客户端层 (Client)                               │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │   │
│  │  │ SDK Client  │  │ REST Client │  │ gRPC Client │  │ Batch Client│  │   │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  │   │
│  └─────────┼───────────────┼───────────────┼───────────────┼──────────┘   │
│            │               │               │               │               │
│            ▼               ▼               ▼               ▼               │
│  ┌────────────────────────────────────────────────────────────────────────┐   │
│  │                       接入层 (Gateway)                                  │   │
│  │                                                                        │   │
│  │  ┌──────────────────────────────────────────────────────────────────┐  │   │
│  │  │                  连接池 (Connection Pool)                         │  │   │
│  │  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │  │   │
│  │  │  │ HTTP/2   │  │ gRPC     │  │ WebSocket│  │ Internal │        │  │   │
│  │  │  │ Pool     │  │ Pool     │  │ Pool     │  │ Pool     │        │  │   │
│  │  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘        │  │   │
│  │  └──────────────────────────────────────────────────────────────────┘  │   │
│  └────────────────────────────────┬───────────────────────────────────────┘   │
│                                   │                                             │
│                                   ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────┐   │
│  │                      缓存层 (Cache Layer)                                │   │
│  │                                                                        │   │
│  │  ┌────────────────────┐  ┌────────────────────┐  ┌──────────────────┐  │   │
│  │  │ L1: 本地内存缓存   │  │ L2: Redis 分布式   │  │ L3: 本地磁盘     │  │   │
│  │  │ LRU/TTL/预加载     │  │ 集群/哨兵/分片      │  │ SSD/NVMe         │  │   │
│  │  │ 命中率 > 90%       │  │ 命中率 > 70%       │  │ 冷数据降级       │  │   │
│  │  └──────────┬─────────┘  └──────────┬─────────┘  └──────────┬───────┘  │   │
│  └─────────────┼──────────────────────┼──────────────────────┼──────────┘   │
│                │                      │                      │               │
│                ▼                      ▼                      ▼               │
│  ┌────────────────────────────────────────────────────────────────────────┐   │
│  │                      核心处理层 (Core)                                   │   │
│  │                                                                        │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │   │
│  │  │ 批量操作    │  │ 异步写入    │  │ 读写分离    │  │ 管道化      │  │   │
│  │  │ Batch Save  │  │ Async Write │  │ Read/Write  │  │ Pipeline    │  │   │
│  │  │ Batch Get   │  │ Buffer      │  │ Splitting   │  │ Processing  │  │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘  │   │
│  └────────────────────────────────┬───────────────────────────────────────┘   │
│                                   │                                             │
│                                   ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────┐   │
│  │                      存储层 (Storage)                                    │   │
│  │                                                                        │   │
│  │  ┌────────────────────┐  ┌────────────────────┐  ┌──────────────────┐  │   │
│  │  │ 内存存储           │  │ 磁盘存储           │  │ 分布式存储       │  │   │
│  │  │ sync.Map/RWMutex   │  │ WAL/B+Tree/SSD     │  │ Raft/Sharding    │  │   │
│  │  │ 零拷贝序列化       │  │ 压缩/索引          │  │ 一致性哈希       │  │   │
│  │  └────────────────────┘  └────────────────────┘  └──────────────────┘  │   │
│  └────────────────────────────────────────────────────────────────────────┘   │
│                                                                                │
└──────────────────────────────────────────────────────────────────────────────┘

二、核心数据结构

复制代码
// memory/optimization/types.go
package optimization

import (
    "container/list"
    "context"
    "sync"
    "time"
)

// CacheLevel 缓存层级
type CacheLevel int

const (
    CacheL1 CacheLevel = iota // 本地内存
    CacheL2                   // Redis
    CacheL3                   // 本地磁盘
)

// CacheConfig 缓存配置
type CacheConfig struct {
    L1 CacheLayerConfig `yaml:"l1"`
    L2 CacheLayerConfig `yaml:"l2"`
    L3 CacheLayerConfig `yaml:"l3"`
}

type CacheLayerConfig struct {
    Enabled       bool          `yaml:"enabled"`
    Capacity      int           `yaml:"capacity"`       // 最大条目数
    TTL           time.Duration `yaml:"ttl"`            // 过期时间
    PreloadKeys   []string      `yaml:"preload_keys"`   // 预热键列表
    StatsEnabled  bool          `yaml:"stats_enabled"`  // 统计开关
}

// CacheEntry 缓存条目
type CacheEntry struct {
    Key       string      `json:"key"`
    Value     interface{} `json:"value"`
    Size      int         `json:"size"`       // 字节数
    ExpireAt  time.Time   `json:"expire_at"`
    CreatedAt time.Time   `json:"created_at"`
    AccessCount int64     `json:"access_count"`
}

// CacheStats 缓存统计
type CacheStats struct {
    Level       CacheLevel `json:"level"`
    Hits        int64      `json:"hits"`
    Misses      int64      `json:"misses"`
    Evictions   int64      `json:"evictions"`
    Expirations int64      `json:"expirations"`
    Size        int        `json:"size"`        // 当前条目数
    MemoryUsage int64      `json:"memory_usage"` // 字节数
    HitRate     float64    `json:"hit_rate"`
}

// ConnectionPoolConfig 连接池配置
type ConnectionPoolConfig struct {
    MaxIdle       int           `yaml:"max_idle"`        // 最大空闲连接
    MaxActive     int           `yaml:"max_active"`      // 最大活跃连接
    IdleTimeout   time.Duration `yaml:"idle_timeout"`    // 空闲超时
    WaitTimeout   time.Duration `yaml:"wait_timeout"`    // 等待超时
    MaxLifetime   time.Duration `yaml:"max_lifetime"`    // 最大生命周期
    HealthCheckInterval time.Duration `yaml:"health_check_interval"`
}

// BatchConfig 批量操作配置
type BatchConfig struct {
    MaxBatchSize    int           `yaml:"max_batch_size"`     // 最大批量大小
    FlushInterval   time.Duration `yaml:"flush_interval"`     // 刷新间隔
    MaxWaitItems    int           `yaml:"max_wait_items"`     // 最大等待条目数
    Concurrency     int           `yaml:"concurrency"`        // 并发数
    RetryCount      int           `yaml:"retry_count"`        // 重试次数
    RetryInterval   time.Duration `yaml:"retry_interval"`     // 重试间隔
}

// BatchOperation 批量操作
type BatchOperation struct {
    ID        string        `json:"id"`
    Type      string        `json:"type"`      // save, get, delete
    Items     []BatchItem   `json:"items"`
    CreatedAt time.Time     `json:"created_at"`
    Timeout   time.Duration `json:"timeout"`
}

type BatchItem struct {
    Key       string      `json:"key"`
    Value     interface{} `json:"value,omitempty"`
    Options   map[string]interface{} `json:"options,omitempty"`
}

// BatchResult 批量操作结果
type BatchResult struct {
    ID        string        `json:"id"`
    Success   bool          `json:"success"`
    Items     []BatchItemResult `json:"items"`
    TotalLatency time.Duration `json:"total_latency"`
    Error     string        `json:"error,omitempty"`
}

type BatchItemResult struct {
    Key     string      `json:"key"`
    Success bool        `json:"success"`
    Value   interface{} `json:"value,omitempty"`
    Error   string      `json:"error,omitempty"`
    Latency time.Duration `json:"latency"`
}

// OptimizationConfig 优化配置
type OptimizationConfig struct {
    Cache     CacheConfig           `yaml:"cache"`
    Pool      ConnectionPoolConfig  `yaml:"connection_pool"`
    Batch     BatchConfig           `yaml:"batch"`
    AsyncWrite AsyncWriteConfig     `yaml:"async_write"`
}

type AsyncWriteConfig struct {
    Enabled         bool          `yaml:"enabled"`
    BufferSize      int           `yaml:"buffer_size"`      // 缓冲区大小
    FlushWorkers    int           `yaml:"flush_workers"`    // 刷新工作者数
    FlushInterval   time.Duration `yaml:"flush_interval"`   // 刷新间隔
    RetryQueueSize  int           `yaml:"retry_queue_size"` // 重试队列大小
}

// BenchmarkConfig 基准测试配置
type BenchmarkConfig struct {
    Duration       time.Duration `yaml:"duration"`        // 测试时长
    Concurrency    int           `yaml:"concurrency"`     // 并发数
    Operations     []string      `yaml:"operations"`      // 操作类型
    ReadRatio      float64       `yaml:"read_ratio"`      // 读比例
    WriteRatio     float64       `yaml:"write_ratio"`     // 写比例
    DataSize       int           `yaml:"data_size"`       // 数据大小(bytes)
    WarmupDuration time.Duration `yaml:"warmup_duration"` // 预热时长
    ReportInterval time.Duration `yaml:"report_interval"` // 报告间隔
}

// BenchmarkReport 基准测试报告
type BenchmarkReport struct {
    Config         BenchmarkConfig   `json:"config"`
    TotalOps       int64             `json:"total_ops"`
    Duration       time.Duration     `json:"duration"`
    Throughput     float64           `json:"throughput"`      // ops/s
    AvgLatency     time.Duration     `json:"avg_latency"`
    P50Latency     time.Duration     `json:"p50_latency"`
    P90Latency     time.Duration     `json:"p90_latency"`
    P99Latency     time.Duration     `json:"p99_latency"`
    MaxLatency     time.Duration     `json:"max_latency"`
    ErrorCount     int64             `json:"error_count"`
    ErrorRate      float64           `json:"error_rate"`
    OpsByType      map[string]int64  `json:"ops_by_type"`
    Timelines      []TimelinePoint   `json:"timelines"`
}

type TimelinePoint struct {
    Timestamp time.Time `json:"timestamp"`
    Throughput float64  `json:"throughput"`
    Latency    float64  `json:"latency_ms"`
    Errors     int64    `json:"errors"`
}

三、多级缓存实现

复制代码
// memory/optimization/cache.go
package optimization

import (
    "container/list"
    "context"
    "encoding/json"
    "fmt"
    "log"
    "sync"
    "time"
)

// Cache 多级缓存接口
type Cache interface {
    Get(ctx context.Context, key string) (interface{}, bool, error)
    Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error
    Delete(ctx context.Context, key string) error
    Clear(ctx context.Context) error
    Stats(ctx context.Context) CacheStats
    Level() CacheLevel
}

// LRUCache L1 本地内存缓存(LRU + TTL)
type LRUCache struct {
    level     CacheLevel
    capacity  int
    ttl       time.Duration
    items     map[string]*list.Element
    evictList *list.List
    stats     CacheStats
    mu        sync.RWMutex
    stopCh    chan struct{}
}

type cacheItem struct {
    key        string
    value      interface{}
    size       int
    expireAt   time.Time
    accessCount int64
}

func NewLRUCache(level CacheLevel, capacity int, ttl time.Duration) *LRUCache {
    c := &LRUCache{
        level:     level,
        capacity:  capacity,
        ttl:       ttl,
        items:     make(map[string]*list.Element),
        evictList: list.New(),
        stats: CacheStats{
            Level: level,
        },
        stopCh: make(chan struct{}),
    }

    // 启动过期清理协程
    go c.expirationLoop()

    return c
}

func (c *LRUCache) Level() CacheLevel {
    return c.level
}

func (c *LRUCache) Get(ctx context.Context, key string) (interface{}, bool, error) {
    c.mu.Lock()
    defer c.mu.Unlock()

    if elem, ok := c.items[key]; ok {
        item := elem.Value.(*cacheItem)

        // 检查过期
        if time.Now().After(item.expireAt) {
            c.removeElement(elem)
            c.stats.Expirations++
            c.stats.Misses++
            return nil, false, nil
        }

        // 移动到队首(最近使用)
        c.evictList.MoveToFront(elem)
        item.accessCount++
        c.stats.Hits++

        return item.value, true, nil
    }

    c.stats.Misses++
    return nil, false, nil
}

func (c *LRUCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error {
    c.mu.Lock()
    defer c.mu.Unlock()

    // 如果已存在,先移除
    if elem, ok := c.items[key]; ok {
        c.removeElement(elem)
    }

    // 检查容量,淘汰最久未使用的
    for c.evictList.Len() >= c.capacity {
        c.evictOldest()
    }

    // 计算大小
    size := estimateSize(value)

    // 创建新条目
    expireAt := time.Now().Add(ttl)
    if ttl == 0 {
        expireAt = time.Now().Add(c.ttl)
    }

    item := &cacheItem{
        key:      key,
        value:    value,
        size:     size,
        expireAt: expireAt,
    }

    elem := c.evictList.PushFront(item)
    c.items[key] = elem
    c.stats.Size = c.evictList.Len()
    c.stats.MemoryUsage += int64(size)

    return nil
}

func (c *LRUCache) Delete(ctx context.Context, key string) error {
    c.mu.Lock()
    defer c.mu.Unlock()

    if elem, ok := c.items[key]; ok {
        c.removeElement(elem)
    }

    return nil
}

func (c *LRUCache) Clear(ctx context.Context) error {
    c.mu.Lock()
    defer c.mu.Unlock()

    c.items = make(map[string]*list.Element)
    c.evictList.Init()
    c.stats.Size = 0
    c.stats.MemoryUsage = 0

    return nil
}

func (c *LRUCache) Stats(ctx context.Context) CacheStats {
    c.mu.RLock()
    defer c.mu.RUnlock()

    stats := c.stats
    total := stats.Hits + stats.Misses
    if total > 0 {
        stats.HitRate = float64(stats.Hits) / float64(total) * 100
    }

    return stats
}

func (c *LRUCache) removeElement(elem *list.Element) {
    c.evictList.Remove(elem)
    item := elem.Value.(*cacheItem)
    delete(c.items, item.key)
    c.stats.MemoryUsage -= int64(item.size)
}

func (c *LRUCache) evictOldest() {
    elem := c.evictList.Back()
    if elem != nil {
        c.removeElement(elem)
        c.stats.Evictions++
    }
}

func (c *LRUCache) expirationLoop() {
    ticker := time.NewTicker(1 * time.Minute)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            c.removeExpired()
        case <-c.stopCh:
            return
        }
    }
}

func (c *LRUCache) removeExpired() {
    c.mu.Lock()
    defer c.mu.Unlock()

    now := time.Now()
    for _, elem := range c.items {
        item := elem.Value.(*cacheItem)
        if now.After(item.expireAt) {
            c.removeElement(elem)
            c.stats.Expirations++
        }
    }
}

// MultiLevelCache 多级缓存
type MultiLevelCache struct {
    levels []Cache
    stats  map[CacheLevel]*CacheStats
    mu     sync.RWMutex
}

func NewMultiLevelCache(config CacheConfig) *MultiLevelCache {
    mlc := &MultiLevelCache{
        stats: make(map[CacheLevel]*CacheStats),
    }

    if config.L1.Enabled {
        l1 := NewLRUCache(CacheL1, config.L1.Capacity, config.L1.TTL)
        mlc.levels = append(mlc.levels, l1)
        mlc.stats[CacheL1] = &CacheStats{Level: CacheL1}
    }

    if config.L2.Enabled {
        l2 := NewRedisCache(config.L2)
        mlc.levels = append(mlc.levels, l2)
        mlc.stats[CacheL2] = &CacheStats{Level: CacheL2}
    }

    if config.L3.Enabled {
        l3 := NewDiskCache(config.L3)
        mlc.levels = append(mlc.levels, l3)
        mlc.stats[CacheL3] = &CacheStats{Level: CacheL3}
    }

    return mlc
}

// Get 多级缓存读取(逐级查找,向上回填)
func (mlc *MultiLevelCache) Get(ctx context.Context, key string) (interface{}, bool, error) {
    for i, cache := range mlc.levels {
        value, found, err := cache.Get(ctx, key)
        if err != nil {
            log.Printf("[CACHE] Level %d get error: %v", cache.Level(), err)
            continue
        }

        if found {
            // 回填到上层缓存
            for j := i - 1; j >= 0; j-- {
                if err := mlc.levels[j].Set(ctx, key, value, 0); err != nil {
                    log.Printf("[CACHE] Backfill to level %d failed: %v", mlc.levels[j].Level(), err)
                }
            }

            mlc.updateStats(cache.Level(), true)
            return value, true, nil
        }

        mlc.updateStats(cache.Level(), false)
    }

    return nil, false, nil
}

// Set 多级缓存写入(写入所有层级)
func (mlc *MultiLevelCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error {
    var lastErr error

    for _, cache := range mlc.levels {
        if err := cache.Set(ctx, key, value, ttl); err != nil {
            log.Printf("[CACHE] Level %d set error: %v", cache.Level(), err)
            lastErr = err
        }
    }

    return lastErr
}

// Delete 多级缓存删除
func (mlc *MultiLevelCache) Delete(ctx context.Context, key string) error {
    var lastErr error

    for _, cache := range mlc.levels {
        if err := cache.Delete(ctx, key); err != nil {
            lastErr = err
        }
    }

    return lastErr
}

// Clear 清空所有缓存
func (mlc *MultiLevelCache) Clear(ctx context.Context) error {
    var lastErr error

    for _, cache := range mlc.levels {
        if err := cache.Clear(ctx); err != nil {
            lastErr = err
        }
    }

    return lastErr
}

// Stats 获取各层缓存统计
func (mlc *MultiLevelCache) Stats(ctx context.Context) map[CacheLevel]*CacheStats {
    mlc.mu.RLock()
    defer mlc.mu.RUnlock()

    result := make(map[CacheLevel]*CacheStats)
    for level, stats := range mlc.stats {
        s := *stats
        result[level] = &s
    }

    // 补充实时统计
    for _, cache := range mlc.levels {
        stats := cache.Stats(ctx)
        result[cache.Level()] = &stats
    }

    return result
}

func (mlc *MultiLevelCache) updateStats(level CacheLevel, hit bool) {
    mlc.mu.Lock()
    defer mlc.mu.Unlock()

    if stats, ok := mlc.stats[level]; ok {
        if hit {
            stats.Hits++
        } else {
            stats.Misses++
        }
    }
}

// estimateSize 估算对象大小
func estimateSize(v interface{}) int {
    data, err := json.Marshal(v)
    if err != nil {
        return 100 // 默认 100 字节
    }
    return len(data)
}

// RedisCache L2 Redis 分布式缓存(占位实现)
type RedisCache struct {
    config CacheLayerConfig
    stats  CacheStats
}

func NewRedisCache(config CacheLayerConfig) *RedisCache {
    return &RedisCache{
        config: config,
        stats: CacheStats{Level: CacheL2},
    }
}

func (rc *RedisCache) Level() CacheLevel { return CacheL2 }

func (rc *RedisCache) Get(ctx context.Context, key string) (interface{}, bool, error) {
    // 实际实现使用 go-redis 客户端
    return nil, false, nil
}

func (rc *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error {
    return nil
}

func (rc *RedisCache) Delete(ctx context.Context, key string) error {
    return nil
}

func (rc *RedisCache) Clear(ctx context.Context) error {
    return nil
}

func (rc *RedisCache) Stats(ctx context.Context) CacheStats {
    return rc.stats
}

// DiskCache L3 本地磁盘缓存(占位实现)
type DiskCache struct {
    config CacheLayerConfig
    stats  CacheStats
}

func NewDiskCache(config CacheLayerConfig) *DiskCache {
    return &DiskCache{
        config: config,
        stats: CacheStats{Level: CacheL3},
    }
}

func (dc *DiskCache) Level() CacheLevel { return CacheL3 }

func (dc *DiskCache) Get(ctx context.Context, key string) (interface{}, bool, error) {
    return nil, false, nil
}

func (dc *DiskCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error {
    return nil
}

func (dc *DiskCache) Delete(ctx context.Context, key string) error {
    return nil
}

func (dc *DiskCache) Clear(ctx context.Context) error {
    return nil
}

func (dc *DiskCache) Stats(ctx context.Context) CacheStats {
    return dc.stats
}

四、连接池实现

复制代码
// memory/optimization/pool.go
package optimization

import (
    "context"
    "errors"
    "fmt"
    "log"
    "sync"
    "sync/atomic"
    "time"
)

var (
    ErrPoolExhausted = errors.New("connection pool exhausted")
    ErrPoolClosed    = errors.New("connection pool closed")
    ErrConnTimeout   = errors.New("connection wait timeout")
)

// ConnFactory 连接工厂
type ConnFactory func(ctx context.Context) (interface{}, error)

// ConnValidator 连接验证器
type ConnValidator func(conn interface{}) bool

// PooledConn 池化连接
type PooledConn struct {
    conn       interface{}
    createdAt  time.Time
    lastUsedAt time.Time
    borrowedBy int32
    broken     bool
}

// ConnectionPool 通用连接池
type ConnectionPool struct {
    config     ConnectionPoolConfig
    factory    ConnFactory
    validator  ConnValidator

    idleConns  chan *PooledConn
    activeConns map[*PooledConn]struct{}
    totalCreated int64
    totalBorrowed int64
    totalReturned int64
    totalBroken   int64
    waitCount    int64
    waitDuration  int64

    closed  bool
    mu      sync.RWMutex
    closeCh chan struct{}
}

func NewConnectionPool(config ConnectionPoolConfig, factory ConnFactory, validator ConnValidator) *ConnectionPool {
    pool := &ConnectionPool{
        config:      config,
        factory:     factory,
        validator:   validator,
        idleConns:   make(chan *PooledConn, config.MaxIdle),
        activeConns: make(map[*PooledConn]struct{}),
        closeCh:     make(chan struct{}),
    }

    // 预先创建空闲连接
    for i := 0; i < config.MaxIdle; i++ {
        conn, err := factory(context.Background())
        if err != nil {
            log.Printf("[POOL] Pre-create connection failed: %v", err)
            continue
        }
        pooled := &PooledConn{
            conn:      conn,
            createdAt: time.Now(),
            lastUsedAt: time.Now(),
        }
        pool.idleConns <- pooled
    }

    // 启动健康检查
    if config.HealthCheckInterval > 0 {
        go pool.healthCheckLoop()
    }

    // 启动空闲连接清理
    go pool.idleCleanupLoop()

    log.Printf("[POOL] Connection pool initialized: maxIdle=%d, maxActive=%d",
        config.MaxIdle, config.MaxActive)

    return pool
}

// Borrow 借用一个连接
func (p *ConnectionPool) Borrow(ctx context.Context) (*PooledConn, error) {
    p.mu.RLock()
    if p.closed {
        p.mu.RUnlock()
        return nil, ErrPoolClosed
    }
    p.mu.RUnlock()

    startTime := time.Now()
    atomic.AddInt64(&p.waitCount, 1)

    for {
        select {
        case pooled, ok := <-p.idleConns:
            if !ok {
                return nil, ErrPoolClosed
            }

            // 验证连接是否有效
            if p.validator != nil && !p.validator(pooled.conn) {
                p.destroyConn(pooled)
                continue // 重新获取
            }

            // 检查生命周期
            if p.config.MaxLifetime > 0 && time.Since(pooled.createdAt) > p.config.MaxLifetime {
                p.destroyConn(pooled)
                continue
            }

            atomic.AddInt64(&p.totalBorrowed, 1)
            atomic.StoreInt64(&p.waitDuration, int64(time.Since(startTime)))
            pooled.lastUsedAt = time.Now()
            atomic.StoreInt32(&pooled.borrowedBy, 1)

            p.mu.Lock()
            p.activeConns[pooled] = struct{}{}
            p.mu.Unlock()

            return pooled, nil

        case <-ctx.Done():
            return nil, ErrConnTimeout

        case <-time.After(p.config.WaitTimeout):
            // 尝试创建新连接
            if p.canCreateNew() {
                conn, err := p.factory(ctx)
                if err != nil {
                    return nil, fmt.Errorf("create connection: %w", err)
                }

                pooled := &PooledConn{
                    conn:      conn,
                    createdAt: time.Now(),
                    lastUsedAt: time.Now(),
                }
                atomic.AddInt64(&p.totalCreated, 1)
                atomic.AddInt64(&p.totalBorrowed, 1)
                pooled.borrowedBy = 1

                p.mu.Lock()
                p.activeConns[pooled] = struct{}{}
                p.mu.Unlock()

                return pooled, nil
            }

            return nil, ErrPoolExhausted
        }
    }
}

// Return 归还连接
func (p *ConnectionPool) Return(pooled *PooledConn, broken bool) error {
    p.mu.Lock()
    defer p.mu.Unlock()

    if p.closed {
        p.destroyConn(pooled)
        return ErrPoolClosed
    }

    delete(p.activeConns, pooled)
    atomic.AddInt64(&p.totalReturned, 1)

    if broken {
        atomic.AddInt64(&p.totalBroken, 1)
        p.destroyConn(pooled)
        return nil
    }

    pooled.borrowedBy = 0
    pooled.lastUsedAt = time.Now()

    // 归还到空闲队列
    select {
    case p.idleConns <- pooled:
    default:
        // 空闲队列满,销毁连接
        p.destroyConn(pooled)
    }

    return nil
}

// Close 关闭连接池
func (p *ConnectionPool) Close() {
    p.mu.Lock()
    defer p.mu.Unlock()

    if p.closed {
        return
    }

    p.closed = true
    close(p.closeCh)
    close(p.idleConns)

    // 销毁所有空闲连接
    for pooled := range p.idleConns {
        p.destroyConn(pooled)
    }

    // 销毁所有活跃连接
    for pooled := range p.activeConns {
        p.destroyConn(pooled)
    }

    log.Printf("[POOL] Connection pool closed: totalCreated=%d, totalBorrowed=%d, totalBroken=%d",
        p.totalCreated, p.totalBorrowed, p.totalBroken)
}

// Stats 连接池统计
func (p *ConnectionPool) Stats() map[string]interface{} {
    p.mu.RLock()
    defer p.mu.RUnlock()

    return map[string]interface{}{
        "idle_count":       len(p.idleConns),
        "active_count":     len(p.activeConns),
        "total_created":    atomic.LoadInt64(&p.totalCreated),
        "total_borrowed":   atomic.LoadInt64(&p.totalBorrowed),
        "total_returned":   atomic.LoadInt64(&p.totalReturned),
        "total_broken":     atomic.LoadInt64(&p.totalBroken),
        "wait_count":       atomic.LoadInt64(&p.waitCount),
        "wait_duration_ms": atomic.LoadInt64(&p.waitDuration) / int64(time.Millisecond),
        "closed":           p.closed,
    }
}

func (p *ConnectionPool) canCreateNew() bool {
    p.mu.RLock()
    defer p.mu.RUnlock()

    active := len(p.activeConns)
    idle := len(p.idleConns)
    total := active + idle

    return total < p.config.MaxActive
}

func (p *ConnectionPool) destroyConn(pooled *PooledConn) {
    if closer, ok := pooled.conn.(interface{ Close() error }); ok {
        closer.Close()
    }
}

func (p *ConnectionPool) healthCheckLoop() {
    ticker := time.NewTicker(p.config.HealthCheckInterval)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            p.checkHealth()
        case <-p.closeCh:
            return
        }
    }
}

func (p *ConnectionPool) checkHealth() {
    // 检查空闲连接的健康状况
    healthyConns := make([]*PooledConn, 0)
    for {
        select {
        case pooled := <-p.idleConns:
            if p.validator != nil && !p.validator(pooled.conn) {
                p.destroyConn(pooled)
                continue
            }
            healthyConns = append(healthyConns, pooled)
        default:
            // 归还健康的连接
            for _, pooled := range healthyConns {
                p.idleConns <- pooled
            }
            return
        }
    }
}

func (p *ConnectionPool) idleCleanupLoop() {
    ticker := time.NewTicker(5 * time.Minute)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            p.cleanupIdle()
        case <-p.closeCh:
            return
        }
    }
}

func (p *ConnectionPool) cleanupIdle() {
    now := time.Now()
    for {
        select {
        case pooled := <-p.idleConns:
            if p.config.IdleTimeout > 0 && now.Sub(pooled.lastUsedAt) > p.config.IdleTimeout {
                p.destroyConn(pooled)
                continue
            }
            // 归还
            p.idleConns <- pooled
        default:
            return
        }
    }
}

五、批量操作实现

复制代码
// memory/optimization/batch.go
package optimization

import (
    "context"
    "fmt"
    "log"
    "sync"
    "time"
)

// BatchProcessor 批量处理器
type BatchProcessor struct {
    config    BatchConfig
    handler   func(context.Context, []BatchItem) ([]BatchItemResult, error)
    buffer    []BatchItem
    mu        sync.Mutex
    flushCh   chan struct{}
    closeCh   chan struct{}
    stats     BatchStats
}

type BatchStats struct {
    TotalBatches  int64
    TotalItems    int64
    SuccessItems  int64
    FailedItems   int64
    AvgBatchSize  float64
    AvgFlushLatency time.Duration
    mu            sync.Mutex
}

func NewBatchProcessor(config BatchConfig, handler func(context.Context, []BatchItem) ([]BatchItemResult, error)) *BatchProcessor {
    bp := &BatchProcessor{
        config:  config,
        handler: handler,
        buffer:  make([]BatchItem, 0, config.MaxBatchSize),
        flushCh: make(chan struct{}, 1),
        closeCh: make(chan struct{}),
    }

    // 启动定时刷新
    go bp.flushLoop()

    return bp
}

// Add 添加条目到批处理队列
func (bp *BatchProcessor) Add(ctx context.Context, item BatchItem) (BatchItemResult, error) {
    resultCh := make(chan BatchItemResult, 1)

    bp.mu.Lock()
    bp.buffer = append(bp.buffer, item)
    shouldFlush := len(bp.buffer) >= bp.config.MaxBatchSize
    bp.mu.Unlock()

    if shouldFlush {
        select {
        case bp.flushCh <- struct{}{}:
        default:
        }
    }

    // 这里简化处理,实际应该使用 Future/Promise 模式
    // 等待批处理完成后通过回调返回结果
    select {
    case result := <-resultCh:
        return result, nil
    case <-time.After(bp.config.RetryInterval):
        return BatchItemResult{Key: item.Key, Success: false, Error: "timeout"}, nil
    }
}

// Flush 手动刷新
func (bp *BatchProcessor) Flush(ctx context.Context) error {
    bp.mu.Lock()
    items := bp.buffer
    bp.buffer = make([]BatchItem, 0, bp.config.MaxBatchSize)
    bp.mu.Unlock()

    if len(items) == 0 {
        return nil
    }

    return bp.processBatch(ctx, items)
}

// Close 关闭批处理器
func (bp *BatchProcessor) Close() {
    close(bp.closeCh)
    bp.Flush(context.Background())
}

// flushLoop 定时刷新循环
func (bp *BatchProcessor) flushLoop() {
    ticker := time.NewTicker(bp.config.FlushInterval)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            bp.Flush(context.Background())
        case <-bp.flushCh:
            bp.Flush(context.Background())
        case <-bp.closeCh:
            return
        }
    }
}

// processBatch 处理一批数据
func (bp *BatchProcessor) processBatch(ctx context.Context, items []BatchItem) error {
    startTime := time.Now()

    // 并发处理
    batchSize := len(items)
    numWorkers := bp.config.Concurrency
    if numWorkers > batchSize {
        numWorkers = batchSize
    }

    chunkSize := (batchSize + numWorkers - 1) / numWorkers
    var wg sync.WaitGroup
    errCh := make(chan error, numWorkers)

    for i := 0; i < numWorkers; i++ {
        start := i * chunkSize
        end := start + chunkSize
        if end > batchSize {
            end = batchSize
        }

        wg.Add(1)
        go func(chunk []BatchItem) {
            defer wg.Done()

            // 重试逻辑
            var lastErr error
            for attempt := 0; attempt <= bp.config.RetryCount; attempt++ {
                results, err := bp.handler(ctx, chunk)
                if err == nil {
                    // 处理结果
                    bp.updateStats(len(chunk), results)
                    return
                }

                lastErr = err
                log.Printf("[BATCH] Attempt %d failed: %v", attempt+1, err)
                time.Sleep(bp.config.RetryInterval)
            }

            errCh <- fmt.Errorf("batch processing failed after %d retries: %w",
                bp.config.RetryCount, lastErr)
        }(items[start:end])
    }

    wg.Wait()
    close(errCh)

    // 收集错误
    var finalErr error
    for err := range errCh {
        if err != nil {
            finalErr = err
        }
    }

    latency := time.Since(startTime)
    bp.stats.mu.Lock()
    bp.stats.TotalBatches++
    bp.stats.TotalItems += int64(batchSize)
    bp.stats.AvgBatchSize = float64(bp.stats.TotalItems) / float64(bp.stats.TotalBatches)
    bp.stats.AvgFlushLatency = time.Duration(
        (int64(bp.stats.AvgFlushLatency)*int64(bp.stats.TotalBatches-1) +
            int64(latency)) / int64(bp.stats.TotalBatches))
    bp.stats.mu.Unlock()

    return finalErr
}

func (bp *BatchProcessor) updateStats(total int, results []BatchItemResult) {
    bp.stats.mu.Lock()
    defer bp.stats.mu.Unlock()

    for _, r := range results {
        if r.Success {
            bp.stats.SuccessItems++
        } else {
            bp.stats.FailedItems++
        }
    }
}

// BatchStats 获取批处理统计
func (bp *BatchProcessor) BatchStats() BatchStats {
    bp.stats.mu.Lock()
    defer bp.stats.mu.Unlock()
    return bp.stats
}

六、基准测试框架

复制代码
// memory/optimization/benchmark.go
package optimization

import (
    "context"
    "fmt"
    "log"
    "math"
    "sort"
    "sync"
    "sync/atomic"
    "time"
)

// BenchmarkRunner 基准测试运行器
type BenchmarkRunner struct {
    config  BenchmarkConfig
    worker  func(ctx context.Context, id int, metrics *BenchmarkMetrics)
    metrics *BenchmarkMetrics
    report  *BenchmarkReport
}

type BenchmarkMetrics struct {
    totalOps     int64
    successOps   int64
    errorOps     int64
    latencies    []int64 // 纳秒
    opsByType    map[string]int64
    timelines    []TimelinePoint
    mu           sync.Mutex
}

func NewBenchmarkRunner(config BenchmarkConfig, worker func(ctx context.Context, id int, metrics *BenchmarkMetrics)) *BenchmarkRunner {
    return &BenchmarkRunner{
        config: config,
        worker: worker,
        metrics: &BenchmarkMetrics{
            opsByType: make(map[string]int64),
            latencies: make([]int64, 0, 100000),
        },
    }
}

// Run 运行基准测试
func (br *BenchmarkRunner) Run(ctx context.Context) (*BenchmarkReport, error) {
    log.Printf("[BENCHMARK] Starting benchmark: concurrency=%d, duration=%v",
        br.config.Concurrency, br.config.Duration)

    report := &BenchmarkReport{
        Config:    br.config,
        Timelines: make([]TimelinePoint, 0),
    }

    // 预热阶段
    if br.config.WarmupDuration > 0 {
        log.Printf("[BENCHMARK] Warming up for %v...", br.config.WarmupDuration)
        br.runPhase(ctx, br.config.WarmupDuration, true)
        // 重置指标
        br.metrics = &BenchmarkMetrics{
            opsByType: make(map[string]int64),
            latencies: make([]int64, 0, 100000),
        }
    }

    // 正式测试
    startTime := time.Now()
    br.runPhase(ctx, br.config.Duration, false)
    elapsed := time.Since(startTime)

    // 生成报告
    br.generateReport(report, elapsed)

    log.Printf("[BENCHMARK] Completed: totalOps=%d, throughput=%.2f ops/s, avgLatency=%v",
        report.TotalOps, report.Throughput, report.AvgLatency)

    return report, nil
}

// runPhase 运行一个阶段
func (br *BenchmarkRunner) runPhase(ctx context.Context, duration time.Duration, warmup bool) {
    var wg sync.WaitGroup
    reportTicker := time.NewTicker(br.config.ReportInterval)
    defer reportTicker.Stop()

    deadline := time.Now().Add(duration)
    ctx, cancel := context.WithDeadline(ctx, deadline)
    defer cancel()

    for i := 0; i < br.config.Concurrency; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            for {
                select {
                case <-ctx.Done():
                    return
                default:
                    br.worker(ctx, id, br.metrics)
                }
            }
        }(i)
    }

    // 定期报告
    if !warmup {
        go func() {
            for {
                select {
                case <-reportTicker.C:
                    br.recordTimeline()
                case <-ctx.Done():
                    return
                }
            }
        }()
    }

    wg.Wait()
}

// recordTimeline 记录时间线
func (br *BenchmarkRunner) recordTimeline() {
    br.metrics.mu.Lock()
    defer br.metrics.mu.Unlock()

    point := TimelinePoint{
        Timestamp: time.Now(),
        Throughput: float64(atomic.LoadInt64(&br.metrics.totalOps)),
        Errors:    atomic.LoadInt64(&br.metrics.errorOps),
    }

    if len(br.metrics.latencies) > 0 {
        sort.Slice(br.metrics.latencies, func(i, j int) bool {
            return br.metrics.latencies[i] < br.metrics.latencies[j]
        })
        point.Latency = float64(br.metrics.latencies[len(br.metrics.latencies)/2]) / 1e6 // 中位数
    }

    br.metrics.timelines = append(br.metrics.timelines, point)
}

// generateReport 生成测试报告
func (br *BenchmarkRunner) generateReport(report *BenchmarkReport, elapsed time.Duration) {
    br.metrics.mu.Lock()
    defer br.metrics.mu.Unlock()

    report.TotalOps = atomic.LoadInt64(&br.metrics.totalOps)
    report.Duration = elapsed
    report.ErrorCount = atomic.LoadInt64(&br.metrics.errorOps)

    if elapsed.Seconds() > 0 {
        report.Throughput = float64(report.TotalOps) / elapsed.Seconds()
    }

    if report.TotalOps > 0 {
        report.ErrorRate = float64(report.ErrorCount) / float64(report.TotalOps) * 100
    }

    // 延迟统计
    if len(br.metrics.latencies) > 0 {
        sorted := make([]int64, len(br.metrics.latencies))
        copy(sorted, br.metrics.latencies)
        sort.Slice(sorted, func(i, j int) bool {
            return sorted[i] < sorted[j]
        })

        totalLat := int64(0)
        for _, l := range sorted {
            totalLat += l
        }

        report.AvgLatency = time.Duration(totalLat / int64(len(sorted)))
        report.P50Latency = time.Duration(percentile(sorted, 50))
        report.P90Latency = time.Duration(percentile(sorted, 90))
        report.P99Latency = time.Duration(percentile(sorted, 99))
        report.MaxLatency = time.Duration(sorted[len(sorted)-1])
    }

    // 按类型统计
    report.OpsByType = make(map[string]int64)
    for k, v := range br.metrics.opsByType {
        report.OpsByType[k] = v
    }

    // 时间线
    report.Timelines = br.metrics.timelines

    br.report = report
}

// percentile 计算百分位数
func percentile(sorted []int64, pct float64) int64 {
    if len(sorted) == 0 {
        return 0
    }

    idx := int(math.Ceil(float64(len(sorted))*pct/100.0)) - 1
    if idx < 0 {
        idx = 0
    }
    if idx >= len(sorted) {
        idx = len(sorted) - 1
    }

    return sorted[idx]
}

// PrintReport 打印报告
func (br *BenchmarkRunner) PrintReport() {
    if br.report == nil {
        fmt.Println("No report available")
        return
    }

    fmt.Println("\n========================================")
    fmt.Println("         BENCHMARK REPORT")
    fmt.Println("========================================")
    fmt.Printf("Duration:       %v\n", br.report.Duration)
    fmt.Printf("Concurrency:    %d\n", br.report.Config.Concurrency)
    fmt.Printf("Total Ops:      %d\n", br.report.TotalOps)
    fmt.Printf("Throughput:     %.2f ops/s\n", br.report.Throughput)
    fmt.Printf("Avg Latency:    %v\n", br.report.AvgLatency)
    fmt.Printf("P50 Latency:    %v\n", br.report.P50Latency)
    fmt.Printf("P90 Latency:    %v\n", br.report.P90Latency)
    fmt.Printf("P99 Latency:    %v\n", br.report.P99Latency)
    fmt.Printf("Max Latency:    %v\n", br.report.MaxLatency)
    fmt.Printf("Error Count:    %d\n", br.report.ErrorCount)
    fmt.Printf("Error Rate:     %.2f%%\n", br.report.ErrorRate)
    fmt.Println("----------------------------------------")
    fmt.Println("Operations by type:")
    for opType, count := range br.report.OpsByType {
        fmt.Printf("  %s: %d\n", opType, count)
    }
    fmt.Println("========================================\n")
}

七、性能优化实战

复制代码
// memory/optimization/optimizer.go
package optimization

import (
    "context"
    "fmt"
    "log"
    "runtime"
    "sync"
    "time"
)

// PerformanceOptimizer 性能优化器
type PerformanceOptimizer struct {
    config    OptimizationConfig
    cache     *MultiLevelCache
    pool      *ConnectionPool
    batchProc *BatchProcessor
    metrics   *OptimizerMetrics
}

type OptimizerMetrics struct {
    CacheHitRate    float64
    PoolUtilization float64
    BatchEfficiency float64
    GoroutineCount  int
    MemoryUsageMB   float64
    GCStats         runtime.MemStats
    updatedAt       time.Time
}

func NewPerformanceOptimizer(config OptimizationConfig, factory ConnFactory) *PerformanceOptimizer {
    po := &PerformanceOptimizer{
        config:  config,
        metrics: &OptimizerMetrics{},
    }

    // 初始化缓存
    po.cache = NewMultiLevelCache(config.Cache)

    // 初始化连接池
    po.pool = NewConnectionPool(config.Pool, factory, func(conn interface{}) bool {
        return true // 简化验证
    })

    // 初始化批处理器
    po.batchProc = NewBatchProcessor(config.Batch, func(ctx context.Context, items []BatchItem) ([]BatchItemResult, error) {
        results := make([]BatchItemResult, len(items))
        for i, item := range items {
            results[i] = BatchItemResult{
                Key:     item.Key,
                Success: true,
                Value:   item.Value,
            }
        }
        return results, nil
    })

    // 启动指标收集
    go po.metricsLoop()

    return po
}

// GetWithCache 带缓存的读取
func (po *PerformanceOptimizer) GetWithCache(ctx context.Context, key string) (interface{}, bool, error) {
    // 先从缓存读取
    value, found, err := po.cache.Get(ctx, key)
    if err != nil {
        log.Printf("[OPTIMIZER] Cache get error: %v", err)
    }
    if found {
        return value, true, nil
    }

    // 缓存未命中,从连接池获取连接读取
    pooled, err := po.pool.Borrow(ctx)
    if err != nil {
        return nil, false, fmt.Errorf("borrow connection: %w", err)
    }

    // 模拟读取数据
    value = fmt.Sprintf("data-for-%s", key)
    po.pool.Return(pooled, false)

    // 回填缓存
    if err := po.cache.Set(ctx, key, value, 5*time.Minute); err != nil {
        log.Printf("[OPTIMIZER] Cache set error: %v", err)
    }

    return value, true, nil
}

// BatchSaveWithPool 批量保存(使用连接池)
func (po *PerformanceOptimizer) BatchSaveWithPool(ctx context.Context, items []BatchItem) error {
    // 分批处理
    batchSize := po.config.Batch.MaxBatchSize
    for i := 0; i < len(items); i += batchSize {
        end := i + batchSize
        if end > len(items) {
            end = len(items)
        }

        chunk := items[i:end]

        // 使用连接池获取连接
        pooled, err := po.pool.Borrow(ctx)
        if err != nil {
            return fmt.Errorf("borrow connection for batch: %w", err)
        }

        // 批量写入
        for _, item := range chunk {
            if err := po.cache.Set(ctx, item.Key, item.Value, 0); err != nil {
                log.Printf("[OPTIMIZER] Cache set error: %v", err)
            }
        }

        po.pool.Return(pooled, false)
    }

    return nil
}

// AsyncWrite 异步写入
func (po *PerformanceOptimizer) AsyncWrite(ctx context.Context, key string, value interface{}) error {
    if !po.config.AsyncWrite.Enabled {
        // 同步写入
        return po.cache.Set(ctx, key, value, 0)
    }

    // 异步写入
    go func() {
        if err := po.cache.Set(ctx, key, value, 0); err != nil {
            log.Printf("[OPTIMIZER] Async write error: %v", err)
        }
    }()

    return nil
}

// GetMetrics 获取优化器指标
func (po *PerformanceOptimizer) GetMetrics() *OptimizerMetrics {
    po.metrics.updatedAt = time.Now()

    // 缓存命中率
    cacheStats := po.cache.Stats(context.Background())
    for _, stats := range cacheStats {
        po.metrics.CacheHitRate = stats.HitRate
        break
    }

    // 连接池利用率
    poolStats := po.pool.Stats()
    idle := poolStats["idle_count"].(int)
    active := poolStats["active_count"].(int)
    total := idle + active
    if total > 0 {
        po.metrics.PoolUtilization = float64(active) / float64(total) * 100
    }

    // Goroutine 数量
    po.metrics.GoroutineCount = runtime.NumGoroutine()

    // 内存使用
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    po.metrics.MemoryUsageMB = float64(m.Alloc) / 1024 / 1024
    po.metrics.GCStats = m

    return po.metrics
}

// metricsLoop 指标收集循环
func (po *PerformanceOptimizer) metricsLoop() {
    ticker := time.NewTicker(30 * time.Second)
    defer ticker.Stop()

    for range ticker.C {
        metrics := po.GetMetrics()
        log.Printf("[OPTIMIZER] CacheHitRate=%.1f%%, PoolUtil=%.1f%%, Goroutines=%d, Memory=%.1fMB",
            metrics.CacheHitRate, metrics.PoolUtilization,
            metrics.GoroutineCount, metrics.MemoryUsageMB)
    }
}

// Close 关闭优化器
func (po *PerformanceOptimizer) Close() {
    po.cache.Clear(context.Background())
    po.pool.Close()
    po.batchProc.Close()
}

八、生产坑位

# 坑位 现象 解决方案
1 缓存穿透​ 大量请求查询不存在的数据,直接打到数据库 布隆过滤器拦截;缓存空值(短 TTL);限流降级
2 缓存雪崩​ 大量缓存同时过期,请求涌向后端 过期时间加随机偏移;本地缓存兜底;熔断保护
3 缓存击穿​ 热点 key 过期瞬间高并发请求 互斥锁重建缓存;永不过期 + 异步刷新;分布式锁
4 连接池泄漏​ 连接未正确归还,池子逐渐耗尽 始终使用 defer Return;超时强制回收;监控告警
5 批量操作超时​ 单个批次过大导致处理超时 拆分批次(≤1000条);设置超时时间;渐进式提交
6 异步写入丢失​ 异步写入失败后数据丢失 重试队列 + 持久化;确认机制;最终一致性补偿
7 GC 压力过大​ 大量临时对象导致频繁 GC 对象池复用;减少内存分配;调整 GOGC 参数
8 锁竞争激烈​ 高并发下互斥锁成为瓶颈 分段锁;读写分离;无锁数据结构(CAS)

九、评测指标

指标 说明 目标值 测量方式
缓存命中率 L1 缓存命中比例 ≥ 90% 缓存统计
缓存穿透率 无效查询比例 < 1% 布隆过滤器统计
连接池利用率 活跃连接占比 60-80% 连接池统计
连接等待时间 获取连接的 P99 延迟 < 5ms 连接池统计
批量效率 批量处理 vs 单条处理提速比 ≥ 5x 对比测试
异步写入延迟 异步写入到落地的延迟 < 100ms 追踪日志
吞吐量 每秒处理的操作数 ≥ 10000 ops/s 基准测试
P99 延迟 99% 操作的延迟 < 50ms 基准测试
GC 暂停时间 单次 GC STW 时间 < 10ms Go trace

十、使用示例

复制代码
// examples/optimization_demo.go
package main

import (
    "context"
    "fmt"
    "log"
    "math/rand"
    "time"

    "memory/optimization"
)

func main() {
    ctx := context.Background()

    fmt.Println("=== 记忆系统性能优化演示 ===\n")

    // 1. 初始化优化配置
    config := optimization.OptimizationConfig{
        Cache: optimization.CacheConfig{
            L1: optimization.CacheLayerConfig{
                Enabled:  true,
                Capacity: 10000,
                TTL:      5 * time.Minute,
            },
            L2: optimization.CacheLayerConfig{
                Enabled: false, // 跳过 Redis
            },
            L3: optimization.CacheLayerConfig{
                Enabled: false,
            },
        },
        Pool: optimization.ConnectionPoolConfig{
            MaxIdle:       10,
            MaxActive:     100,
            IdleTimeout:   5 * time.Minute,
            WaitTimeout:   1 * time.Second,
            MaxLifetime:   30 * time.Minute,
            HealthCheckInterval: 30 * time.Second,
        },
        Batch: optimization.BatchConfig{
            MaxBatchSize:  100,
            FlushInterval: 100 * time.Millisecond,
            Concurrency:   4,
            RetryCount:    2,
            RetryInterval: 100 * time.Millisecond,
        },
        AsyncWrite: optimization.AsyncWriteConfig{
            Enabled:       true,
            BufferSize:    1000,
            FlushWorkers:  2,
            FlushInterval: 500 * time.Millisecond,
        },
    }

    // 2. 初始化性能优化器
    optimizer := optimization.NewPerformanceOptimizer(config, func(ctx context.Context) (interface{}, error) {
        return "connection", nil
    })
    defer optimizer.Close()
    fmt.Println("✓ 性能优化器已初始化")

    // 3. 演示多级缓存
    fmt.Println("\n=== 多级缓存演示 ===")

    // 写入缓存
    for i := 0; i < 100; i++ {
        key := fmt.Sprintf("key-%d", i)
        value := fmt.Sprintf("value-%d", i)
        if err := optimizer.AsyncWrite(ctx, key, value); err != nil {
            log.Printf("Write error: %v", err)
        }
    }
    fmt.Println("✓ 已写入 100 条缓存数据")

    // 读取缓存(大部分命中)
    hits := 0
    misses := 0
    for i := 0; i < 200; i++ {
        key := fmt.Sprintf("key-%d", rand.Intn(150)) // 50% 可能不存在
        _, found, err := optimizer.GetWithCache(ctx, key)
        if err != nil {
            log.Printf("Get error: %v", err)
            continue
        }
        if found {
            hits++
        } else {
            misses++
        }
    }
    fmt.Printf("缓存读取: 命中=%d, 未命中=%d, 命中率=%.1f%%\n", hits, misses, float64(hits)/float64(hits+misses)*100)

    // 4. 演示连接池
    fmt.Println("\n=== 连接池演示 ===")
    poolStats := optimizer.GetMetrics()
    fmt.Printf("连接池利用率: %.1f%%\n", poolStats.PoolUtilization)

    // 5. 演示批量操作
    fmt.Println("\n=== 批量操作演示 ===")
    batchItems := make([]optimization.BatchItem, 50)
    for i := 0; i < 50; i++ {
        batchItems[i] = optimization.BatchItem{
            Key:   fmt.Sprintf("batch-key-%d", i),
            Value: fmt.Sprintf("batch-value-%d", i),
        }
    }

    startTime := time.Now()
    if err := optimizer.BatchSaveWithPool(ctx, batchItems); err != nil {
        log.Printf("Batch save error: %v", err)
    }
    batchLatency := time.Since(startTime)
    fmt.Printf("批量保存 50 条耗时: %v (单条平均 %.2f µs)\n",
        batchLatency, float64(batchLatency.Microseconds())/50)

    // 6. 运行基准测试
    fmt.Println("\n=== 基准测试演示 ===")

    benchConfig := optimization.BenchmarkConfig{
        Duration:       5 * time.Second,
        Concurrency:    10,
        Operations:     []string{"get", "set"},
        ReadRatio:      0.8,
        WriteRatio:     0.2,
        DataSize:       128,
        WarmupDuration: 1 * time.Second,
        ReportInterval: 1 * time.Second,
    }

    runner := optimization.NewBenchmarkRunner(benchConfig, func(ctx context.Context, id int, metrics *optimization.BenchmarkMetrics) {
        key := fmt.Sprintf("bench-key-%d", rand.Intn(1000))

        if rand.Float64() < 0.8 {
            // 读操作
            start := time.Now()
            optimizer.GetWithCache(ctx, key)
            latency := time.Since(start).Nanoseconds()

            metrics.Mu.Lock()
            metrics.TotalOps++
            metrics.SuccessOps++
            metrics.Latencies = append(metrics.Latencies, latency)
            metrics.OpsByType["get"]++
            metrics.Mu.Unlock()
        } else {
            // 写操作
            start := time.Now()
            optimizer.AsyncWrite(ctx, key, fmt.Sprintf("value-%d", rand.Intn(1000)))
            latency := time.Since(start).Nanoseconds()

            metrics.Mu.Lock()
            metrics.TotalOps++
            metrics.SuccessOps++
            metrics.Latencies = append(metrics.Latencies, latency)
            metrics.OpsByType["set"]++
            metrics.Mu.Unlock()
        }
    })

    report, err := runner.Run(ctx)
    if err != nil {
        log.Fatalf("Benchmark failed: %v", err)
    }

    runner.PrintReport()

    // 7. 查看优化器指标
    fmt.Println("\n=== 优化器最终指标 ===")
    finalMetrics := optimizer.GetMetrics()
    fmt.Printf("缓存命中率: %.1f%%\n", finalMetrics.CacheHitRate)
    fmt.Printf("连接池利用率: %.1f%%\n", finalMetrics.PoolUtilization)
    fmt.Printf("Goroutine 数: %d\n", finalMetrics.GoroutineCount)
    fmt.Printf("内存使用: %.1f MB\n", finalMetrics.MemoryUsageMB)
    fmt.Printf("GC 次数: %d\n", finalMetrics.GCStats.NumGC)

    fmt.Println("\n演示完成!")
}

十一、本讲总结

复制代码
┌──────────────────────────────────────────────────────────────────────────┐
│                    第9讲 核心收获                                          │
│                                                                           │
│  ✅ 实现了多级缓存:                                                       │
│     - L1 本地 LRU 缓存(带 TTL 过期)                                     │
│     - L2 Redis 分布式缓存(占位)                                         │
│     - L3 本地磁盘缓存(占位)                                             │
│     - 逐级查找 + 向上回填策略                                            │
│                                                                           │
│  ✅ 实现了连接池:                                                         │
│     - 通用连接池(工厂模式)                                              │
│     - 空闲连接预创建                                                      │
│     - 健康检查 + 自动清理                                                │
│     - 完整的统计指标                                                      │
│                                                                           │
│  ✅ 实现了批量操作:                                                       │
│     - 自动缓冲 + 定时刷新                                                 │
│     - 并发处理 + 重试机制                                                │
│     - 背压控制                                                            │
│                                                                           │
│  ✅ 实现了基准测试框架:                                                   │
│     - 预热阶段                                                            │
│     - 并发压测                                                            │
│     - 延迟百分位统计                                                      │
│     - 详细报告输出                                                        │
│                                                                           │
│  ✅ 覆盖了 8 个生产坑位与解决方案                                         │
│  ✅ 定义了性能优化的关键评测指标                                          │
│                                                                           │
└──────────────────────────────────────────────────────────────────────────┘

十二、下一讲预告

第10讲:《记忆系统的配置管理与热更新------YAML 配置、环境变量、配置中心与无损重启》

你将学到:

  • 分层配置管理(默认值 → 配置文件 → 环境变量 → 配置中心)
  • Viper 配置库深度使用
  • 配置热更新(监听文件变化 + 信号处理)
  • 配置中心集成(etcd/Consul)
  • 无损重启(Graceful Restart)
  • 配置版本管理与回滚

🧰 开发之余的小工具推荐

在编写 YAML 配置文件和基准测试报告时,经常需要进行格式校验和数据转换。zz365.top 的 YAML/JSON 互转工具可以快速将你的 memory.yaml 配置在两种格式间转换,方便在不同场景下使用。其文本差异比较工具则可以对比不同版本的配置文件变化,帮助你快速定位配置变更引入的问题。所有处理均在浏览器本地完成,不会泄露你的配置内容。

相关推荐
MoRanzhi12032 小时前
第4篇 · 使用 PyQt5 实现 2048:平滑动画与性能优化
python·性能优化·qtimer·pyqt5·qpainter·gui动画·2048游戏
星夜孤帆2 小时前
Redis缓存击穿与分布式锁实战:专栏目录、源码与实验说明
redis·分布式·缓存
余槐i3 小时前
yt-dlp 线程开到 16 反而更慢:1000 个视频的实测与限速原因
性能优化·ffmpeg·自动化·开发工具·yt-dlp
西红柿炖牛腩3543 小时前
3D 模型压缩脚本又报错又配环境?换个不用维护的方案
javascript·3d·性能优化
SHENGWEI胜为3 小时前
NVMe SSD写入速度突然下降?从SLC缓存耗尽到温度降速的排查方法
网络·缓存
打工仔折腾 AI3 小时前
极空间部署Portainer实战:绕过Socket权限、解决9000端口冲突与固定内网访问
人工智能·后端·python·性能优化
clz13145213 小时前
ruoyi-cloud功能开发demo实战:三级联动 Redis Hash 缓存查看器
redis·缓存·哈希算法
lexiangqicheng4 小时前
前端高阶面试核心通关指南:深入解析Vue3与React18底层原理及性能优化
前端·面试·性能优化
杨运交4 小时前
080-缓存模块-Spring Cache缓存键前缀设计与租户隔离实践
java·spring·缓存