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集群使用一致性哈希算法,服务的节点收到请求后,发现数据不在本节点,会去对应节点获取数据,然后将数据返回