选sync.map还是bigcache取决于场景:纯读(如配置、黑白名单)用sync.map,轻量无依赖;高频读写或value>1kb、写qps>1k/s时必须用bigcache,其分片+内存池设计可支撑单核50w+ qps,但value须为[]byte且不支持遍历与原子操作。

本地缓存用 bigcache 还是 sync.Map?
选错会直接拖慢网关吞吐量。高频请求下,sync.Map 在写多场景(比如缓存频繁更新)会出现锁竞争加剧、GC压力上升;而 bigcache 通过分片 + 内存池设计,能把单核 QPS 提升到 50w+,但代价是不支持值类型直接序列化,必须是 []byte。
实操建议:
- 纯读场景(如静态路由配置、黑白名单)用
sync.Map,代码少、无依赖 - 热点接口响应缓存(如
/api/v1/product/123)必须用bigcache,尤其当 value 大于 1KB 或并发写 >1k/s 时 - 别把
bigcache当通用 map 用——它不支持遍历、不支持原子增减,只适合“查+设+删”三操作 - 初始化时预估容量:比如预计缓存 10 万个 key,平均 value 2KB,则
shards设为 512,maxEntrySize至少 2048
go-redis/v9 客户端连接池怎么配才不超时?
网关层 Redis 连接池配置不当,会导致大量请求卡在 redis.Client.Get 上,表现就是 P99 延迟突然跳到 500ms+,但 CPU 和 Redis 本身负载正常。
关键参数不是 PoolSize,而是 MinIdleConns 和 MaxConnAge:
-
PoolSize设为 32~64 即可,过高反而增加 Redis 端连接管理开销 -
MinIdleConns必须 ≥ 4,否则突发流量来临时要重新建连,触发 TCP 握手延迟 -
MaxConnAge设为 30m,避免长连接因网络中间设备(如 SLB)静默断连后,客户端仍往死连接发命令 - 务必开启
ReadTimeout和WriteTimeout,都设为 100ms,超时立即失败而非阻塞
缓存穿透和击穿怎么用网关层逻辑挡掉?
数据库还没扛上,网关就先被打挂了——这是没在缓存未命中路径加保护的典型症状。不能只靠 Redis 的布隆过滤器或空值缓存,网关自身得有兜底。
实操要点:
- 对所有 GET 接口启用「本地互斥锁」:用
singleflight.Group包裹回源逻辑,同一 key 的并发请求只放行一个去查后端 - 空值缓存必须带随机 TTL(比如 60±10s),否则所有攻击请求会在同一秒集中失效,变成缓存雪崩
- 对非法 ID(如负数、超长字符串)直接拦截返回 400,不走任何缓存或后端,这类请求占穿透流量的 70% 以上
- 不要在网关里做布隆过滤器——它需要全量 key 加载到内存,网关实例重启就失效,且无法实时同步变更
缓存一致性用「先删缓存再更新 DB」还是反过来?
在网关层做写操作协调几乎不可能,真正可行的是把一致性逻辑下沉到业务服务内部。网关只负责「读路径」缓存,写请求一律透传,由后端服务自己决定何时删/更新缓存。
所以网关侧唯一要做的,是识别出哪些请求是写操作,并跳过缓存:
- 检查 HTTP method:除
GET和HEAD外,其他一律不查缓存、不写缓存 - 检查 path pattern:比如匹配
/api/v1/order/*且 method 是POST,直接 bypass cache middlewares - 别信 header 里的
X-Cache-Control: no-cache——攻击者能伪造,只以 method + path 为准 - 如果业务要求强一致(如支付结果查询),网关可支持「强制回源」query 参数,例如
?force_refresh=1,但需白名单校验
最易被忽略的一点:网关的本地缓存和 Redis 缓存必须用同一套 key 生成规则,否则回源更新后,两个缓存层 key 对不上,永远不一致。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











