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的缓存