From 1229016f2b3df5ea736f195f4ff6f4711ef10472 Mon Sep 17 00:00:00 2001 From: Kim Tae Kwon Date: Tue, 13 Jul 2021 16:34:01 +0800 Subject: [PATCH 1/4] Initial commit for FIFO pool --- internal/pool/pool.go | 22 ++++++++++++++++++---- options.go | 5 +++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/internal/pool/pool.go b/internal/pool/pool.go index a8f0a6d4e..605f05878 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -11,7 +11,12 @@ import ( "github.com/go-redis/redis/v8/internal" ) +type PoolType string + var ( + PoolLifo PoolType = "" + PoolFifo PoolType = "fifo" + // ErrClosed performs any operation on the closed client will return this error. ErrClosed = errors.New("redis: client is closed") @@ -57,6 +62,7 @@ type Options struct { Dialer func(context.Context) (net.Conn, error) OnClose func(*Conn) error + PoolType PoolType PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -308,13 +314,21 @@ func (p *ConnPool) freeTurn() { } func (p *ConnPool) popIdle() *Conn { - if len(p.idleConns) == 0 { + n := len(p.idleConns) + if n == 0 { return nil } - idx := len(p.idleConns) - 1 - cn := p.idleConns[idx] - p.idleConns = p.idleConns[:idx] + var cn *Conn + if p.opt.PoolType == PoolFifo { + cn = p.idleConns[0] + copy(p.idleConns, p.idleConns[1:]) + p.idleConns = p.idleConns[:n-1] + } else { + idx := n - 1 + cn = p.idleConns[idx] + p.idleConns = p.idleConns[:idx] + } p.idleConnsLen-- p.checkMinIdleConns() return cn diff --git a/options.go b/options.go index 8bbc27b82..fcb9a3cda 100644 --- a/options.go +++ b/options.go @@ -76,6 +76,10 @@ type Options struct { // Default is ReadTimeout. WriteTimeout time.Duration + // Type of Pool + // Default is lifo, supports fifo too + // Note that fifo has higher overhead compared to lifo + PoolType pool.PoolType // Maximum number of socket connections. // Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. PoolSize int @@ -291,6 +295,7 @@ func newConnPool(opt *Options) *pool.ConnPool { Dialer: func(ctx context.Context) (net.Conn, error) { return opt.Dialer(ctx, opt.Network, opt.Addr) }, + PoolType: opt.PoolType, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, From 8548dcb3cb46193c78b2259904bbd10fe6b98c8f Mon Sep 17 00:00:00 2001 From: Kim Tae Kwon Date: Wed, 14 Jul 2021 17:18:41 +0800 Subject: [PATCH 2/4] Change PoolType string to PoolFIFO bool --- internal/pool/pool.go | 9 +++------ options.go | 10 +++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 605f05878..c66709894 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -11,12 +11,9 @@ import ( "github.com/go-redis/redis/v8/internal" ) -type PoolType string +type PoolFIFO bool var ( - PoolLifo PoolType = "" - PoolFifo PoolType = "fifo" - // ErrClosed performs any operation on the closed client will return this error. ErrClosed = errors.New("redis: client is closed") @@ -62,7 +59,7 @@ type Options struct { Dialer func(context.Context) (net.Conn, error) OnClose func(*Conn) error - PoolType PoolType + PoolFIFO bool PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -320,7 +317,7 @@ func (p *ConnPool) popIdle() *Conn { } var cn *Conn - if p.opt.PoolType == PoolFifo { + if p.opt.PoolFIFO { cn = p.idleConns[0] copy(p.idleConns, p.idleConns[1:]) p.idleConns = p.idleConns[:n-1] diff --git a/options.go b/options.go index fcb9a3cda..5d39bf049 100644 --- a/options.go +++ b/options.go @@ -76,10 +76,10 @@ type Options struct { // Default is ReadTimeout. WriteTimeout time.Duration - // Type of Pool - // Default is lifo, supports fifo too - // Note that fifo has higher overhead compared to lifo - PoolType pool.PoolType + // Type of connection pool. + // true for FIFO pool, false for LIFO pool. + // Note that fifo has higher overhead compared to lifo. + PoolFIFO bool // Maximum number of socket connections. // Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. PoolSize int @@ -295,7 +295,7 @@ func newConnPool(opt *Options) *pool.ConnPool { Dialer: func(ctx context.Context) (net.Conn, error) { return opt.Dialer(ctx, opt.Network, opt.Addr) }, - PoolType: opt.PoolType, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, From 6b0689492797c73c4c63396262793c709fccffae Mon Sep 17 00:00:00 2001 From: Kim Tae Kwon Date: Thu, 15 Jul 2021 16:33:38 +0800 Subject: [PATCH 3/4] Remove redundant type --- internal/pool/pool.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/pool/pool.go b/internal/pool/pool.go index c66709894..91b55e466 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -11,8 +11,6 @@ import ( "github.com/go-redis/redis/v8/internal" ) -type PoolFIFO bool - var ( // ErrClosed performs any operation on the closed client will return this error. ErrClosed = errors.New("redis: client is closed") From 2f705aa5fbde67761b6d16023a428817eb747b35 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Fri, 16 Jul 2021 11:37:22 +0800 Subject: [PATCH 4/4] add PoolFIFO option to all clients Signed-off-by: monkey92t --- cluster.go | 4 ++++ ring.go | 4 ++++ sentinel.go | 6 ++++++ universal.go | 6 ++++++ 4 files changed, 20 insertions(+) diff --git a/cluster.go b/cluster.go index 49b2d37bd..9690f88a8 100644 --- a/cluster.go +++ b/cluster.go @@ -68,6 +68,9 @@ type ClusterOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + // PoolSize applies per cluster node and not for the whole cluster. PoolSize int MinIdleConns int @@ -146,6 +149,7 @@ func (opt *ClusterOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, diff --git a/ring.go b/ring.go index 34d05f35a..5e35b6bb6 100644 --- a/ring.go +++ b/ring.go @@ -78,6 +78,9 @@ type RingOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -138,6 +141,7 @@ func (opt *RingOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, diff --git a/sentinel.go b/sentinel.go index ca2e088a7..7b53fd4f5 100644 --- a/sentinel.go +++ b/sentinel.go @@ -57,6 +57,9 @@ type FailoverOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -86,6 +89,7 @@ func (opt *FailoverOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, @@ -115,6 +119,7 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, @@ -146,6 +151,7 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, diff --git a/universal.go b/universal.go index bb5f8b616..1e962ab3b 100644 --- a/universal.go +++ b/universal.go @@ -35,6 +35,9 @@ type UniversalOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -83,6 +86,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { DialTimeout: o.DialTimeout, ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge, @@ -120,6 +124,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions { ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge, @@ -155,6 +160,7 @@ func (o *UniversalOptions) Simple() *Options { ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge,