赞
踩
码字不易,转载请附原链,搬砖繁忙回复不及时见谅,技术交流请加QQ群:909211071
完整最新源码:https://github.com/why444216978/gin-api/blob/master/libraries/redis/redis.go
安装redigo扩展
go get -v github.com/gomodule/redigo/redis
- package redis
-
- import (
- "context"
- "fmt"
- "github.com/opentracing/opentracing-go"
- "strconv"
- "strings"
- "time"
- "why/config"
- "why/log"
- "why/util"
-
- "github.com/gomodule/redigo/redis"
- )
-
- type RedisDB struct {
- pool *redis.Pool
- Config *Config
- }
-
- var obj map[string]*RedisDB
-
- func Conn(conn string) (db *RedisDB, err error) {
- if len(obj) == 0 {
- obj = make(map[string]*RedisDB)
- }
- if obj[conn] != nil {
- db = obj[conn]
- return
- }
-
- fileCfg := config.GetConfigEntrance("redis", conn)
-
- portCfg, err := strconv.Atoi(fileCfg["port"]);
- dbCfg, err := strconv.Atoi(fileCfg["db"]);
- maxActiveCfg, err := strconv.Atoi(fileCfg["max_active"]);
- maxIdleCfg, err := strconv.Atoi(fileCfg["max_idle"]);
- logCfg, err := strconv.ParseBool(fileCfg["is_log"])
- util.Must(err)
-
- cfg := &Config{
- Host: fileCfg["host"],
- Port: portCfg,
- Password: fileCfg["auth"],
- DB: dbCfg,
- MaxActive: maxActiveCfg,
- MaxIdle: maxIdleCfg,
- IsLog: logCfg,
- }
-
- db = new(RedisDB)
- db.Config = cfg
- db.pool = &redis.Pool{
- Dial: func() (redis.Conn, error) {
- return redis.Dial(
- "tcp",
- fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
- redis.DialPassword(cfg.Password),
- redis.DialDatabase(cfg.DB),
- redis.DialConnectTimeout(time.Second*2),
- redis.DialReadTimeout(time.Second*2),
- redis.DialWriteTimeout(time.Second*2),
- )
- },
- TestOnBorrow: func(c redis.Conn, t time.Time) error {
- _, err := c.Do("PING")
- return err
- },
- MaxIdle: cfg.MaxIdle, // 最大的空闲连接数,表示即使没有redis连接时依然可以保持N个空闲的连接,而不被清除,随时处于待命状态
- MaxActive: cfg.MaxActive, // 最大的激活连接数,表示同时最多有N个连接 ,为0事表示没有限制
- IdleTimeout: time.Second, //最大的空闲连接等待时间,超过此时间后,空闲连接将被关闭
- Wait: true, // 当链接数达到最大后是否阻塞,如果不的话,达到最大后返回错误
- }
-
- if _, err = db.Do(context.TODO(), "PING"); err != nil {
- fmt.Println(err)
- err = errorsWrap(err, "ping error")
- return
- }
- obj[conn] = db
-
- return
- }
-
- func errorsWrap(err error, msg string) error {
- return fmt.Errorf("%s: %w", msg, err)
- }
-
- // ConnPool 返回 redis.Pool.
- // 除非必要一般不建议用这个函数, 用本库封装好的函数操作数据库.
- func (db *RedisDB) ConnPool() *redis.Pool {
- return db.pool
- }
-
- // Close 释放连接资源.
- func (db *RedisDB) Close() error {
- if db.pool != nil {
- return db.pool.Close()
- }
- return nil
- }
-
- // Do 执行 redis 命令
- // NOTE 除非有必要(比如在一个函数内部需要执行多次 redis 操作), 否则请用该函数执行所有的操作, 这样能有效避免忘记释放资源.
- func (db *RedisDB) Do(ctx context.Context, commandName string, args ...interface{}) (reply interface{}, err error) {
- var (
- conn = db.pool.Get()
- parent = opentracing.SpanFromContext(ctx)
- span opentracing.Span
- startAt = time.Now()
- endAt time.Time
- logFormat = log.LogHeaderFromContext(ctx)
- argsStr []string
- )
- defer conn.Close()
-
- reply, err = conn.Do(commandName, args...)
-
- if db.Config.IsLog == false {
- return;
- }
-
- if logFormat == nil {
- logFormat = log.NewLog()
- }
-
- for _, arg := range args {
- argsStr = append(argsStr, fmt.Sprint(arg))
- }
-
- lastModule := logFormat.Module
- defer func() {logFormat.Module = lastModule}()
- defer func() {
- endAt = time.Now()
- logFormat.StartTime = startAt
- logFormat.EndTime = endAt
- latencyTime := logFormat.EndTime.Sub(logFormat.StartTime).Microseconds()// 执行时间
- logFormat.LatencyTime = latencyTime
-
- logFormat.Module = "databus/redis"
- if endAt.Sub(startAt) > db.Config.ExecTimeout.Duration {
- log.Warnf(logFormat, "redis do:[%s], used: %d milliseconds",
- fmt.Sprint(commandName, " ", strings.Join(argsStr, " ")),
- endAt.Sub(startAt).Milliseconds())
- }
-
- if err != nil {
- log.Errorf(logFormat, "redis do:[%s], error: %s",
- fmt.Sprint(commandName, " ", strings.Join(argsStr, " ")),
- err)
- }
- }()
-
- if parent == nil {
- span = opentracing.StartSpan("redisDo")
- } else {
- span = opentracing.StartSpan("redisDo", opentracing.ChildOf(parent.Context()))
- }
- defer span.Finish()
-
- span.SetTag("db.type", "redis")
- span.SetTag("db.statement", fmt.Sprint(commandName, " ", strings.Join(argsStr, " ")))
- span.SetTag("error", err != nil)
- return
- }
-
-

使用:
- package services
-
- import (
- "context"
- "strconv"
- "why/util"
-
- redigo "github.com/gomodule/redigo/redis"
- )
-
- const (
- location_detail = "location::id_detail:"
- location_name = "location::id_name:"
- )
-
- func GetLocationDetail(ctx context.Context, id int) string {
- db := Conn("location")
- data, err := redigo.String( db.Do(ctx, "GET", location_name + strconv.Itoa(id)) )
- util.Must(err)
- return data
- }
-
- func BatchLocationDetail(ctx context.Context, ids []int) []string {
- db := Conn("location")
-
- var args []interface{}
- for _,v := range ids {
- args = append(args, location_detail + strconv.Itoa(v))
- }
-
- data, err := redigo.Strings(db.Do(ctx,"MGET", args...))
- util.Must(err)
-
- return data
- }

config参考:https://blog.csdn.net/why444216978/article/details/103978355
util参考:https://blog.csdn.net/why444216978/article/details/103992579
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。