先上链接和 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 都根据对应的语言特性做了优化
1
artnowben 2023-04-14 10:08:35 +08:00
请教一下应用场景,学习下,谢谢
|
2
matrix1010 OP @artnowben 应用场景可参考同类的[caffeine]( https://github.com/ben-manes/caffeine), [ristretto]( https://github.com/dgraph-io/ristretto). 简单来说存在内存里就是快,同时不需要序列化 /反序列化。但内存空间有限,所以要想办法提高缓存命中率
|
3
victorc 2023-04-14 11:37:05 +08:00
这方向属于做 mini-mini 市场,缓存的刚需是基于分布式缓存,这是云原生-微服务-无状态架构浪潮推动的。in-process ,一个 map 不就行了
|
4
matrix1010 OP @victorc 很多 web 框架都支持内存缓存以及多级缓存,毫无疑问内存缓存的性能远高于分布式缓存。另一方面对于数据库或者持久化 KV ,一般也都有内存缓存层来提高性能,比如 pebble 就是用的 clock pro 。当然市场 /浪潮什么的作为 cto 可能比较关心,但我作为普通开发人员还是致力于写出高性能并且有点意思的东西
|
5
Kould 2023-04-14 13:58:12 +08:00 1
感觉不错
|
6
victorc 2023-04-14 16:19:12 +08:00
@matrix1010 性能不是首先考虑项,微服务:多个节点+不保存状态,只能用基于网络的缓存,就是大用特用 redis 。
从整个架构来评估性能,很少会去抠某一个 in-memory cache 的 get/set 性能,time cost 大头不在这里 |
7
matrix1010 OP @victorc 你要说微服务只能用网络缓存有点武断了,唯一没法用内存缓存的情况就是 serverless 。至于实际用什么,怎么用完全取决于产品的技术需求和公司的实际情况。
|
8
qile1 2023-04-14 16:44:33 +08:00 via Android
@matrix1010 现在我想 fastapi 里面的医生字典和科室字典能不能放到这个缓存里面,当我更新字典时候能不能更新字典,或者用户登录的 token 能不能放这里,放这里怎么获取有没有方法?能不能当 radis 用?
|
9
jorneyr 2023-04-14 16:50:22 +08:00
@matrix1010 微服务,负载均衡的请求下,一个请求可能被路由到不同的服务,不用网络缓存,服务之间应该怎么共享缓存,怎么做呢?
|
10
matrix1010 OP @qile1 你说的是 Python 版本吧。由于不确定你的架构,比如几台服务器,一致性需求等我没法直接回答你。简单来说你就可以把 Theine 当作一个字典,只是这个字典能设定最多存储多少内容和内容的过期时间。超过最大 size 这个字典会根据一定的规则自动删除数据。如果这样能满足你的需求你可以试一试
|
11
sadfQED2 2023-04-14 16:54:45 +08:00 via Android
单机缓存直接一个 map ,分布式缓存直接一个 redis
|
12
matrix1010 OP @jorneyr 比如你的微服务 A 需要从微服务 B 获取用户信息。获取时先检查本地缓存,如果本地缓存有就用,没有就从微服务 B 获取然后存入本地缓存。这里有 2 个问题,1 是一致性,如果你可以接受短期不一致设个几十秒的 ttl 自动过期就行,或者你可以通过 mq 之类的同步,但总会有一定的不一致。第 2 是并发问题,比如微服务 B 有 10 个 pods ,那这 10 个 pods 都没有缓存的话会同时发请求,如果你的单个微服务有几千个 pods 而且全部同时 miss 可能会瞬间有很大压力
|
13
FrankAdler 2023-04-14 19:36:34 +08:00
支持一下
|
14
djoiwhud 2023-04-14 19:44:07 +08:00 via Android
go 缓存只有两种。一种 redis ,一种 map 。
|
15
jorneyr 2023-04-14 20:11:39 +08:00
|
16
matrix1010 OP 说缓存只有两种, redis 和 xxx 的,memcached 要哭了
|
17
matrix1010 OP @jorneyr 感觉没有理解你想表达什么。但就像我说的实际使用方法取决于你的产品和架构,我只是来推广一下我这个库而已
|
18
realpg 2023-04-14 20:29:40 +08:00
@matrix1010 #16
2023 年你还见过新建项目用 memcached 的么? |
19
matrix1010 OP @realpg 我在的公司没用过。但至少 aws 的 whitepaper 还是挺推荐 memcached 的: https://docs.aws.amazon.com/whitepapers/latest/scale-performance-elasticache/memcached-vs.-redis.html
|
20
Kould 2023-04-19 16:06:37 +08:00
感觉不少人对缓存应用的概念有着不是很恰当的认知,楼主这类的缓存框架与 map 类似主要还是服务于业务层代码,而不少人一下子就开始以分布式的宏大场景去讨论且与 Redis 相提并论。离谱
|
21
matrix1010 OP @Kould 这令我想到了这几天在 zhihu 上看到的帖子,游戏服务器为什么不用 Redis 。毕竟互联网天天都和 Redis 打交道,面试也是各种卷 Redis ,这么信仰 Redis 也挺正常
|
22
cuebyte 2023-04-22 05:46:33 +08:00 1
支持!
|
23
zhujq 2023-04-25 17:21:12 +08:00 1
支持支持
|
24
zzl22100048 2023-04-28 00:01:08 +08:00
如果能加上一个过期回调就好了,这样可以当延迟队列用
|
25
matrix1010 OP @zzl22100048 最新版本已经加上回调了。不过由于 timingwheel 的特性过期回调触发的时间不是精确的,只能保证最终会发生
|
26
matrix1010 OP 顺带补充一点,Redis 的 client-side caching 其实就是 redis+local 两级 cache ,缓存失效时 client1->redis server->client2 发通知。有些 redis 的 client 没有这个功能,有些则使用简单 LRU, 这也是 Theine 的潜在使用场景。client-side caching 的设计可以看: https://redis.io/docs/manual/client-side-caching/#the-redis-implementation-of-client-side-caching
|