redigoのredis.Pool構成パラメータのチューニング

9116 ワード

reids.Pool構造の紹介
// github.com/garyburd/redigo/redis/pool.go
type Pool struct {

    // Dial()        ,              
    Dial func() (Conn, error)

    // TestOnBorrow()        ,                
    TestOnBorrow func(c Conn, t time.Time) error

    //        
    MaxIdle int

    //   pool            
    //     0   , pool       
    MaxActive int

    //         ,               。
    //      0,          
    //        redis            
    IdleTimeout time.Duration

    //   Wait    true, Get()      
    Wait bool

    // mu protects fields defined below.
    mu     sync.Mutex
    cond   *sync.Cond
    closed bool
    active int

    //       
    idle list.List
}

接続プールからの接続の取得
// get prunes stale connections and returns a connection from the idle list or
// creates a new connection.
func (p *Pool) get() (Conn, error) {
    p.mu.Lock()

    //  idle           
    if timeout := p.IdleTimeout; timeout > 0 {
        for i, n := 0, p.idle.Len(); i < n; i++ {
            e := p.idle.Back()//  idle          (      )
            if e == nil {
                break
            }
            ic := e.Value.(idleConn)
            if ic.t.Add(timeout).After(nowFunc()) { //                ,     
                break
            }
            p.idle.Remove(e)//            
            p.release()//  p.active,         
            p.mu.Unlock()
            ic.c.Close()//    
            p.mu.Lock()
        }
    }

    for {

        //  idle            
        for i, n := 0, p.idle.Len(); i < n; i++ {
            e := p.idle.Front()// idle       ,         
            if e == nil {
                break
            }
            ic := e.Value.(idleConn)
            p.idle.Remove(e)//           
            test := p.TestOnBorrow
            p.mu.Unlock()
            if test == nil || test(ic.c, ic.t) == nil {//         ,           
                return ic.c, nil//          ,     
            }
            ic.c.Close()//   ,     
            p.mu.Lock()
            p.release()//  p.active,         
        }

        //   pool       
        if p.closed {
            p.mu.Unlock()
            return nil, errors.New("redigo: get on closed pool")
        }

        //       
        if p.MaxActive == 0 || p.active < p.MaxActive {//          active  
            dial := p.Dial
            p.active += 1
            p.mu.Unlock()
            c, err := dial()//  dial       
            if err != nil {
                p.mu.Lock()
                p.release()
                p.mu.Unlock()
                c = nil
            }
            return c, err
        }

        //                    
        if !p.Wait {//          
            p.mu.Unlock()
            return nil, ErrPoolExhausted
        }

        if p.cond == nil {
            p.cond = sync.NewCond(&p.mu)
        }
        p.cond.Wait()//  ,    
    }
}

接続を閉じる
func (p *Pool) put(c Conn, forceClose bool) error {
    err := c.Err()
    p.mu.Lock()
    if !p.closed && err == nil && !forceClose {//p    ,     ,         
        p.idle.PushFront(idleConn{t: nowFunc(), c: c})//         idle   
        if p.idle.Len() > p.MaxIdle {//   idle       (      1)
            c = p.idle.Remove(p.idle.Back()).(idleConn).c// idle         
        } else {
            c = nil
        }
    }

    if c == nil {
        if p.cond != nil {
            p.cond.Signal()//                 
        }
        p.mu.Unlock()
        return nil
    }

    p.release()//  active  
    p.mu.Unlock()
    return c.Close()//     
}

シーンの設定
主なパラメータを見てみましょう
  • MaxIdle
  • は、接続プールの空き接続リストの長さ制限
  • を示す.
  • 空きリストは桟式の構造で、先進的に
  • を出た.
  • MaxActive
  • 接続プールの中で最も大きい接続数の制限
  • を表す
  • は、サービス側がサポートする接続数の上限と、アプリケーション間の「分割」接続数
  • を主に考慮する.
  • IdleTimeout
  • アイドル接続のタイムアウト設定は、タイムアウトするとアイドルリストから
  • が削除される.
  • このタイムアウト時間は、サービス側の接続タイムアウト設定
  • よりも小さいべきである.

    2つの使用シーンを区別します.
  • 高周波呼び出しのシーンは、redisのパフォーマンスをできるだけ搾取する必要があります.
  • MaxIdleのサイズを大きくします.この数はmaxActiveより小さいです.バッファとして同じように存在するため、バッファを拡大しても問題はありません.
  • MaxActiveを高くし、サービス側のサポート上限を考慮して、できるだけ
  • を高くします.
  • IdleTimeout高周波使用シーンなので、設定が短くても構いませんが、注意すべき点はMaxIdle設定が長くなり、キュー内の期限切れの接続が増える可能性があります.このときIdleTimeoutもそれに応じて
  • 変化します.
  • 低周波呼び出しのシーンは、呼び出し量がredisの負荷に達していないため、安定性が重要です.
  • MaxIdleで設定できる小さな
  • IdleTimeoutはそれに応じて小さい
  • を設定する.
  • MaxActive随意、足りればいい、異常を検出しやすい