bigcache源码解析

1. 设计目标

Bigcache 是用 Golang 实现的本地内存缓存的开源库,主打的就是可缓存数据量大,查询速度快。 在其官方的介绍文章《 Writing a very fast cache service with millions of entries in Go 》一文中,明确提出的 bigcache 的设计目标:

  1. 多: 缓存的元素数量非常大,可以达到百万级或千万级。
  2. 快: 对延迟有非常高的要求,平均延迟要求在 5 毫秒以内。redis 、memcached 之类的就不在考虑范围内了,毕竟用 Redis 还要多走一遍网络 IO 。
  3. 稳: 99.9 分位延迟应在 10 毫秒左右,99.999 分位延迟应在 400 毫秒左右。

目前有许多开源的 cache 库,大部分都是基于 map 实现的,例如 go-cache,ttl-cache 等。bigcache 明确指出,当数据量巨大时,直接基于 map 实现的 cache 库将出现严重的性能问题,这也是他们设计了一个全新的 cache 库的原因。

本文将通过分析 bigcache v3.1.0 的源码,揭秘 bigcache 如何解决现有 map 库的性能缺陷,以极致的性能优化,实现超高性能的缓存库。

2. 整体原理

2.1. 时序图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.1.1. 为什么分片数需要是2的幂次

这样分片数减1之后,前几位都是1,可以通过位运算&取hash的后几位,即通过位运算实现hash取余,更加高效

1. hashkey和分片数都为uint64,
2. 如分片数为16,减1后为15,二进制为为00000000 00001111
3. 如果hashkey为17,二进制为0000000 00010001
4. hashkey&(shareds-1)=17&(16-1)=1
5. 17%16=1, 即hashkey&(shareds-1)能通过位运算实现取余

3. 数据结构

img

4. 注意点

  1. bigcache处理hash冲突的方式是把map和entries里的值删掉,然后再重新插入。之前的值会被删除

5. 初始化

func newBigCache(ctx context.Context, config Config, clock clock) (*BigCache, error) {
   
    // Shards数需要是2的次幂
    if !isPowerOfTwo(config.Shards) {
   
        return nil, errors.New("Shards number must be power of two")
    }
    if config.MaxEntryByte < 0 {
   
        return nil, errors.New("MaxEntrySize must be >= 0")
    }
    if config.MaxEntriesInWindow < 0 {
   
        return nil, errors.New("MaxEntriesInWindow must be >= 0")
    }
    if config.HardMaxCacheSize < 0 {
   
        return nil, errors.New("HardMaxCacheSize must be >= 0")
    }

    lifeWindowSeconds := uint64(config.LifeWindow.Seconds())
    if config.CleanWindow > 0 && lifeWindowSeconds == 0 {
   
        return nil, errors.New("LifeWindow must be >= 1s when CleanWindow is set")
    }

    if config
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值