我们在开发 HTTP Server 的时候,经常有对接口内容做缓存的需求。例如,对于某些热点内容,我们希望做 1 分钟内的缓存。短期内缓存相同内容不会对业务造成实质影响,同时也会降低系统的整体负载。
有时我们需要把缓存逻辑放在 Server 内部,而非网关侧如 Nginx 等,是因为这样我们可以根据需要便捷地清除缓存,或者可以使用 Redis 等其他存储介质作为缓存后端。
这样的缓存场景无非是有缓存时从缓存取,无缓存时从下游服务取,并将数据放入缓存中。这其实是个非常通用的逻辑,应该可以将其抽象出来。从而缓存逻辑无需进侵入业务代码。
我常用的 HTTP 框架是 golang 的 gin 。gin 官方就有一个 cache 组件:github.com/gin-contrib/cache,但这个 cache 组件无论在性能还是接口设计上,都有一些不足之处。
因此,我重新设计了一套 cache 中间件: gin-cache。 从压测结果来看,其性能相比于 gin-contrib/cache
明显提升。
1
meshell 2021-06-18 16:21:02 +08:00
没看代码。问个问题,比如说如果根据用户不同缓存是怎么做,或者其它的不同?在中间件中取唯一码,生成不同的缓存 key?
|
2
cyhone OP @meshell 好问题。gin-cache 提供了两个快捷函数,CacheByPath 和 CacheByUri,如果用户的信息(比如 uid)就在 url 中,直接使用这两个函数就行。
如果需要从其他地方获取用户的唯一信息(例如 header 、body ),gin-cache 也支持用户自定义 KeyGenerator,这样可以自行写函数,根据不同请求,生成不同的 cache key |
3
xkeyideal 2021-06-18 16:40:40 +08:00
inmemory cache 以为是自己写的,没想到居然用的是”大名鼎鼎“的 https://github.com/patrickmn/go-cache fork 而来的库,在此呢,想劝你改掉,要么自己写一个,要么换个别的,换之前呢,类似 cache 这种代码量没多少,先阅读一下源码,看看有没有 bug 或性能问题。
看到此贴的人,在 inmemory 没有换底层库之前,不要使用此缓存中间件,否则线上 P0 随时等着你 |
4
meshell 2021-06-18 16:41:09 +08:00
@cyhone 针对当前用户标识,一般我们都在 logic server 里面拿 uid 。还有就是我是不是要告诉中间件,我这个请求需要缓存,需要根据啥规则缓存,时间等。这些是直接写在 cache middleware 里面?
|
5
xkeyideal 2021-06-18 16:45:40 +08:00
@meshell 再修复问题之前,先把在各个论坛上推广的帖子给屏蔽一下吧,inmemory 不能在较大数据量场景下使用,这是在给使用者制造故障,会把别人饭碗砸掉的
|
7
cyhone OP @xkeyideal 感谢反馈此库的问题。但需要说明的两点是:
1. 并不是 fork 了此库。而是使用了该库作为内置的 inmemory 实现,是属于依赖而非 fork 关系。 2. 如果觉得内置方案有问题,是可以替换为其他的自己的方案的。只要实现 persist.CacheStore 就可以 此外,感谢反馈,我先研究下这个库的问题。同时已将该贴下沉了一天~ |
8
cyhone OP @meshell 是的,这些信息需要提供给 cache middleware 。但目前自定义 cache 策略中,暂时只支持生成 cache key, 以及是否要进行 cache 。缓存时间目前沿用了 api 默认的缓存时间,暂不支持每个请求自定义,不过这个 case 感觉可以加一下~
|
9
xkeyideal 2021-06-18 17:23:01 +08:00 1
@cyhone 有问题反馈给作者是应该的,面向接口编程是好的设计,提供的实现方案也不应该有严重的潜在问题,这个库的问题之前有位线上出故障了,最终找到是此库的原因,还拿出来秀了一遍故障复盘。
如果找不到问题可以找我 inmemory cache 的实现无非需注意以下几点: 1 、考虑到大数据量时的查询性能与并发安全,直接解决方案就是分片存储与加锁 2 、此类 cache 一般都会涉及过期自动删除问题,如何最少化遍历或尽可能少的遍历,解决方案主流就是空间换时间,链表或堆 3 、结合实际项目需求做相应的需求封装,建议不要使用或少使用第三方开源的 cache (因为并不难写) 再提供一个可能存在问题的 cache 库,`muesli/cache2go` 三年前有位同事使用该库出现过 bug,原因好像是死锁,如今有无修复不清楚。 |