前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang源码分析:groupcache(1)

golang源码分析:groupcache(1)

作者头像
golangLeetcode
发布2023-09-06 19:28:24
1510
发布2023-09-06 19:28:24
举报

github.com/golang/groupcache 存储的是kv结构,同是memcache作者出品.在放弃update/delete 的特性后,换来的是:Cluster 的能力,处理热点的能力。

因为groupcache只能get,不能update和delete,也不能设置过期时间,只能通过lru淘汰最近最少访问的数据;有些数据如果长时间不更改,那么可以用groupcache作为缓存;groupcache已经在dl.Google.com、Blogger、Google Code、Google Fiber、Google生产监视系统等项目中投入使用。groupcache既是服务器,也是客户端,当在本地groupcache缓存中没有查找的数据时,通过一致性哈希,查找到该key所对应的peer服务器,在通过http协议,从该peer服务器上获取所需要的数据;还有一点就是当多个客户端同时访问memcache中不存在的键时,会导致多个客户端从mysql获取数据并同时插入memcache中,而在相同情况下,groupcache只会有一个客户端从mysql获取数据,其他客户端阻塞,直到第一个客户端获取到数据之后,再返回给多个客户端。

下面我们用一个例子看下,如何使用它。

代码语言:javascript
复制
package main

import (
  "context"
  "errors"
  "log"
  "net/http"
  "strconv"

  "github.com/golang/groupcache"
)

const (
  // 启动的http端口
  ServicePort = 9000
  // groupcache内部通信端口 同时修改CachePort 和ServicePort 端口,模拟启动运行多个节点
  CachePort = 8000
  // 组名称
  GroupName = "user"
)

// 模拟数据库
var UserDb = map[string]string{
  "1001": "张三",
  "1002": "李四",
  "1003": "王五",
}

// 数据不在缓存中时,加载数据
// 使用单飞,防止缓存惊群效应
func getterFunc(ctx context.Context, key string, dest groupcache.Sink) (err error) {
  log.Println("从数据库获取用户姓名,uid=" + key)

  name, ok := UserDb[key]
  if !ok {
    return errors.New("uid miss")
  }

  dest.SetString(name)
  return nil
}

func startHTTP() {
  group := groupcache.NewGroup(GroupName, 1<<20, groupcache.GetterFunc(getterFunc))
  http.HandleFunc("/getName", func(writer http.ResponseWriter, request *http.Request) {
    // 数据查询
    uid := request.URL.Query().Get("uid")
    log.Println("http uid=" + uid)
    var name []byte
    err := group.Get(context.Background(), uid, groupcache.AllocatingByteSliceSink(&name))
    if err != nil {
      writer.Write([]byte("404"))
      return
    }

    writer.Write([]byte("name=" + string(name)))
  })

  go http.ListenAndServe(":"+strconv.Itoa(ServicePort), nil)
}

func main() {
  startHTTP()

  // 启动groupcache
  localUrl := "http://127.0.0.1:" + strconv.Itoa(CachePort)
  peers := groupcache.NewHTTPPool(localUrl)
  peers.Set("http://127.0.0.1:8000", "http://127.0.0.1:8001")

  http.ListenAndServe(":"+strconv.Itoa(CachePort), peers)
}

测试下

代码语言:javascript
复制
% curl 'http://127.0.0.1:9000/getName?uid=1002'
name=李四%                                                                     
% curl 'http://127.0.0.1:9000/getName?uid=1001'
name=张三%                                                                   
% curl 'http://127.0.0.1:9000/getName?uid=1003'
name=王五%
代码语言:javascript
复制
2023/05/14 16:58:17 http uid=1002
2023/05/14 16:58:17 从数据库获取用户姓名,uid=1002
2023/05/14 16:58:20 http uid=1001
2023/05/14 16:58:23 http uid=1003
2023/05/14 16:58:23 从数据库获取用户姓名,uid=1003

整个流程如下:

1,初始化groupCache,并指定回源函数。

2,注册peer节点

3,启动cache服务供peer查询

查询过程如下:

1,先从本地的lru cache里查询

2,如果本地查不到,到peer的本地缓存查询,peer的选取采用一致性hash算法

3,如果peer中也没有取到结果则回源查询

4,将回源查询的结果存入本地缓存

5,上述查询过程为了防止击穿,采用了singleflight组件。

总的来说,它是为了保证可用性,放弃了一致性,所以不支持主动设置缓存、缓存过期、和缓存内容的修改。

适合不修改的内容的缓存。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-05-20,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com