最近无业游民就像看看现在招聘Go的需求看到有些公司有对 groupcache 要求,于是兴趣来就看啦下

当前项目 Star 7w+



groupcache is a caching and cache-filling library, intended as a replacement for memcached in many cases.






package consistenthash


type Hash func(data []byte) uint32

type Map struct {
	hash     Hash
	replicas int
	keys     []int // Sorted
	hashMap  map[int]string

// 使用案例
// Override the hash function to return easier to reason about values. Assumes
// the keys can be converted to an integer.
hash := New(3, func(key []byte) uint32 {
	i, err := strconv.Atoi(string(key))
	if err != nil {
	return uint32(i)
// 具体库调用位置 http.go 109 和 121
p.peers = consistenthash.New(p.opts.Replicas, p.opts.HashFn)

Add 向哈希添加一些键。

// Adds some keys to the hash.
// 向哈希添加一些键。
func (m *Map) Add(keys ...string) {
	for _, key := range keys {
		for i := 0; i < m.replicas; i++ {
			hash := int(m.hash([]byte(strconv.Itoa(i) + key)))
			m.keys = append(m.keys, hash)
			m.hashMap[hash] = key
    // 重新排序

Get 获取散列中与提供的键最接近的项。

// Gets the closest item in the hash to the provided key.
// 获取散列中与提供的键最接近的项。
func (m *Map) Get(key string) string {
	if m.IsEmpty() {
		return ""
	hash := int(m.hash([]byte(key)))
	// Binary search for appropriate replica.
	idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash })
	// Means we have cycled back to the first replica.
	if idx == len(m.keys) {
		idx = 0
	return m.hashMap[m.keys[idx]]

package lru

LRU 算法实现,基于 container/list


// Cache is an LRU cache. It is not safe for concurrent access.
type Cache struct {
	// MaxEntries is the maximum number of cache entries before
	// an item is evicted. Zero means no limit.
	MaxEntries int

	// OnEvicted optionally specifies a callback function to be
	// executed when an entry is purged from the cache.
	OnEvicted func(key Key, value interface{})

	ll    *list.List
	cache map[interface{}]*list.Element

// A Key may be any value that is comparable.
type Key interface{}
  • Add 添加缓存,如果存在更换位置
  • Get 获取一个缓存,并且,并且更新位置
  • Remove 移出制定缓存
  • RemoveOldest 删除最旧的缓存
  • Clear 清空缓存
  • Len 获取长度

package singleflight



// call is an in-flight or completed Do call
type call struct {
    wg  sync.WaitGroup
    val interface{}
    err error
// 控制单位结构
// Group represents a class of work and forms a namespace in which
// units of work can be executed with duplicate suppression.
type Group struct {
    mu sync.Mutex       // protects m
    m  map[string]*call // lazily initialized


// 执行当前Group的单元控制
// Do executes and returns the results of the given function, making
// sure that only one execution is in-flight for a given key at a
// time. If a duplicate comes in, the duplicate caller waits for the
// original to complete and receives the same results.
func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error)


// 只有这一个地方调用
// load loads key either by invoking the getter locally or by sending it to another machine.
func (g *Group) load(ctx Context, key string, dest Sink) (value ByteView, destPopulated bool, err error) {
    viewi, err := g.loadGroup.Do(key, func() (interface{}, error)

// 上层调用方法为
func (g *Group) Get(ctx Context, key string, dest Sink) error 

package groupcachepb

grpc 接口声明

核心 groupcache.go



func NewGroup(name string, cacheBytes int64, getter Getter) *Group {
	return newGroup(name, cacheBytes, getter, nil)


var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc(
    func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
        result := client.Get(key) // 客户端调用,参考下面案例链接地址
        fmt.Printf("asking for %s from dbserver\n", key)
        return nil
// 获取缓存方法
func (g *Group) Get(ctx Context, key string, dest Sink) error


Playing with groupcache

grpc 接口调用