V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
matrix1010
V2EX  ›  Go 编程语言

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

  •  
  •   matrix1010 ·
    Yiling-J · 349 天前 · 3029 次点击
    这是一个创建于 349 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先上链接和 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 都根据对应的语言特性做了优化

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

    从整个架构来评估性能,很少会去抠某一个 in-memory cache 的 get/set 性能,time cost 大头不在这里
    matrix1010
        7
    matrix1010  
    OP
       349 天前
    @victorc 你要说微服务只能用网络缓存有点武断了,唯一没法用内存缓存的情况就是 serverless 。至于实际用什么,怎么用完全取决于产品的技术需求和公司的实际情况。
    qile1
        8
    qile1  
       349 天前 via Android
    @matrix1010 现在我想 fastapi 里面的医生字典和科室字典能不能放到这个缓存里面,当我更新字典时候能不能更新字典,或者用户登录的 token 能不能放这里,放这里怎么获取有没有方法?能不能当 radis 用?
    jorneyr
        9
    jorneyr  
       349 天前
    @matrix1010 微服务,负载均衡的请求下,一个请求可能被路由到不同的服务,不用网络缓存,服务之间应该怎么共享缓存,怎么做呢?
    matrix1010
        10
    matrix1010  
    OP
       349 天前
    @qile1 你说的是 Python 版本吧。由于不确定你的架构,比如几台服务器,一致性需求等我没法直接回答你。简单来说你就可以把 Theine 当作一个字典,只是这个字典能设定最多存储多少内容和内容的过期时间。超过最大 size 这个字典会根据一定的规则自动删除数据。如果这样能满足你的需求你可以试一试
    sadfQED2
        11
    sadfQED2  
       349 天前 via Android
    单机缓存直接一个 map ,分布式缓存直接一个 redis
    matrix1010
        12
    matrix1010  
    OP
       349 天前
    @jorneyr 比如你的微服务 A 需要从微服务 B 获取用户信息。获取时先检查本地缓存,如果本地缓存有就用,没有就从微服务 B 获取然后存入本地缓存。这里有 2 个问题,1 是一致性,如果你可以接受短期不一致设个几十秒的 ttl 自动过期就行,或者你可以通过 mq 之类的同步,但总会有一定的不一致。第 2 是并发问题,比如微服务 B 有 10 个 pods ,那这 10 个 pods 都没有缓存的话会同时发请求,如果你的单个微服务有几千个 pods 而且全部同时 miss 可能会瞬间有很大压力
    FrankAdler
        13
    FrankAdler  
       349 天前
    支持一下
    djoiwhud
        14
    djoiwhud  
       349 天前 via Android
    go 缓存只有两种。一种 redis ,一种 map 。
    jorneyr
        15
    jorneyr  
       349 天前
    @matrix1010
    同一个服务高可用呢,服务名一样,负载均衡的情况。
    还有通过 mq 做缓存,太有想法了。
    matrix1010
        16
    matrix1010  
    OP
       349 天前
    说缓存只有两种, redis 和 xxx 的,memcached 要哭了
    matrix1010
        17
    matrix1010  
    OP
       349 天前
    @jorneyr 感觉没有理解你想表达什么。但就像我说的实际使用方法取决于你的产品和架构,我只是来推广一下我这个库而已
    realpg
        18
    realpg  
       349 天前
    @matrix1010 #16
    2023 年你还见过新建项目用 memcached 的么?
    matrix1010
        19
    matrix1010  
    OP
       348 天前
    @realpg 我在的公司没用过。但至少 aws 的 whitepaper 还是挺推荐 memcached 的: https://docs.aws.amazon.com/whitepapers/latest/scale-performance-elasticache/memcached-vs.-redis.html
    Kould
        20
    Kould  
       344 天前
    感觉不少人对缓存应用的概念有着不是很恰当的认知,楼主这类的缓存框架与 map 类似主要还是服务于业务层代码,而不少人一下子就开始以分布式的宏大场景去讨论且与 Redis 相提并论。离谱
    matrix1010
        21
    matrix1010  
    OP
       344 天前
    @Kould 这令我想到了这几天在 zhihu 上看到的帖子,游戏服务器为什么不用 Redis 。毕竟互联网天天都和 Redis 打交道,面试也是各种卷 Redis ,这么信仰 Redis 也挺正常
    cuebyte
        22
    cuebyte  
       341 天前   ❤️ 1
    支持!
    zhujq
        23
    zhujq  
       338 天前   ❤️ 1
    支持支持
    zzl22100048
        24
    zzl22100048  
       335 天前
    如果能加上一个过期回调就好了,这样可以当延迟队列用
    matrix1010
        25
    matrix1010  
    OP
       335 天前 via iPhone
    @zzl22100048 最新版本已经加上回调了。不过由于 timingwheel 的特性过期回调触发的时间不是精确的,只能保证最终会发生
    matrix1010
        26
    matrix1010  
    OP
       331 天前
    顺带补充一点,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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3057 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:46 · PVG 20:46 · LAX 05:46 · JFK 08:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.