开始使用

配置

进入项目中的configs目录,打开memcache.toml,我们可以看到:

  1. [Client]
  2. name = "demo"
  3. proto = "tcp"
  4. addr = "127.0.0.1:11211"
  5. active = 50
  6. idle = 10
  7. dialTimeout = "100ms"
  8. readTimeout = "200ms"
  9. writeTimeout = "300ms"
  10. idleTimeout = "80s"

在该配置文件中我们可以配置memcache的连接方式proto、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。

初始化

进入项目的internal/dao目录,打开mc.go,其中:

  1. var cfg struct {
  2. Client *memcache.Config
  3. }
  4. checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc))

使用paladin配置管理工具将上文中的memcache.toml中的配置解析为我们需要使用的配置。

  1. // dao dao.
  2. type dao struct {
  3. mc *memcache.Memcache
  4. mcExpire int32
  5. }

在dao的主结构提中定义了memcache的连接池对象和过期时间。

  1. d = &dao{
  2. // memcache
  3. mc: memcache.New(mc.Demo),
  4. mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second),
  5. }

使用kratos/pkg/cache/memcache包的New方法进行连接池对象的初始化,需要传入上文解析的配置。

Ping

  1. // Ping ping the resource.
  2. func (d *dao) Ping(ctx context.Context) (err error) {
  3. return d.pingMC(ctx)
  4. }
  5. func (d *dao) pingMC(ctx context.Context) (err error) {
  6. if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
  7. log.Error("conn.Set(PING) error(%v)", err)
  8. }
  9. return
  10. }

生成的dao层模板中自带了memcache相关的ping方法,用于为负载均衡服务的健康监测提供依据,详见blademaster

关闭

  1. // Close close the resource.
  2. func (d *Dao) Close() {
  3. d.mc.Close()
  4. }

在关闭dao层时,通过调用memcache连接池对象的Close方法,我们可以关闭该连接池,从而释放相关资源。

常用方法

推荐使用memcache代码生成器帮助我们生成memcache操作的相关代码。

以下我们来逐一解析以下kratos/pkg/cache/memcache包中提供的常用方法。

单个查询

  1. // CacheDemo get data from mc
  2. func (d *Dao) CacheDemo(c context.Context, id int64) (res *Demo, err error) {
  3. key := demoKey(id)
  4. res = &Demo{}
  5. if err = d.mc.Get(c, key).Scan(res); err != nil {
  6. res = nil
  7. if err == memcache.ErrNotFound {
  8. err = nil
  9. }
  10. }
  11. if err != nil {
  12. prom.BusinessErrCount.Incr("mc:CacheDemo")
  13. log.Errorv(c, log.KV("CacheDemo", fmt.Sprintf("%+v", err)), log.KV("key", key))
  14. return
  15. }
  16. return
  17. }

如上为代码生成器生成的进行单个查询的代码,使用到mc.Get(c,key)方法获得返回值,再使用scan方法将memcache的返回值转换为golang中的类型(如string,bool, 结构体等)。

批量查询使用

  1. replies, err := d.mc.GetMulti(c, keys)
  2. for _, key := range replies.Keys() {
  3. v := &Demo{}
  4. err = replies.Scan(key, v)
  5. }

如上为代码生成器生成的进行批量查询的代码片段,这里使用到mc.GetMulti(c,keys)方法获得返回值,与单个查询类似地,我们需要再使用scan方法将memcache的返回值转换为我们定义的结构体。

设置KV

  1. // AddCacheDemo Set data to mc
  2. func (d *Dao) AddCacheDemo(c context.Context, id int64, val *Demo) (err error) {
  3. if val == nil {
  4. return
  5. }
  6. key := demoKey(id)
  7. item := &memcache.Item{Key: key, Object: val, Expiration: d.demoExpire, Flags: memcache.FlagJSON | memcache.FlagGzip}
  8. if err = d.mc.Set(c, item); err != nil {
  9. prom.BusinessErrCount.Incr("mc:AddCacheDemo")
  10. log.Errorv(c, log.KV("AddCacheDemo", fmt.Sprintf("%+v", err)), log.KV("key", key))
  11. return
  12. }
  13. return
  14. }

如上为代码生成器生成的添加结构体进入memcache的代码,这里需要使用到的是mc.Set方法进行设置。 这里使用的item为memcache.Item结构体,包含key, value, 超时时间(秒), Flags。

Flags

上文添加结构体进入memcache中,使用到的flags为:memcache.FlagJSON | memcache.FlagGzip代表着:使用json作为编码方式,gzip作为压缩方式。

Flags的相关常量在kratos/pkg/cache/memcache包中进行定义,包含编码方式如gob, json, protobuf,和压缩方式gzip。

  1. const(
  2. // Flag, 15(encoding) bit+ 17(compress) bit
  3. // FlagRAW default flag.
  4. FlagRAW = uint32(0)
  5. // FlagGOB gob encoding.
  6. FlagGOB = uint32(1) << 0
  7. // FlagJSON json encoding.
  8. FlagJSON = uint32(1) << 1
  9. // FlagProtobuf protobuf
  10. FlagProtobuf = uint32(1) << 2
  11. // FlagGzip gzip compress.
  12. FlagGzip = uint32(1) << 15
  13. )

删除KV

  1. // DelCacheDemo delete data from mc
  2. func (d *Dao) DelCacheDemo(c context.Context, id int64) (err error) {
  3. key := demoKey(id)
  4. if err = d.mc.Delete(c, key); err != nil {
  5. if err == memcache.ErrNotFound {
  6. err = nil
  7. return
  8. }
  9. prom.BusinessErrCount.Incr("mc:DelCacheDemo")
  10. log.Errorv(c, log.KV("DelCacheDemo", fmt.Sprintf("%+v", err)), log.KV("key", key))
  11. return
  12. }
  13. return
  14. }

如上为代码生成器生成的从memcache中删除KV的代码,这里需要使用到的是mc.Delete方法。 和查询时类似地,当memcache中不存在参数中的key时,会返回error为memcache.ErrNotFound。如果不需要处理这种error,可以参考上述代码将返回出去的error置为nil。

扩展阅读

memcache代码生成器
redis模块说明