Bootstrap

go-kratos 学习笔记(8) redis的使用

redis的在项目中的使用是很常见的,前面有了mysql的使用redis的也差不多;也是属于在data层的操作,所以需要新建一个 NewRedisCmd方法

在internal/data/data.go中新增NewRedisCmd 方法,注入到ProviderSet

package data

import (
	"context"
	"github.com/go-kratos/kratos/contrib/registry/nacos/v2"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/registry"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/google/wire"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
	"github.com/redis/go-redis/v9"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"time"
	"xgs_kratos/gen/config/users"
	"xgs_kratos/gen/orders"
)

// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewDiscovery, CreateRegister, NewOrderServiceClient, NewUserRepo, NewRedisCmd)

// Data .
type Data struct {
	// TODO wrapped database client
	db          *gorm.DB
	log         *log.Helper
	orderClient orders.OrderClient
	redisCli    redis.Cmdable
}

// NewData .
func NewData(c *conf.Data, logger log.Logger, client orders.OrderClient, redisCli redis.Cmdable) (*Data, func(), error) {

	db, err := gorm.Open(mysql.Open(c.Database.Source), &gorm.Config{})
	if err != nil {
		log.Fatalf("failed to connect database: %v", err)
		panic(err)
	}
	d := &Data{
		db:          db,
		log:         log.NewHelper(logger),
		orderClient: client,
		redisCli:    redisCli,
	}
	cleanup := func() {
		log.NewHelper(logger).Info("closing the data resources")
	}
	return d, cleanup, nil
}

// NewDiscovery 服务发现
func NewDiscovery(conf *conf.Data) registry.Discovery {
	sc := []constant.ServerConfig{
		{
			IpAddr: conf.Nacos.Addr,
			Port:   conf.Nacos.Port,
		},
	}
	cc := constant.ClientConfig{
		NamespaceId: conf.Nacos.NamespaceId,
		TimeoutMs:   5000,
	}

	client, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &cc,
			ServerConfigs: sc,
		},
	)

	if err != nil {
		panic(err)
	}

	r := nacos.New(client)
	return r
}

// NewOrderServiceClient orders 服务客户端
func NewOrderServiceClient(r registry.Discovery) orders.OrderClient {
	conn, err := grpc.DialInsecure(
		context.Background(),
		grpc.WithEndpoint("discovery:///orders-xgs.grpc"),
		grpc.WithDiscovery(r),
		grpc.WithTimeout(time.Second*2),
		grpc.WithMiddleware(
			recovery.Recovery(),
		),
	)
	if err != nil {
		panic(err)
	}
	c := orders.NewOrderClient(conn)
	return c
}

// NewRedisCmd redis的链接
func NewRedisCmd(conf *conf.Data) redis.Cmdable {
	client := redis.NewClient(&redis.Options{
		Addr:         conf.Redis.Addr,
		ReadTimeout:  conf.Redis.ReadTimeout.AsDuration(),
		WriteTimeout: conf.Redis.WriteTimeout.AsDuration(),
		DialTimeout:  time.Second * 2,
		PoolSize:     10,
	})
	timeout, cancelFunc := context.WithTimeout(context.Background(), time.Second*2)
	defer cancelFunc()
	err := client.Ping(timeout).Err()
	if err != nil {
		log.Fatalf("redis connect error: %v", err)
	}
	return client
}

执行 wire 生成依赖

在业务层使用 data/user.go 中的ListUser 方法做个缓存

package data

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/redis/go-redis/v9"
	"time"
	"xgs_kratos/app/users/internal/biz"
	"xgs_kratos/app/users/internal/data/dal"
	"xgs_kratos/gen/orders"
	"xgs_kratos/gen/users"
)

//data 层处理数据的存储和读取

type userRepo struct {
	data *Data
	log  *log.Helper
}

// NewUserRepo . r registry.Discovery,
func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
	return &userRepo{
		data: data,
		log:  log.NewHelper(logger),
	}
}

// CreateUser 创建用户
func (r *userRepo) CreateUser(ctx context.Context, req *users.CreateUserRequest) (*users.CreateUserReply, error) {
	user := dal.UserMo{
		Age:   req.Age,
		Name:  req.Name,
		Email: req.Email,
	}
	result := r.data.db.Create(&user)
	if result.Error != nil {
		return nil, result.Error
	}
	return &users.CreateUserReply{
		Id: user.Id,
	}, nil
}

func (r *userRepo) ListUser(ctx context.Context, req *users.ListUserRequest) ([]*users.UserData, error) {
	//获取order服务的client
	client := r.data.orderClient
	order, err := client.CreateOrder(ctx, &orders.CreateOrderRequest{
		OrderNo: 1,
	})
	if err != nil {
		return nil, err
	}
	fmt.Println(order)
	var redisKey = "user_list"
	//获取redis的数据
	redisData, err := r.data.redisCli.Get(ctx, redisKey).Result()
	if err == redis.Nil {
		redisData = ""
	} else if err != nil {
		return nil, err
	}

	var results []dal.UserMo
	//缓存没有查询到查询数据库
	if redisData == "" {
		fmt.Println("查询了数据库。。。。。。")
		res := r.data.db.Find(&results)
		if res.Error != nil {
			return nil, res.Error
		}
		//把数据转换成json
		resByte, err := json.Marshal(results)
		if err != nil {
			return nil, err
		}
		//设置redis数据
		err = r.data.redisCli.Set(ctx, redisKey, string(resByte), 30*time.Second).Err()
		if err != nil {
			return nil, err
		}
	} else {
		fmt.Println("查询的缓存。。。。。。")
		//查到之后 把数据转换回去
		err = json.Unmarshal([]byte(redisData), &results)
		if err != nil {
			return nil, err
		}
	}
	var userDatas []*users.UserData
	for _, result := range results {
		userDatas = append(userDatas, &users.UserData{
			Id:    result.Id,
			Name:  result.Name,
			Age:   result.Age,
			Email: result.Email,
		})
	}

	return userDatas, nil
}

 然后启动项目 kratos run 看redis的缓存

项目的代码  码云 https://gitee.com/gebilaoxie/xgs_kratos.git

;