在微服务架构中,缓存是提升系统性能的利器。L2Cache作为二级缓存解决方案,通过本地缓存(如Caffeine)和分布式缓存(如Redis)的组合使用,能够有效解决单一缓存方案的局限性。我经历过一个电商项目,当大促期间用户信息查询量暴增时,纯Redis方案出现了明显的网络瓶颈,而引入L2Cache后性能提升了近3倍。
L2Cache的独特之处在于它的"智能分层"设计。高频访问的数据会自动驻留在本地内存,减少网络开销;低频数据则存储在分布式缓存,保证内存利用率。这种设计特别适合包含多种数据访问模式的复杂系统,比如同时存在热点商品数据和冷门供应商信息的电商平台。
用户基本信息是典型的读多写少数据。在我们的社交APP项目中,用户profile的读取QPS峰值达到5万+,但每天更新不到10次。针对这种场景,我推荐这样配置:
yaml复制l2cache:
config:
defaultConfig:
cacheType: composite
composite:
l1CacheType: caffeine
l2CacheType: redis
l1AllOpen: true
caffeine:
defaultSpec: "initialCapacity=1000,maximumSize=50000,refreshAfterWrite=30m,recordStats"
关键点在于:
实测中,这种配置使得用户信息的平均响应时间从23ms降到了2ms。有个坑要注意:当用户量超过maximumSize时,Caffeine会基于LFU算法淘汰缓存,可能导致缓存穿透,建议配合布隆过滤器使用。
商品价格数据更新频率中等(每天约1000次),但要求强一致性。我们在跨境电商项目中这样配置:
yaml复制goodsPriceCache:
cacheType: redis
redis:
lock: true
tryLock: true
expireTime: 3600000
expireTimeCacheNameMap:
goodsPriceCache: 86400000
这里的关键选择是:
实际运行中发现,当价格批量更新时,频繁的锁竞争会导致性能下降。后来我们增加了batchPageSize参数,将批量操作改为分页执行:
yaml复制redis:
batchPageSize: 50
品牌数据往往呈现明显的二八分布。我们监测到一个电商平台中,前20%的品牌占据了80%的访问量。针对这种场景,热key探测+本地缓存的组合效果最好:
yaml复制hotkey:
type: sentinel
sentinel:
default-rule:
grade: 1
count: 100
durationInSec: 5
rules:
- resource: hotBrandCache
count: 500
durationInSec: 10
brandCache:
cacheType: composite
composite:
l1CacheType: caffeine
l2CacheType: redis
l1Manual: true
caffeine:
specs:
hotBrandCache: "initialCapacity=100,maximumSize=1000,refreshAfterWrite=5m"
这个配置实现了:
在分布式环境下,本地缓存的同步是个难题。我们对比过Redis pubsub和Kafka两种方案:
| 方案 | 延迟 | 可靠性 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|
| Redis pubsub | <1ms | 最终一致 | 简单 | 中小规模集群 |
| Kafka | 10-50ms | 强一致 | 复杂 | 大规模跨机房部署 |
最终选择了Redis方案,配置如下:
yaml复制cacheSyncPolicy:
type: redis
topic: l2cache_sync
这里有个实用技巧:在微服务架构中,建议按业务域划分不同的topic,比如"user_cache_sync"、"product_cache_sync",避免单一topic压力过大。
缓存过期时间的设置需要精细设计。我们的最佳实践是:
示例配置:
yaml复制defaultConfig:
useL1ReplaceL2ExpireTime: false
caffeine:
specs:
userSessionCache: "expireAfterWrite=10m"
redis:
expireTimeCacheNameMap:
userSessionCache: 1800000
productCatalogCache: 86400000
缓存系统需要完善的降级策略。我们总结了几种常见场景的处理方案:
yaml复制defaultConfig:
allowNullValues: true
nullValueExpireTimeSeconds: 30
java复制// 在代码中添加随机偏移量
int expireTime = 3600000 + new Random().nextInt(600000);
yaml复制redis:
lock: true
tryLock: true
在内存受限的环境中,我们通过以下配置将内存占用降低了40%:
yaml复制caffeine:
defaultSpec: "maximumSize=10000,softValues"
关键参数:
对于批量查询场景(如商品详情页),我们改进了批量加载策略:
yaml复制redis:
batchPageSize: 100
composite:
l2BatchPut: true
l2BatchEvict: true
配合代码中的分批处理:
java复制public Map<String, Product> batchGetProducts(List<String> ids) {
return cacheLoader.batchGetOrLoad(ids,
missedIds -> productDAO.batchQuery(missedIds));
}
完善的监控是性能调优的基础。我们建议采集这些指标:
配置示例:
yaml复制caffeine:
defaultSpec: "recordStats"
在Spring Boot中可以通过CacheStatistics可视化这些数据。