Theine - 新一代高性能&高命中率泛型内存缓存

2023-04-14 10:04:43 +08:00
 matrix1010

先上链接和 benchmarks:

https://github.com/Yiling-J/theine-go

cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz

BenchmarkGetTheineParallel-12           32432190                36.39 ns/op            0 B/op          0 allocs/op
BenchmarkGetRistrettoParallel-12        63978058                18.86 ns/op           17 B/op          1 allocs/op
BenchmarkSetTheineParallel-12           20791834                84.49 ns/op            0 B/op          0 allocs/op
BenchmarkSetRistrettoParallel-12        23354626                65.53 ns/op          116 B/op          3 allocs/op
BenchmarkZipfTheineParallel-12          14771362                74.72 ns/op            1 B/op          0 allocs/op
BenchmarkZipfRistrettoParallel-12       21031435                61.82 ns/op          100 B/op          3 allocs/op

由于充分利用 sync pool 以及 atomic ,Theine 的 GC 压力很低,同时有着和 Ristretto 同一数量级的性能。

相比于 Ristretto ,Theine 最大的特点其实是极高的缓存命中率,benchmark 结果都是图片,可以直接去 README 看: hit-ratios。简单来说 Ristretto 是通过丢弃请求来达到高性能,代价就是高写入下大量 Set 请求丢弃导致缓存命中率大幅下降。而 Theine 则通过合理的架构避免了这个问题。

同时 Theine 也有 Python 版本: https://github.com/Yiling-J/theine. 所以你也许会觉得看到这个名字眼熟。Theine-Go 的 TinyLFU 部分其实是直接从 Python 版本转过来的,但在提高性能方面 Python 和 Go 版本的 Theine 都根据对应的语言特性做了优化

3549 次点击
所在节点    Go 编程语言
26 条回复
artnowben
2023-04-14 10:08:35 +08:00
请教一下应用场景,学习下,谢谢
matrix1010
2023-04-14 10:11:05 +08:00
@artnowben 应用场景可参考同类的[caffeine]( https://github.com/ben-manes/caffeine), [ristretto]( https://github.com/dgraph-io/ristretto). 简单来说存在内存里就是快,同时不需要序列化 /反序列化。但内存空间有限,所以要想办法提高缓存命中率
victorc
2023-04-14 11:37:05 +08:00
这方向属于做 mini-mini 市场,缓存的刚需是基于分布式缓存,这是云原生-微服务-无状态架构浪潮推动的。in-process ,一个 map 不就行了
matrix1010
2023-04-14 12:10:46 +08:00
@victorc 很多 web 框架都支持内存缓存以及多级缓存,毫无疑问内存缓存的性能远高于分布式缓存。另一方面对于数据库或者持久化 KV ,一般也都有内存缓存层来提高性能,比如 pebble 就是用的 clock pro 。当然市场 /浪潮什么的作为 cto 可能比较关心,但我作为普通开发人员还是致力于写出高性能并且有点意思的东西
Kould
2023-04-14 13:58:12 +08:00
感觉不错
victorc
2023-04-14 16:19:12 +08:00
@matrix1010 性能不是首先考虑项,微服务:多个节点+不保存状态,只能用基于网络的缓存,就是大用特用 redis 。

从整个架构来评估性能,很少会去抠某一个 in-memory cache 的 get/set 性能,time cost 大头不在这里
matrix1010
2023-04-14 16:35:46 +08:00
@victorc 你要说微服务只能用网络缓存有点武断了,唯一没法用内存缓存的情况就是 serverless 。至于实际用什么,怎么用完全取决于产品的技术需求和公司的实际情况。
qile1
2023-04-14 16:44:33 +08:00
@matrix1010 现在我想 fastapi 里面的医生字典和科室字典能不能放到这个缓存里面,当我更新字典时候能不能更新字典,或者用户登录的 token 能不能放这里,放这里怎么获取有没有方法?能不能当 radis 用?
jorneyr
2023-04-14 16:50:22 +08:00
@matrix1010 微服务,负载均衡的请求下,一个请求可能被路由到不同的服务,不用网络缓存,服务之间应该怎么共享缓存,怎么做呢?
matrix1010
2023-04-14 16:52:42 +08:00
@qile1 你说的是 Python 版本吧。由于不确定你的架构,比如几台服务器,一致性需求等我没法直接回答你。简单来说你就可以把 Theine 当作一个字典,只是这个字典能设定最多存储多少内容和内容的过期时间。超过最大 size 这个字典会根据一定的规则自动删除数据。如果这样能满足你的需求你可以试一试
sadfQED2
2023-04-14 16:54:45 +08:00
单机缓存直接一个 map ,分布式缓存直接一个 redis
matrix1010
2023-04-14 17:00:57 +08:00
@jorneyr 比如你的微服务 A 需要从微服务 B 获取用户信息。获取时先检查本地缓存,如果本地缓存有就用,没有就从微服务 B 获取然后存入本地缓存。这里有 2 个问题,1 是一致性,如果你可以接受短期不一致设个几十秒的 ttl 自动过期就行,或者你可以通过 mq 之类的同步,但总会有一定的不一致。第 2 是并发问题,比如微服务 B 有 10 个 pods ,那这 10 个 pods 都没有缓存的话会同时发请求,如果你的单个微服务有几千个 pods 而且全部同时 miss 可能会瞬间有很大压力
FrankAdler
2023-04-14 19:36:34 +08:00
支持一下
djoiwhud
2023-04-14 19:44:07 +08:00
go 缓存只有两种。一种 redis ,一种 map 。
jorneyr
2023-04-14 20:11:39 +08:00
@matrix1010
同一个服务高可用呢,服务名一样,负载均衡的情况。
还有通过 mq 做缓存,太有想法了。
matrix1010
2023-04-14 20:12:29 +08:00
说缓存只有两种, redis 和 xxx 的,memcached 要哭了
matrix1010
2023-04-14 20:18:20 +08:00
@jorneyr 感觉没有理解你想表达什么。但就像我说的实际使用方法取决于你的产品和架构,我只是来推广一下我这个库而已
realpg
2023-04-14 20:29:40 +08:00
@matrix1010 #16
2023 年你还见过新建项目用 memcached 的么?
matrix1010
2023-04-14 20:59:17 +08:00
@realpg 我在的公司没用过。但至少 aws 的 whitepaper 还是挺推荐 memcached 的: https://docs.aws.amazon.com/whitepapers/latest/scale-performance-elasticache/memcached-vs.-redis.html
Kould
2023-04-19 16:06:37 +08:00
感觉不少人对缓存应用的概念有着不是很恰当的认知,楼主这类的缓存框架与 map 类似主要还是服务于业务层代码,而不少人一下子就开始以分布式的宏大场景去讨论且与 Redis 相提并论。离谱

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/932421

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX