Skip to content

Feature Request: Support read/write separation in Redis adapters to prevent blocking and improve scalabilityΒ #141

@zishang520

Description

@zishang520

Background

Currently, the Redis adapters in this project use a single Redis client (and thus a shared connection pool) for both reading/polling operations and writing operations.

The Problem

Using a single Redis client for both read and write operations introduces significant performance and scalability bottlenecks under heavy load:

  1. Connection Blocking / Pool Starvation: Read operations like XREAD BLOCK (in Redis Streams) or SUBSCRIBE (in standard Redis Pub/Sub) are blocking or long-lived by nature. Sharing the same connection pool for high-throughput write operations (e.g., XADD, PUBLISH, SET for session persistence) can lead to connection starvation, where writes are delayed because connections are held by blocking reads.
  2. Inability to Scale via Redis Replicas: In production environments, it is a common best practice to route read operations to Redis Replicas and write operations to the Redis Master. The current single-client design prevents users from utilizing Redis read replicas effectively.

Affected Adapters

This issue applies to all current Redis-based adapters:

  • RedisAdapter
  • ShardedRedisAdapter
  • RedisStreamsAdapter

Proposed Solution

We should introduce read/write separation by allowing users to provide two distinct Redis clients in the adapter options.

For example, following the convention in the official socket.io-redis ecosystem, the API could accept a pubClient (for writes/publishing) and a subClient (for reads/subscribing/polling):

// Example API design
type RedisAdapterOptions struct {
    WriteClient *redis.RedisClient // Used for PUBLISH, XADD, SET, etc.
    ReadClient  *redis.RedisClient // Used for SUBSCRIBE, XREAD, GET, etc.
    // ... other options
}

(If only one client is provided, it can fallback to using the same client for both to maintain backward compatibility).

Benefits

  • Performance: Eliminates the risk of blocking read operations starving the connection pool for write operations.
  • High Availability & Scaling: Allows users to configure the ReadClient to target a Redis read-replica endpoint, distributing the load and preventing the Redis Master from being overwhelmed.
  • Ecosystem Consistency: Aligns with the standard Node.js socket.io-redis implementation which heavily utilizes separate pubClient and subClient configurations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions