手撕 Golang 高性能内存缓存库 bigcache!( 三 )

  • 参考 freecache 的思路,用 ringbuffer 存 entry,绕过了 map 里存指针,简单瞄了一下代码,后面有空再研究一下(继续挖坑
  • 利用 Go 1.5+ 的特性:
  • 当 map 中的 key 和 value 都是基础类型时,GC 就不会扫到 map 里的 key 和 value
    最终他们采用了 map[uint64]uint32 作为 cacheShard 中的关键存储 。key 是 sharding 时得到的 uint64 hashed key,value 则只存 offset ,整体使用 FIFO 的 bytes queue,也符合按照时序淘汰的需求,非常精巧 。
    经过优化,bigcache 在 2000w 条记录下 GC 的表现
    go version go version go1.13 linux/arm64
    go run caches_gc_overhead_comparison.go Number of entries:  20000000GC pause for bigcache:  22.382827msGC pause for freecache:  41.264651msGC pause for map:  72.236853ms
    效果挺明显 , 但是对于低延时的服务来说 , 22ms 的 GC 时间还是很致命的 , 对象数还是尽量能控制住比较好 。
    5. 小结认真学完 bigcache 的代码 , 我们至少有以下几点收获:
    • 可以通过 sharding 来降低资源竞争
    • 可以用位运算来取余数做 sharding (需要是 2 的整数幂 - 1)
    • 避免 map 中出现指针、使用 go 基础类型可以显著降低 GC 压力、提升性能
    • bigcache 底层存储是 bytes queue,初始化时设置合理的配置项可以减少 queue 扩容的次数,提升性能
    参考资料
    • https://github.com/allegro/bigcache
    • 《allegro.tech blog - Writing a very fast cache service with millions of entries in Go》https://blog.allegro.tech/2016/03/writing-fast-cache-service-in-go.html
    • 《鸟窝 - 妙到颠毫: bigcache优化技巧》https://colobu.com/2019/11/18/how-is-the-bigcache-is-fast/
    • 《Stefanie Lai - Our Go Cache Library Choices》https://medium.com/codex/our-go-cache-library-choices-406f2662d6b
    • 《熊喵君的博客 - Golang 高性能 LocalCache:BigCache 设计与分析》https://pandaychen.Github.io/2020/03/03/BIGCACHE-ANALYSIS/
    • https://github.com/coocood/freecache
    • https://github.com/glycerine/offheap 堆外内存
    本文转载自微信公众号「 翔叔架构笔记」

    【手撕 Golang 高性能内存缓存库 bigcache!】


    推荐阅读