用redigo自己实现一个redis连接池

目前主要的两个go语言的redis库主要是redigo和radix。最近想用go实现一个redis的连接池,看了一下网上的demo,基本都是直接套用的redigo的方法。实现很简单,如下:

func newPool(server, password string) *redis.Pool {
    return &redis.Pool{
        MaxIdle: 3,
        IdleTimeout: 240 * time.Second,
        Dial: func () (redis.Conn, error) {
            c, err := redis.Dial("tcp", server)
            if err != nil {
                return nil, err
            }
            if _, err := c.Do("AUTH", password); err != nil {
                c.Close()
                return nil, err
            }
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            return err
        },
    }
}
var (
    pool *redis.Pool
    redisServer = flag.String("redisServer", ":6379", "")
    redisPassword = flag.String("redisPassword", "", "")
)
 
func main() {
    flag.Parse()
    pool = newPool(*redisServer, *redisPassword)
}

这是从网上copy过来的连接池实现,很简单,直接使用redis.Pool,设置各项参数即可正常运作。

 

接下里这个demo是我个人实现的,可能没redis.Pool配置那么全面,简单实现了下连接池的各项功能。

library包如下:

package library

import (
        "errors"

        "github.com/garyburd/redigo/redis"
)

const (
        DEFAULT_MAX_ACTIVE = 20
        DEFAULT_MAX_IDLE   = 10
)

//go redis 结构
type Godis struct {
        Server  string
        Options map[string]string
}

type RedisPool struct {
        max_active int
        max_idle   int

        current_idle int
        //关于pool究竟用何种类型来存储 一开始使用的map,但是脱离了池的概念更像一个单例  后来使用slice,但是无法标记当前连接的状态,是否被占用
        Pool chan redis.Conn
}

//redis连接
func (config Godis) connect() (redis.Conn, error) {
        //      var option_auth redis.DialOption
        //      if auth, ok := config["auth"]; ok {
        //              if auth != "" {
        //                      option_auth = redis.DialPassword(auth)
        //              }
        //      }
        //      option_connecttime := redis.DialConnectTimeout(time.Microsecond * 3000)

        conn, err := redis.Dial("tcp", config.Server)

        if err != nil {
                return nil, err
        }
        if auth, ok := config.Options["auth"]; ok {
                if auth != "" {
                        if _, err := conn.Do("AUTH", auth); err != nil {
                                conn.Close()
                                return nil, err
                        }
                }
        }

        return conn, nil
}

//初始化pool的各项参数
func (p *RedisPool) InitPool(active_num int, idle_num int) {
        if active_num <= 0 {
                active_num = DEFAULT_MAX_ACTIVE
        }
        if idle_num > active_num {
                idle_num = active_num / 2
        }

        p.max_active = active_num
        p.max_idle = idle_num
        p.current_idle = 0
        //设置跟池子一样大的缓冲 如果没有缓冲就只是单例的连接了
        p.Pool = make(chan redis.Conn, active_num)
}

//获取池子中的连接
func (p *RedisPool) Get() (redis.Conn, error) {
        if p.current_idle == 0 {
                err := errors.New("has no available resource!!")
                return nil, err
        }

        p.current_idle--
        return <-p.Pool, nil
}

//添加连接
func (p *RedisPool) PutPool(config Godis) error {
        //pool已经满了
        if len(p.Pool) >= p.max_active {
                err := errors.New("pool is full")
                return err
        }

        if p.current_idle >= p.max_idle {
                err := errors.New("idle resource is too much!!")
                return err
        }

        conn, err := config.connect()
        if err != nil {
                return err
        }

        p.current_idle++
        p.Pool <- conn
        return nil

}

func (p *RedisPool) PutConn(conn redis.Conn) error {
        //pool已经满了
        if len(p.Pool) >= p.max_active {
                err := errors.New("pool is full")
                return err
        }

        if p.current_idle >= p.max_idle {
                err := errors.New("idle resource is too much!!")
                return err
        }

        p.current_idle++
        p.Pool <- conn
        return nil

}

//删除连接
func (p *RedisPool) RemovePool() error {
        if p.current_idle > 0 {
                conn := <-p.Pool
                p.current_idle--
                return conn.Close()
        }

        return nil
} 

main包:

package main

import (
        "fmt"
        "library"
        "time"
)

func main() {
        redisConfig := library.Godis{Server: "101.138.97.217:1578", Options: make(map[string]string)}
        redisConfig.Options["auth"] = "xxxxxxxxxxx"

        //初始化连接池
        pool := new(library.RedisPool)
        pool.InitPool(10, 5)

        go func() {
                for i := 0; i < 5; i++ {
                        err := pool.PutPool(redisConfig)
                        if err != nil {
                                fmt.Println(err)
                        }   
                }   
        }() 
        //主协程等待20毫秒再进行
        time.Sleep(time.Millisecond * 20) 
        //从池子中取出连接来操作redis
        conn, err := pool.Get()
        if err != nil {
                fmt.Println(err)
                return
        }

        dbsize, err := conn.Do("dbsize")
        fmt.Println(dbsize)
        pool.PutConn(conn) //用完之后放回到池子中
        fmt.Println(len(pool.Pool))

}        

 

转载于:https://my.oschina.net/u/3470972/blog/1528355

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值