| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- package redis
- import (
- "fmt"
- "git.shuncheng.lu/bigthing/gocommon/pkg/conf"
- "git.shuncheng.lu/bigthing/gocommon/pkg/internal/util"
- "git.shuncheng.lu/bigthing/gocommon/pkg/logger"
- "git.shuncheng.lu/bigthing/gocommon/pkg/net/qconf"
- "github.com/garyburd/redigo/redis"
- )
- var (
- redisInstance *ConnPool
- )
- // ConnPool is for Cache fd
- type ConnPool struct {
- prefix string
- redisPool *redis.Pool
- }
- //获取实例
- func Instance() *ConnPool {
- return redisInstance
- }
- // 将Pool暴露出去,记住需要defer close!
- func InstancePool() *redis.Pool {
- return redisInstance.redisPool
- }
- func PrefixKey(key string) string {
- return fmt.Sprintf("%s%s", redisInstance.prefix, key)
- }
- func CheckIsNilErr(err error) bool { // 检测是不是nil的问题,true是nil-err
- return err == redis.ErrNil
- }
- func CheckIsNotNilErr(err error) bool { // 检测是不是nil的问题,true不是nil-err
- return err != redis.ErrNil
- }
- func getConfig(section, key string, defaultVal ...string) string {
- return conf.GetString(section, key, defaultVal...)
- }
- //初始化redis pool
- func Init() error {
- config, err := getRedisConfig("redis", conf.SetAndAssertNil)
- if err != nil {
- return err
- }
- util.Debugf("Redis load config success, config=%+v", config)
- redisConfig := getRedisConfigFromMap(config)
- // 如果不是直接连接&&env不是debug则qconf获取
- if (!util.String2Bool(config["is_direct"])) && conf.GetEnv() != conf.EnvDebug {
- realHost, err := qconf.GetHost(redisConfig.Host, qconf.GetQconfIdc())
- if err != nil {
- return err
- }
- redisConfig.Host = realHost
- }
- pool, err := newRedisPool(redisConfig)
- if err != nil {
- return err
- }
- redisInstance = &ConnPool{redisPool: pool, prefix: config["cache_prefix"]}
- return nil
- }
- // Close pool
- func (p *ConnPool) Close() error {
- err := p.redisPool.Close()
- return err
- }
- // Do commands
- func (p *ConnPool) Do(command string, args ...interface{}) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do(command, args...)
- }
- // SetString for string
- func (p *ConnPool) SetString(key string, value interface{}) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("SET", key, value)
- }
- // SetString for string ttl,ttl 单位s
- func (p *ConnPool) SetExString(key string, value interface{}, ttl uint64) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("SET", key, value, "EX", ttl)
- }
- // GetString for string, 如果key不存在会抛出异常: redigo: nil returned
- func (p *ConnPool) GetString(key string) (string, error) {
- // get one connection from pool
- conn := p.redisPool.Get()
- // put connection to pool
- defer conn.Close()
- return redis.String(conn.Do("GET", key))
- }
- // GetBytes for bytes
- func (p *ConnPool) GetBytes(key string) ([]byte, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Bytes(conn.Do("GET", key)) // if nil return errnil
- }
- // GetInt for int
- func (p *ConnPool) GetInt(key string) (int, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int(conn.Do("GET", key))
- }
- //Incr
- func (p *ConnPool) Incr(key string) (int, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int(conn.Do("INCR", key))
- }
- //Decr
- func (p *ConnPool) Decr(key string) (int, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int(conn.Do("DECR", key))
- }
- // GetInt64 for int64
- func (p *ConnPool) GetInt64(key string) (int64, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int64(conn.Do("GET", key))
- }
- // DelKey for key
- func (p *ConnPool) DelKey(key string) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("DEL", key)
- }
- // ExpireKey for key
- func (p *ConnPool) ExpireKey(key string, seconds int64) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("EXPIRE", key, seconds)
- }
- // Keys for key
- func (p *ConnPool) Keys(pattern string) ([]string, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Strings(conn.Do("KEYS", pattern))
- }
- // KeysByteSlices for key
- func (p *ConnPool) KeysByteSlices(pattern string) ([][]byte, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.ByteSlices(conn.Do("KEYS", pattern))
- }
- // SetHashMap for hash map
- func (p *ConnPool) SetHashMap(key string, fieldValue map[string]interface{}) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("HMSET", redis.Args{}.Add(key).AddFlat(fieldValue)...)
- }
- // GetHashMapString for hash map
- func (p *ConnPool) GetHashMapString(key string) (map[string]string, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.StringMap(conn.Do("HGETALL", key))
- }
- // HGet
- func (p *ConnPool) HGet(key, field string) (string, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.String(conn.Do("HGET", key, field))
- }
- // HSet
- func (p *ConnPool) HSet(key, field, val string) (int, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int(conn.Do("HSET", key, field, val))
- }
- // GetHashMapInt for hash map
- func (p *ConnPool) GetHashMapInt(key string) (map[string]int, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.IntMap(conn.Do("HGETALL", key))
- }
- // GetHashMapInt64 for hash map
- func (p *ConnPool) GetHashMapInt64(key string) (map[string]int64, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Int64Map(conn.Do("HGETALL", key))
- }
- // LPUSH
- func (p *ConnPool) LPUSH(key string, fieldValue []interface{}) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return conn.Do("LPUSH", redis.Args{}.Add(key).AddFlat(fieldValue)...)
- }
- // LPOP
- func (p *ConnPool) LPOP(key string) (interface{}, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.String(conn.Do("LPOP", key))
- }
- // BLPOP
- func (p *ConnPool) BLPOP(key string, timeout int) ([]string, error) {
- conn := p.redisPool.Get()
- defer conn.Close()
- return redis.Strings(conn.Do("BLPOP", key, timeout))
- }
- /*
- Distributed mutual exclusion lock(Redis分布式排斥锁)
- */
- //===========start===========
- func (p *ConnPool) LockAcquire(name string, value string, expiry int) bool {
- conn := p.redisPool.Get()
- defer conn.Close()
- reply, err := redis.String(conn.Do("SET", name, value, "NX", "PX", expiry))
- logger.Infof("Redis LockAcquire name:%s,value:%s,reply:%s", name, value, reply)
- return err == nil && reply == "OK"
- }
- var lockDeleteScript = redis.NewScript(1, `
- if redis.call("GET", KEYS[1]) == ARGV[1] then
- return redis.call("DEL", KEYS[1])
- else
- return 0
- end
- `)
- func (p *ConnPool) LockRelease(name string, value string) bool {
- conn := p.redisPool.Get()
- defer conn.Close()
- status, err := lockDeleteScript.Do(conn, name, value)
- return err == nil && status != 0
- }
- var lockTouchScript = redis.NewScript(1, `
- if redis.call("GET", KEYS[1]) == ARGV[1] then
- return redis.call("SET", KEYS[1], ARGV[1], "XX", "PX", ARGV[2])
- else
- return "ERR"
- end
- `)
- func (p *ConnPool) LockTouch(name string, value string, expiry int) bool {
- conn := p.redisPool.Get()
- defer conn.Close()
- status, err := redis.String(lockTouchScript.Do(conn, name, value, expiry))
- return err == nil && status != "ERR"
- }
- //===========end===========
|