介绍
如标题所示,DREAMEMO是一个分布式缓存,具有开箱即用,高尺度性,模块化设计功能。引用了groupcache实现,重新结构,特定的模块差异化如下:如下:
主模块将在设计模块中详细介绍。
快速开始
安装
执行以下命令以安装DreameMo:
go get github.com/B1NARY-GR0UP/dreamemo
使用独立模式运行
DreameMo提供了函数dream.StandAlone
使用的默认配置,以帮助用户迅速以独立模式启动。您需要做的就是配置相应数据源的source.Getter
。
package main
import (
"context"
"fmt"
"net/http"
"github.com/B1NARY-GR0UP/dreamemo/common/constant"
"github.com/B1NARY-GR0UP/dreamemo/dream"
"github.com/B1NARY-GR0UP/dreamemo/guidance"
"github.com/B1NARY-GR0UP/dreamemo/source"
log "github.com/B1NARY-GR0UP/inquisitor/core"
"github.com/B1NARY-GR0UP/piano/core"
"github.com/B1NARY-GR0UP/piano/core/bin"
)
var db = map[string]string{
"binary": "dreamemo",
"hello": "world",
"ping": "pong",
}
func getFromDB(_ context.Context, key string) ([]byte, error) {
log.Info("Get from DB")
if v, ok := db[key]; ok {
return []byte(v), nil
}
return nil, fmt.Errorf("key %v is not exist", key)
}
// go run .
// curl localhost:8080/hello?key=ping
func main() {
dream.StandAlone(source.GetterFunc(getFromDB))
p := bin.Default(core.WithHostAddr(":8080"))
p.GET("/hello", func(ctx context.Context, pk *core.PianoKey) {
key := pk.Query("key")
g := guidance.GetGroup(constant.DefaultGroupName)
value, _ := g.Get(ctx, key)
pk.JSON(http.StatusOK, core.M{
key: value.String(),
})
})
p.Play()
}
以map
仿真数据源数据库的形式,并使用PIANO HTTP Framework作为前端服务器,而不是使用其他HTTP框架,例如Hertz,Gin等。检索钥匙的URL。
go run .
curl localhost:8080/hello?key=ping
使用集群模式运行
DreameMo还提供了使用默认配置在群集模式下运行的dream.Cluster
函数。您需要做的就是配置相应的群集节点和数据源的地址。
package main
import (
"context"
"fmt"
"net/http"
"github.com/B1NARY-GR0UP/dreamemo/common/constant"
"github.com/B1NARY-GR0UP/dreamemo/common/util"
"github.com/B1NARY-GR0UP/dreamemo/dream"
"github.com/B1NARY-GR0UP/dreamemo/guidance"
"github.com/B1NARY-GR0UP/dreamemo/source"
log "github.com/B1NARY-GR0UP/inquisitor/core"
"github.com/B1NARY-GR0UP/piano/core"
"github.com/B1NARY-GR0UP/piano/core/bin"
)
var db = map[string]string{
"binary": "dreamemo",
"hello": "world",
"ping": "pong",
}
func getFromDB(_ context.Context, key string) ([]byte, error) {
log.Info("Get from DB")
if v, ok := db[key]; ok {
return []byte(v), nil
}
return nil, fmt.Errorf("key %v is not exist", key)
}
// go run . --addrs=http://localhost:7246,http://localhost:7247,http://localhost:7248 --api
// go run . --addrs=http://localhost:7247,http://localhost:7248,http://localhost:7246
// go run . --addrs=http://localhost:7248,http://localhost:7246,http://localhost:7247
// curl localhost:8080/hello?key=ping
func main() {
addrs, api := util.ParseFlags()
e := dream.Cluster(source.GetterFunc(getFromDB), addrs...)
if api {
go func() {
p := bin.Default(core.WithHostAddr(":8080"))
p.GET("/hello", func(ctx context.Context, pk *core.PianoKey) {
key := pk.Query("key")
g := guidance.GetGroup(constant.DefaultGroupName)
value, _ := g.Get(ctx, key)
pk.JSON(http.StatusOK, core.M{
key: value.String(),
})
})
p.Play()
}()
}
e.Run()
}
再次将数据库数据源模拟为map
,并在localhost:7246
,localhost:7247
和localhost:7248
上配置了三个缓存节点,前端服务器在port 8080
上配置。要检索键的值,请运行以下命令并访问URL:
go run . --addrs=http://localhost:7246,http://localhost:7247,http://localhost:7248 --api
go run . --addrs=http://localhost:7247,http://localhost:7248,http://localhost:7246
go run . --addrs=http://localhost:7248,http://localhost:7246,http://localhost:7247
curl localhost:8080/hello?key=ping
定制组装
dream.StandAlone
和dream.Cluster
功能由DreameMo配置为较早使用,在这里我们将查看一种更自定义的运行汇编的方式。
- 配置引擎
在这里,我们配置了引擎,util.ParseFlags
是提供用于解析标志参数的实用程序方法。我们使用app.WithHostAddr
来配置引擎以聆听和app.WithThrift0
用作thrift作为序列化协议并注册其他节点。
addrs, api := util.ParseFlags()
e := server.NewEngine(app.WithHostAddr(addrs[0]), app.WithThrift0())
e.RegisterInstances(addrs...)
- 配置缓存消除策略
配置LFU
l := lfu.NewLFUCore()
m := memo.NewMemo(l)
- 配置缓存组
我们将CACHE组名称配置为guidance.WithGroupName
,将节俭配置为具有guidance.WithThrift1
的序列化协议,与引擎保持一致,并使用source.Getter
配置数据源
guidance.NewGroup(m, e, guidance.WithGroupName("hello"), guidance.WithThrift1(), guidance.WithGetter(source.GetterFunc(getFromDB)))
完整的代码如下:
package main
import (
"context"
"fmt"
"net/http"
"github.com/B1NARY-GR0UP/dreamemo/app"
"github.com/B1NARY-GR0UP/dreamemo/app/server"
"github.com/B1NARY-GR0UP/dreamemo/common/util"
"github.com/B1NARY-GR0UP/dreamemo/guidance"
"github.com/B1NARY-GR0UP/dreamemo/memo"
"github.com/B1NARY-GR0UP/dreamemo/source"
"github.com/B1NARY-GR0UP/dreamemo/strategy/eliminate/lfu"
log "github.com/B1NARY-GR0UP/inquisitor/core"
"github.com/B1NARY-GR0UP/piano/core"
"github.com/B1NARY-GR0UP/piano/core/bin"
)
var db = map[string]string{
"binary": "dreamemo",
"hello": "world",
"ping": "pong",
}
func getFromDB(_ context.Context, key string) ([]byte, error) {
log.Info("Get from DB")
if v, ok := db[key]; ok {
return []byte(v), nil
}
return nil, fmt.Errorf("key %v is not exist", key)
}
// go run . --addrs=http://localhost:7246,http://localhost:7247,http://localhost:7248 --api
// go run . --addrs=http://localhost:7247,http://localhost:7248,http://localhost:7246
// go run . --addrs=http://localhost:7248,http://localhost:7246,http://localhost:7247
// curl localhost:8080/hello?key=ping
func main() {
addrs, api := util.ParseFlags()
e := server.NewEngine(app.WithHostAddr(addrs[0]), app.WithThrift0())
e.RegisterInstances(addrs...)
l := lfu.NewLFUCore()
m := memo.NewMemo(l)
guidance.NewGroup(m, e, guidance.WithGroupName("hello"), guidance.WithThrift1(), guidance.WithGetter(source.GetterFunc(getFromDB)))
if api {
go func() {
p := bin.Default(core.WithHostAddr(":8080"))
p.GET("/hello", func(ctx context.Context, pk *core.PianoKey) {
key := pk.Query("key")
g := guidance.GetGroup("hello")
value, _ := g.Get(ctx, key)
pk.JSON(http.StatusOK, core.M{
key: value.String(),
})
})
p.Play()
}()
}
e.Run()
}
运行并使用以下命令获取缓存值:
go run . --addrs=http://localhost:7246,http://localhost:7247,http://localhost:7248 --api
go run . --addrs=http://localhost:7247,http://localhost:7248,http://localhost:7246
go run . --addrs=http://localhost:7248,http://localhost:7246,http://localhost:7247
curl localhost:8080/hello?key=ping
设计
消除策略
在缓存策略方面,DreameMo支持LRU和LFU缓存消除算法,用户可以自己选择和组装它们:
- lru
c := lru.NewLRUCore()
- lfu
c := lfu.NewLFUCore()
DreameMo还提供了用于扩展其他消除策略的界面。只需实现界面并将对象传递到memo.NewMemo
如下:
type ICore interface {
Add(Key, Value)
Get(Key) (Value, bool)
Remove(Key)
Clear()
Name() string
}
序列化
dreamemo支持节俭和Protobuf序列化协议。默认值是Protobuf,要使用thrift,您需要在配置引擎和高速缓存组中启用节俭:
e := server.NewEngine(app.WithThrift0()) // engine
guidance.NewGroup(m, e, guidance.WithThrift1()) // group
数据源
DreameMo提供了使用Redis作为数据源的默认配置:
s := redis.NewSource()
DreameMo还提供了一个接口来配置您自己的更多数据源:
type Getter interface {
Get(ctx context.Context, key string) ([]byte, error)
}
一致的哈希
DreameMo,例如GroupCache,使用一致的散布进行分布式节点选择,同时还提供了一个配置更多策略的接口。
全部
DreameMo还很年轻,可以做出许多变化。将来,将提供更多节点选择算法和快速配置工具。
概括
这就是本文的全部。希望这可以帮到你。如果您可以给DREAMEMO成为明星,我会很感激。
如果您有任何疑问,请将其留在评论或问题中。感谢您的阅读。