groupcache是类似于memcache的分布式储存库,在使用时它既是客户端又是服务端
- package main
-
- import (
- "context"
- "errors"
- "github.com/golang/groupcache"
- "log"
- "net/http"
- "strconv"
- )
-
- 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)
- }
集群中所有节点通过http通讯,存储所有节点
负责数据的处理
数据不存在时,加载数据
groupcache集群使用一致性哈希算法,服务的节点收到请求后,发现数据不在本节点,会去对应节点获取数据,然后将数据返回