Skip to content

Commit 14685b9

Browse files
committed
add configurable buffer sizes for Redis connections
1 parent be6dfd5 commit 14685b9

File tree

7 files changed

+107
-4
lines changed

7 files changed

+107
-4
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ func main() {
297297
```
298298
299299
300+
### Buffer Size Configuration
301+
302+
go-redis uses 0.5MiB read and write buffers by default for optimal performance. For high-throughput applications or large pipelines, you can customize buffer sizes:
303+
304+
```go
305+
rdb := redis.NewClient(&redis.Options{
306+
Addr: "localhost:6379",
307+
ReadBufferSize: 1024 * 1024, // 1MiB read buffer
308+
WriteBufferSize: 1024 * 1024, // 1MiB write buffer
309+
})
310+
```
311+
300312
### Advanced Configuration
301313
302314
go-redis supports extending the client identification phase to allow projects to send their own custom client identification.

internal/pool/conn.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,28 @@ type Conn struct {
2828
}
2929

3030
func NewConn(netConn net.Conn) *Conn {
31+
return NewConnWithBufferSize(netConn, proto.DefaultBufferSize, proto.DefaultBufferSize)
32+
}
33+
34+
func NewConnWithBufferSize(netConn net.Conn, readBufSize, writeBufSize int) *Conn {
3135
cn := &Conn{
3236
netConn: netConn,
3337
createdAt: time.Now(),
3438
}
35-
cn.rd = proto.NewReader(netConn)
36-
cn.bw = bufio.NewWriter(netConn)
39+
40+
// Use specified buffer sizes, or fall back to 0.5MiB defaults if 0
41+
if readBufSize > 0 {
42+
cn.rd = proto.NewReaderSize(netConn, readBufSize)
43+
} else {
44+
cn.rd = proto.NewReader(netConn) // Uses 0.5MiB default
45+
}
46+
47+
if writeBufSize > 0 {
48+
cn.bw = bufio.NewWriterSize(netConn, writeBufSize)
49+
} else {
50+
cn.bw = bufio.NewWriterSize(netConn, proto.DefaultBufferSize)
51+
}
52+
3753
cn.wr = proto.NewWriter(cn.bw)
3854
cn.SetUsedAt(time.Now())
3955
return cn

internal/pool/pool.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ type Options struct {
7171
MaxActiveConns int
7272
ConnMaxIdleTime time.Duration
7373
ConnMaxLifetime time.Duration
74+
75+
ReadBufferSize int
76+
WriteBufferSize int
7477
}
7578

7679
type lastDialErrorWrap struct {
@@ -226,7 +229,7 @@ func (p *ConnPool) dialConn(ctx context.Context, pooled bool) (*Conn, error) {
226229
return nil, err
227230
}
228231

229-
cn := NewConn(netConn)
232+
cn := NewConnWithBufferSize(netConn, p.cfg.ReadBufferSize, p.cfg.WriteBufferSize)
230233
cn.pooled = pooled
231234
return cn, nil
232235
}

internal/proto/reader.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import (
1212
"github.com/redis/go-redis/v9/internal/util"
1313
)
1414

15+
// DefaultBufferSize is the default size for read/write buffers (0.5MiB)
16+
const DefaultBufferSize = 512 * 1024
17+
1518
// redis resp protocol data type.
1619
const (
1720
RespStatus = '+' // +<string>\r\n
@@ -58,7 +61,13 @@ type Reader struct {
5861

5962
func NewReader(rd io.Reader) *Reader {
6063
return &Reader{
61-
rd: bufio.NewReader(rd),
64+
rd: bufio.NewReaderSize(rd, DefaultBufferSize),
65+
}
66+
}
67+
68+
func NewReaderSize(rd io.Reader, size int) *Reader {
69+
return &Reader{
70+
rd: bufio.NewReaderSize(rd, size),
6271
}
6372
}
6473

options.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/redis/go-redis/v9/auth"
1717
"github.com/redis/go-redis/v9/internal/pool"
18+
"github.com/redis/go-redis/v9/internal/proto"
1819
)
1920

2021
// Limiter is the interface of a rate limiter or a circuit breaker.
@@ -130,6 +131,18 @@ type Options struct {
130131
// See https://redis.uptrace.dev/guide/go-redis-debugging.html#timeouts
131132
ContextTimeoutEnabled bool
132133

134+
// ReadBufferSize is the size of the bufio.Reader buffer for each connection.
135+
// Larger buffers can improve performance for commands that return large responses.
136+
//
137+
// default: 0.5MiB (524288 bytes)
138+
ReadBufferSize int
139+
140+
// WriteBufferSize is the size of the bufio.Writer buffer for each connection.
141+
// Larger buffers can improve performance for large pipelines and commands with many arguments.
142+
//
143+
// default: 0.5MiB (524288 bytes)
144+
WriteBufferSize int
145+
133146
// PoolFIFO type of connection pool.
134147
//
135148
// - true for FIFO pool
@@ -241,6 +254,12 @@ func (opt *Options) init() {
241254
if opt.PoolSize == 0 {
242255
opt.PoolSize = 10 * runtime.GOMAXPROCS(0)
243256
}
257+
if opt.ReadBufferSize == 0 {
258+
opt.ReadBufferSize = proto.DefaultBufferSize
259+
}
260+
if opt.WriteBufferSize == 0 {
261+
opt.WriteBufferSize = proto.DefaultBufferSize
262+
}
244263
switch opt.ReadTimeout {
245264
case -2:
246265
opt.ReadTimeout = -1
@@ -592,5 +611,7 @@ func newConnPool(
592611
MaxActiveConns: opt.MaxActiveConns,
593612
ConnMaxIdleTime: opt.ConnMaxIdleTime,
594613
ConnMaxLifetime: opt.ConnMaxLifetime,
614+
ReadBufferSize: opt.ReadBufferSize,
615+
WriteBufferSize: opt.WriteBufferSize,
595616
})
596617
}

osscluster.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ type ClusterOptions struct {
9292
ConnMaxIdleTime time.Duration
9393
ConnMaxLifetime time.Duration
9494

95+
// ReadBufferSize is the size of the bufio.Reader buffer for each connection.
96+
// Larger buffers can improve performance for commands that return large responses.
97+
//
98+
// default: 0.5MiB (524288 bytes)
99+
ReadBufferSize int
100+
101+
// WriteBufferSize is the size of the bufio.Writer buffer for each connection.
102+
// Larger buffers can improve performance for large pipelines and commands with many arguments.
103+
//
104+
// default: 0.5MiB (524288 bytes)
105+
WriteBufferSize int
106+
95107
TLSConfig *tls.Config
96108

97109
// DisableIndentity - Disable set-lib on connect.
@@ -127,6 +139,12 @@ func (opt *ClusterOptions) init() {
127139
if opt.PoolSize == 0 {
128140
opt.PoolSize = 5 * runtime.GOMAXPROCS(0)
129141
}
142+
if opt.ReadBufferSize == 0 {
143+
opt.ReadBufferSize = proto.DefaultBufferSize
144+
}
145+
if opt.WriteBufferSize == 0 {
146+
opt.WriteBufferSize = proto.DefaultBufferSize
147+
}
130148

131149
switch opt.ReadTimeout {
132150
case -1:
@@ -318,6 +336,8 @@ func (opt *ClusterOptions) clientOptions() *Options {
318336
MaxActiveConns: opt.MaxActiveConns,
319337
ConnMaxIdleTime: opt.ConnMaxIdleTime,
320338
ConnMaxLifetime: opt.ConnMaxLifetime,
339+
ReadBufferSize: opt.ReadBufferSize,
340+
WriteBufferSize: opt.WriteBufferSize,
321341
DisableIdentity: opt.DisableIdentity,
322342
DisableIndentity: opt.DisableIdentity,
323343
IdentitySuffix: opt.IdentitySuffix,

ring.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/redis/go-redis/v9/internal"
1919
"github.com/redis/go-redis/v9/internal/hashtag"
2020
"github.com/redis/go-redis/v9/internal/pool"
21+
"github.com/redis/go-redis/v9/internal/proto"
2122
"github.com/redis/go-redis/v9/internal/rand"
2223
)
2324

@@ -113,6 +114,18 @@ type RingOptions struct {
113114
ConnMaxIdleTime time.Duration
114115
ConnMaxLifetime time.Duration
115116

117+
// ReadBufferSize is the size of the bufio.Reader buffer for each connection.
118+
// Larger buffers can improve performance for commands that return large responses.
119+
//
120+
// default: 0.5MiB (524288 bytes)
121+
ReadBufferSize int
122+
123+
// WriteBufferSize is the size of the bufio.Writer buffer for each connection.
124+
// Larger buffers can improve performance for large pipelines and commands with many arguments.
125+
//
126+
// default: 0.5MiB (524288 bytes)
127+
WriteBufferSize int
128+
116129
TLSConfig *tls.Config
117130
Limiter Limiter
118131

@@ -164,6 +177,13 @@ func (opt *RingOptions) init() {
164177
case 0:
165178
opt.MaxRetryBackoff = 512 * time.Millisecond
166179
}
180+
181+
if opt.ReadBufferSize == 0 {
182+
opt.ReadBufferSize = proto.DefaultBufferSize
183+
}
184+
if opt.WriteBufferSize == 0 {
185+
opt.WriteBufferSize = proto.DefaultBufferSize
186+
}
167187
}
168188

169189
func (opt *RingOptions) clientOptions() *Options {
@@ -195,6 +215,8 @@ func (opt *RingOptions) clientOptions() *Options {
195215
MaxActiveConns: opt.MaxActiveConns,
196216
ConnMaxIdleTime: opt.ConnMaxIdleTime,
197217
ConnMaxLifetime: opt.ConnMaxLifetime,
218+
ReadBufferSize: opt.ReadBufferSize,
219+
WriteBufferSize: opt.WriteBufferSize,
198220

199221
TLSConfig: opt.TLSConfig,
200222
Limiter: opt.Limiter,

0 commit comments

Comments
 (0)