代码积累 --redisgo

  |   0 评论   |   0 浏览

golang 创建 Redis 连接池和 Redis 基础操作

package redigo

import (
	"encoding/json"
	"errors"
	"fmt"
	log "github.com/alecthomas/log4go"
	"github.com/gomodule/redigo/redis"
	"time"
)

const (
	DEL      = "DEL"
	HGETALL  = "Hgetall"
	ZADD     = "ZADD"
	ZREM     = "ZREM"
	KEYS     = "KEYS"
	ZRANGE   = "ZRANGE"
	SMEMBERS = "smembers"
	HMGET    = "HMGET"
)

// ScriptItem an item contains script and keycount
type ScriptItem struct {
	Script   string //Script a redis script
	KeyCount int    //KeyCount Script key count
}
type RedisConfig struct {
	Host        string
	Password    string
	Db          int
	MaxIdle     int
	MaxActive   int
	IdleTimeout time.Duration
}

//RedisClient interface
type RedisClient struct {
	Pool    *redis.Pool     //redis pool
	scripts []*redis.Script //redis scripts
	Config  *RedisConfig
}


/**
* @desc 创建redis客户端
* @author huangtao
* @date 2020/3/28 下午2:23
*/
func NewRedisClient(config *RedisConfig) (client *RedisClient, err error) {
	pool := &redis.Pool{
		MaxIdle:     config.MaxIdle,
		MaxActive:   config.MaxActive,
		IdleTimeout: config.IdleTimeout,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", config.Host)
			if err != nil {
				return nil, err
			}
			if config.Password != "" {
				if _, err := c.Do("AUTH", config.Password); err != nil {
					_ = c.Close()
					return nil, err
				}
			}
			if config.Db != 0 {
				if _, err := c.Do("SELECT", config.Db); err != nil {
					_ = c.Close()
					return nil, err
				}
			}
			redis.DialReadTimeout(time.Second * 10)
			redis.DialWriteTimeout(time.Second * 10)
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}

	client = &RedisClient{
		Pool:   pool,
		Config: config,
	}
	return
}

// Load load srcipt
func (c *RedisClient) Load(script ...ScriptItem) error {
	conn := c.Pool.Get()
	if err := conn.Err(); err != nil {
		return err
	}
	defer conn.Close()
	l := len(script)
	if l == 0 { //meanless when param script is nil
		return errors.New("args nil")
	}
	s := make([]*redis.Script, 0, l)

	for _, v := range script {
		_, err := conn.Do("SCRIPT", "LOAD", v.Script)
		if err != nil {
			return fmt.Errorf("%s, err:%s", v.Script, err.Error())
		}

		i := redis.NewScript(v.KeyCount, v.Script)
		if i == nil {
			panic(fmt.Sprintf("script illegal, %s, %d", v.Script, v.KeyCount))
		}
		s = append(s, i)
	}
	c.scripts = s
	return nil
}

// Script returns a srcipt
func (c *RedisClient) Script(index int) *redis.Script {
	if index < len(c.scripts) && index >= 0 {
		return c.scripts[index]
	}
	return nil
}

func (rc RedisClient) Ping() error {
	conn := rc.Pool.Get()
	defer conn.Close()

	_, err := conn.Do("PING")
	return err
}

func (rc RedisClient) Get(key string) ([]byte, error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	reply, err := redis.Bytes(conn.Do("GET", key))

	if err != nil {
		return nil, err
	}
	return reply, nil
}

func (rc RedisClient) Del(key string) error {
	conn := rc.Pool.Get()
	defer conn.Close()

	_, err := redis.Bool(conn.Do(DEL, key))

	if err != nil {
		return err
	}
	return nil
}

func (rc RedisClient) Set(key string, data interface{}, time int64) error {
	conn := rc.Pool.Get()
	defer conn.Close()

	value, err := json.Marshal(data)
	if err != nil {
		return err
	}

	_, err = conn.Do("SET", key, value)
	if err != nil {
		return err
	}
	_, err = conn.Do("EXPIRE", key, time)
	if err != nil {
		return err
	}
	return nil
}

func (rc RedisClient) Exists(key string) bool {

	conn := rc.Pool.Get()
	defer conn.Close()

	exists, err := redis.Bool(conn.Do("EXISTS", key))
	if err != nil {
		return false
	}
	return exists
}

func (rc RedisClient) TTL(key string) (int64, error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	exists, err := redis.Int64(conn.Do("TTL", key))
	if err != nil {
		return exists, err
	}
	return exists, nil
}

func (rc RedisClient) HSet(key string, field string, data interface{}) error {
	conn := rc.Pool.Get()
	defer conn.Close()

	_, err := conn.Do("HSET", key, field, data)
	if err != nil {
		return err
	}
	return nil
}

func (rc RedisClient) HExists(key string, field string) bool {
	conn := rc.Pool.Get()
	defer conn.Close()

	exists, err := redis.Bool(conn.Do("HEXISTS", key, field))
	if err != nil {
		log.Warnf("[gredis] HExists key: %s, field: %s, error: %v", key, field, err)
		return false
	}
	return exists
}

// 删除
func (rc RedisClient) HDel(key string, filed string) error {
	conn := rc.Pool.Get()
	defer conn.Close()

	if rc.HExists(key, filed) == false {
		return nil
	}
	_, err := conn.Do("HDEL", key, filed)

	if err != nil {
		return err
	}
	return nil
}

func (rc RedisClient) HGet(key string, field string) ([]byte, error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	if rc.HExists(key, field) == false {
		return nil, nil
	}

	value, err := redis.Bytes(conn.Do("HGET", key, field))
	if err != nil {
		log.Warnf("[gredis] Hget key: %s, field: %s, error: %v", key, field, err)
		return nil, err
	}
	return value, nil
}

// HMGET 批量获取Hash中的Key O(n)
func (rc RedisClient) HMGET(key string, fields []interface{}) ([][]byte, error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	var regs = []interface{}{key}
	regs = append(regs, fields...)
	value, err := redis.ByteSlices(conn.Do("HMGET", regs...))
	return value, err
}

func (rc RedisClient) HGetall(key string) (values map[string]string, err error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	log.Debugf("in key: %s", key)

	v, err := redis.Values(conn.Do("HGetall", key))
	if err != nil {
		log.Warnf("[gredis] HGEALL key: %s, error: %v", key, err)
		return nil, err
	}

	data := map[string]string{}
	for i := 0; i < len(v); i += 2 {
		key := fmt.Sprintf("%s", v[i])
		value := fmt.Sprintf("%s", v[i+1])
		data[key] = value
	}

	log.Debugf("out key:%s out data: %v", key, data)
	return data, nil
}

func (rc RedisClient) Keys(key string) (keys []string, err error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	keys, err = redis.Strings(conn.Do("keys", key))
	return
}

// ZrangeByScore 获取score在某某区间内的所有成员
func (rc RedisClient) ZrangeByScore(key string, start string, end string) (members []string, err error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	members, err = redis.Strings(conn.Do(ZRANGE, key, start, end))
	return
}

func (rc RedisClient) ZrangeByScoreWithScores(key string, start string, end string) (members []string, err error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	members, err = redis.Strings(conn.Do(ZRANGE, key, start, end, "WITHSCORES"))
	return
}

func (rc RedisClient) Zremrangebyscore(key string, start string, end string) (counts int, err error) {
	conn := rc.Pool.Get()
	defer conn.Close()

	counts, err = redis.Int(conn.Do("ZREMRANGEBYSCORE", key, start, end))
	return
}

// Zrevrange 取前几位
func (rc RedisClient) Zrevrange(key string, start string, end string) ([]string, error) {
	conn := rc.Pool.Get()
	defer conn.Close()
	strings, e := redis.Strings(conn.Do("ZREVRANGE", key, start, end))
	return strings, e
}

// Set 获取所有
func (rc RedisClient) Smembers(key string) ([]string, error) {
	conn := rc.Pool.Get()
	defer conn.Close()
	strings, e := redis.Strings(conn.Do(SMEMBERS, key))
	return strings, e
}


标题:代码积累 --redisgo
作者:疲惫的怪神明