Overview
The Redis Stream Source Connector reads messages from one Redis Stream, converts each Stream message into a Kafka Connect SourceRecord, and writes it to a Kafka topic. It sits between Redis and Kafka and is suitable for bringing business events, task statuses, or real-time notifications from a Redis Stream into a Kafka data pipeline. The Connector uses a Redis consumer group to distribute messages. The Kafka message key is the Redis Stream message ID, and the value is a structure containingid, stream, and the string field map body. The destination topic can be specified explicitly or generated from the Redis Stream name by using ${stream}.
License
Licensed under the Apache License 2.0.Quick Start
Prepare a Connect Cluster, Kafka, and a Redis service, and confirm that the Connect Worker can access Redis and Kafka. If automatic topic creation is disabled in the Kafka cluster, create the destination topic before starting the connector. For preparation and management procedures, see Manage Connectors.<redis-host> with the Redis address and <redis-stream-name> with the Redis Stream key to read. The example uses the default Redis port 6379, the default consumer group, and the at-least-once delivery mode. By default, the destination topic has the same name as the Redis Stream. If authentication, TLS, or a fixed destination topic is required, add the corresponding configuration before creating the Connector.
Configuration
Redis Connection
redis.cluster
Selects the Redis standalone client or Redis Cluster client.
- Type:
boolean - Default:
false - Importance: Medium
- Valid Values / Notes:
falseuses the standalone client, andtrueuses the Cluster client. The address or URI must match the selected deployment mode.
redis.host
The Redis hostname or address.
- Type:
string - Default:
localhost - Importance: High
- Valid Values / Notes: Used only when
redis.uriis empty, together withredis.port. The address must be resolvable and accessible from the Connect Worker.
redis.port
The Redis TCP port.
- Type:
int - Default:
6379 - Importance: High
- Valid Values / Notes: Used only when
redis.uriis empty, together withredis.host. ConfigDef does not validate the port range, so specify a valid port on which Redis is actually listening.
redis.uri
Specifies the connection endpoint with a Redis URI.
- Type:
string - Default: Empty string
- Importance: Medium
- Valid Values / Notes: A non-empty value takes precedence over
redis.hostandredis.port. It supports client-acceptedredis://andrediss://URIs. A URI can contain credentials and must be handled as sensitive information. A non-emptyredis.passwordapplies separately configured credentials after endpoint selection.
redis.timeout
The Redis command timeout in seconds.
- Type:
long - Default:
60 - Importance: Medium
- Valid Values / Notes: Use a positive number appropriate for Redis response latency. ConfigDef does not validate the range, and an invalid duration can fail during client construction or at runtime.
Redis Authentication
redis.username
The Redis ACL username.
- Type:
string - Default: Empty string
- Importance: Medium
- Valid Values / Notes: Used only when
redis.passwordis non-empty. Leave it empty to use password-only authentication.
redis.password
The Redis password.
- Type:
password - Default: Empty string
- Importance: Medium
- Valid Values / Notes: A non-empty value enables separate credential configuration. When
redis.usernameis also set, ACL username and password authentication is used; otherwise, password-only authentication is used. Supply this value through a controlled Secret or Config Provider.
TLS
redis.tls
Explicitly enables TLS for a Redis connection constructed from redis.host and redis.port.
- Type:
boolean - Default:
false - Importance: Medium
- Valid Values / Notes: Set it to
trueto enable TLS. Whenredis.uriusesrediss://, the connection uses TLS even if this setting remainsfalse; however,redis.insecureis read only when this configuration is explicitly set totrue.
redis.insecure
Disables TLS peer certificate verification.
- Type:
boolean - Default:
false - Importance: Medium
- Valid Values / Notes: Effective only when
redis.tls=true. Do not enable it in production. If onlyrediss://is configured without settingredis.tls=true, this value does not affect the certificate verification branch.
redis.cacert
Specifies the CA certificate file used to verify the Redis server certificate.
- Type:
string - Default: Empty string
- Importance: Medium
- Valid Values / Notes: A non-empty value must point to an X.509 CA certificate file readable by the Connect Worker.
redis.key.file
Specifies the TLS client private key file.
- Type:
string - Default: Empty string
- Importance: Medium
- Valid Values / Notes: A non-empty value enables the client Key Manager. The file must be a PKCS#8 PEM private key readable by the Connect Worker, and a matching
redis.key.certmust also be provided.
redis.key.cert
Specifies the TLS client certificate chain file.
- Type:
string - Default: Empty string
- Importance: Medium
- Valid Values / Notes: Read only when
redis.key.fileis non-empty. It must point to a PEM X.509 certificate chain that matches the private key and is readable by the Connect Worker.
redis.key.password
Specifies the password for the TLS client private key.
- Type:
password - Default: Empty string
- Importance: Medium
- Valid Values / Notes: Read only when
redis.key.fileis non-empty. Leave it empty for an unencrypted private key. For an encrypted private key, supply the password through a controlled Secret or Config Provider.
Stream Selection and Routing
redis.stream.name
Specifies the Redis Stream key to read.
- Type:
string - Default: None
- Importance: High
- Valid Values / Notes: One Connector instance reads only one Stream. A usable Redis key must be provided. Although an explicitly empty string passes ConfigDef string parsing, it cannot form a valid deployment.
- Required: Yes
topic
Specifies the Kafka topic to which SourceRecords are written.
- Type:
string - Default:
${stream} - Importance: Medium
- Valid Values / Notes:
${stream}is replaced with the Redis Stream name. A fixed topic name can also be specified. The final name must meet Kafka topic naming, existence or automatic creation, and authorization requirements. Other placeholders are not resolved.
redis.stream.offset
Specifies the initial Redis Stream offset to use when no Kafka Connect source offset has been stored.
- Type:
string - Default:
0-0 - Importance: Medium
- Valid Values / Notes: Use a message ID accepted by the Redis Stream reader. On restart, a stored Kafka Connect offset takes precedence over this value. An existing consumer group also does not reset its server-side cursor when this value changes.
Consumer Group and Delivery
redis.stream.consumer.group
Specifies the Redis Stream consumer group name.
- Type:
string - Default:
kafka-consumer-group - Importance: Medium
- Valid Values / Notes: All tasks for the same Connector use this consumer group. Changing the group name switches the Redis Pending Entry and acknowledgment state used by the Connector.
redis.stream.consumer.name
Specifies the Redis Stream consumer name template.
- Type:
string - Default:
consumer-${task} - Importance: Medium
- Valid Values / Notes:
${task}is replaced with the numeric task ID. Whentasks.maxis greater than1, retain this placeholder to prevent multiple tasks from using the same consumer identity.
redis.stream.delivery
Selects the Redis Stream message acknowledgment mode.
- Type:
string - Default:
at-least-once - Importance: Medium
- Valid Values / Notes: Accepts only the case-sensitive values
at-least-onceorat-most-once. The former acknowledges messages when the SourceTask commits and can replay them. The latter acknowledges messages immediately after reading, so a failure window can cause message loss. Neither provides an exactly-once transaction across Redis and Kafka.
Read Cadence
batch.size
Sets the maximum number of records for each Redis read request.
- Type:
int - Default:
500 - Importance: Low
- Valid Values / Notes: Use a positive number. It limits the number of records in one read request, not the total number of Pending Entries or the total memory across multiple polls. ConfigDef does not validate the bounds.
redis.stream.block
Sets the blocking duration for Redis XREADGROUP, in milliseconds.
- Type:
long - Default:
100 - Importance: Low
- Valid Values / Notes: Use a non-negative value supported by the Redis client. This value directly affects how long one poll waits when no new message is available. ConfigDef does not validate the range.
Compatibility Configuration
redis.pool
The inherited Redis connection pool size configuration.
- Type:
int - Default:
8 - Importance: Medium
- Valid Values / Notes: This configuration is publicly settable, but the Stream read path in RedisStreamSourceConnector 0.9.1 does not use it. Changing it has no confirmed Stream Source tuning effect.
Kafka Connect Framework
connector.class
Specifies the Connector implementation class to load.
- Type:
string - Default: None
- Importance: High
- Valid Values / Notes: Must be set to
com.redis.kafka.connect.RedisStreamSourceConnector. - Required: Yes
tasks.max
Sets the maximum number of tasks that Kafka Connect creates for the Connector.
- Type:
int - Default:
1 - Importance: High
- Valid Values / Notes: Must be at least
1. Every task reads the same Redis Stream and consumer group. With multiple tasks, retainredis.stream.consumer.namewith the${task}placeholder.
tasks.max.enforce
Controls whether the framework enforces the tasks.max limit.
- Type:
boolean - Default:
true - Importance: Low
- Valid Values / Notes: Kafka Connect has deprecated this configuration and plans to remove it in a future major version. Keep the default and use
tasks.maxto set the scale. - Deprecated: Yes
- Replacement: None
key.converter
Specifies the Kafka Connect Converter for the Redis Stream message ID key.
- Type:
class - Default:
null - Importance: Low
- Valid Values / Notes: When omitted, inherits the Worker’s key Converter. The Connector emits a non-null key with a STRING schema, so select a Converter compatible with that schema.
value.converter
Specifies the Kafka Connect Converter for the structured message value.
- Type:
class - Default:
null - Importance: Low
- Valid Values / Notes: When omitted, inherits the Worker’s value Converter. The Connector emits a STRUCT containing
id,stream, and aMAP<STRING,STRING>typebody, so select a Converter that supports these schemas.
Best Practices
Enable TLS and ACL Authentication for Production Onboarding
Applicable Scenario: Redis is on a production network or uses ACLs to manage access. The connection between the Connect Worker and Redis must be encrypted, while the Connector is granted only the permissions needed to read the target Stream and use the consumer group. Configuration Example: Add the following connection configuration to the Quick Start configuration.redis.insecure=true in production. If Redis requires mutual TLS, also configure a matching client private key and certificate chain.
Tune the Read Cadence for Throughput and Idle Latency
Applicable Scenario: The Connector is reading a single Stream reliably, and you need to balance per-request processing overhead, throughput, and return latency when no new messages are available. Start with the defaults, observe throughput, latency, and Worker resources, and then make small adjustments. Configuration Example: The following example increases the number of records per request and allows idle reads to wait longer.batch.size is the record count limit for one Redis read request, not a total memory or Pending Entry limit. redis.stream.block directly increases the wait time for an idle poll. The example values are not universally optimal. Adjust them gradually based on message size, destination topic write capacity, task latency, and Worker memory.
Add Tasks When a Single Stream Has a Sustained Backlog
Applicable Scenario: A single task has become the read bottleneck, the Redis Stream consumer group has a sustained backlog, and Kafka and the Connect Workers still have processing capacity. Adding tasks allows multiple Redis consumers in the same consumer group to process new messages. Configuration Example: The following example creates two tasks for the same Stream and retains task-specific consumer names.Monitoring
What to Monitor
Monitor general Kafka Connect health, Connector and task status, throughput, latency, offset commits, errors, retries, and Worker JVM signals. Also monitor the Redis consumer group backlog and Pending Entry changes. Monitor DLQ activity only when the corresponding error handling is enabled in the deployment.Import the Grafana Dashboard
Confirm that Kafka Connect metrics are available through a Grafana data source and that the collected labels meet the dashboard filter requirements. Download the Kafka Connect Dashboard, import the JSON into Grafana, and select the corresponding data source.Limitations
- One Connector instance can read only one Redis Stream key. Stream lists and pattern matching are not supported.
- An existing Redis consumer group does not reset its server-side cursor when
redis.stream.offsetchanges. On restart, a stored Kafka Connect source offset also takes precedence over this configuration. - The Connector does not provide an exactly-once transaction or duplicate suppression across Redis acknowledgment and Kafka writes. The
at-least-oncemode can replay messages, while theat-most-oncemode can lose a message after acknowledgment and before it is written to Kafka. - The Connector recovers only Pending Entries owned by the current consumer identity. It does not automatically use
XCLAIMorXAUTOCLAIMto take over messages owned by other consumers. - In version 0.9.1, all tasks use the same empty source partition and therefore share one Kafka Connect source-offset key. Do not assume that each Redis consumer has an independent recovery checkpoint; multi-task failure recovery requires separate validation.
- In version 0.9.1, a successful commit in
at-least-oncemode does not clear the message IDs accumulated by the task. Later commits resend historicalXACKIDs to Redis, and the in-memory list grows for the lifetime of the task. Long-running, high-throughput workloads can therefore increase task memory use and Redis acknowledgment overhead; no safe threshold has been verified. - Ordering is limited to the result of one poll by a single task. Multiple tasks or a multi-partition Kafka topic do not provide global ordering.
- The message value schema is fixed as a map of string fields. It does not preserve arbitrary binary field values or automatically infer or evolve field types.
FAQ
Why Does Reading Not Start from the New Position After I Change redis.stream.offset?
A stored Kafka Connect source offset takes precedence over redis.stream.offset, and the Connector does not reset the server-side cursor when it opens an existing Redis consumer group. First check the consumer group in use, the Kafka Connect offset, and the Redis group state. To establish an independent read baseline, use a new consumer group and handle Pending Entries from the original group carefully instead of changing only the initial offset.
Why Do Duplicate Messages Appear in Kafka?
The defaultat-least-once mode acknowledges Redis messages when Kafka Connect commits, and there is no cross-system transaction among the Redis read, Kafka write, and offset commit. If a failure occurs after the write but before acknowledgment or offset persistence, a message can be replayed after restart. The Kafka message key is the Redis Stream message ID, which downstream systems can use for idempotent processing or deduplication.
Why Are Pending Entries from an Old Consumer Not Processed After Reducing the Number of Tasks?
The Connector reads only Pending Entries owned by the current consumer name and does not automatically take over messages owned by other consumers. Check the owner of each Pending Entry in the Redis consumer group. During scaling, keep the consumer names generated byconsumer-${task} stable, handle a consumer’s Pending Entries before removing it, and explicitly transfer ownership through Redis operational procedures when necessary.
Why Does the Message Timestamp Differ from the Time in the Redis Stream ID?
The SourceRecord timestamp comes from the Worker clock when the Connector converts the message, not from the time component encoded in the Redis Stream ID. When event time is required, write the business timestamp explicitly into a Stream message field and have downstream systems extract and use it frombody.