一、性能优化架构
┌──────────────────────────────────────────────────────────────────────────────┐
│ 记忆系统性能优化架构 │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 客户端层 (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 配置在两种格式间转换,方便在不同场景下使用。其文本差异比较工具则可以对比不同版本的配置文件变化,帮助你快速定位配置变更引入的问题。所有处理均在浏览器本地完成,不会泄露你的配置内容。