| title | Redis |
|---|---|
| description | Redis extension providing high-performance and low-latency event store and snapshot storage. |
The Redis extension provides support for Redis, suitable for scenarios requiring high performance and low latency. It implements the following interfaces:
CommandBus- Command busDomainEventBus- Domain event busStateEventBus- State event busEventStore- Event storageSnapshotStore- Snapshot storePrepareKey- Prepare key
flowchart TB
subgraph Application["Application Layer"]
CG[CommandGateway]
EP[EventProcessor]
AR[Aggregate Root]
end
subgraph Redis["Redis Cluster"]
subgraph Streams["Redis Streams"]
CS["Command Stream"]
ES["Event Stream"]
SS["State Stream"]
end
subgraph Storage["Storage"]
EH["Event Hash"]
SH["Snapshot Hash"]
PK["Prepare Key"]
end
end
CG -->|Send Command| CS
AR -->|Publish Event| ES
AR -->|Publish State| SS
AR -->|Append Event| EH
AR -->|Save Snapshot| SH
AR -->|Prepare Key| PK
CS -->|Consume Command| EP
::: code-group
implementation("me.ahoo.wow:wow-redis")
implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive")implementation 'me.ahoo.wow:wow-redis'
implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'<dependency>
<groupId>me.ahoo.wow</groupId>
<artifactId>wow-redis</artifactId>
<version>${wow.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>:::
- Configuration class: RedisProperties
- Prefix:
wow.redis.
| Name | Data Type | Description | Default Value |
|---|---|---|---|
enabled |
Boolean |
Whether to enable | true |
YAML Configuration Example
spring:
data:
redis:
host: localhost
port: 6379
password: your-password
wow:
command:
bus:
type: redis
event:
bus:
type: redis
eventsourcing:
store:
storage: redis
snapshot:
storage: redis
state:
bus:
type: redis
redis:
enabled: trueThe Redis command bus uses Redis Streams for message delivery:
{prefix}{contextName}.{aggregateName}.command
Example: wow.order-service.order.command
Each processor corresponds to a consumer group:
{contextName}.{processorName}
{prefix}{contextName}.{aggregateName}.event
{prefix}{contextName}.{aggregateName}.state
Redis event store uses bucketed Redis Cluster hash tags so event stream append, request idempotency, and aggregate ID scanning indexes can be updated atomically in one Lua script.
Event stream ZSET key: {{contextAlias}.{aggregateName}:es:{bucket}}:{aggregateId}@{tenantId}
Score: {version}
Member: {eventStreamJson}
Request id SET key: {{contextAlias}.{aggregateName}:es:{bucket}}:{aggregateId}@{tenantId}:req_idx
Member: {requestId}
Aggregate ID ZSET key: {{contextAlias}.{aggregateName}:es:{bucket}}:ids
Score: 0
Member: {aggregateId}
Aggregate tenant HASH key: {{contextAlias}.{aggregateName}:es:{bucket}}:tenants
Field: {aggregateId}
Value: {tenantId}
Request IDs are stored in the bucket-aligned SET key shown above.
EventStore.scanAggregateId scans bucketed aggregate ID indexes and merges the results in lexicographical order. Aggregate IDs are globally unique, so the scanner stores one aggregate ID member and resolves its tenant from the bucket-aligned tenant HASH.
Snapshots are stored using Hash structure:
Key: {prefix}{contextName}.{aggregateName}:{aggregateId}:snapshot
Value: {snapshotJson}
PrepareKey uses String structure:
Key: {prefix}prepare:{keyName}:{key}
Value: {preparedValue}
TTL: Based on configuration or permanent
spring:
data:
redis:
lettuce:
pool:
min-idle: 8
max-idle: 16
max-active: 32
max-wait: 1000ms| Parameter | Description | Recommended Value |
|---|---|---|
min-idle |
Minimum idle connections | 8 |
max-idle |
Maximum idle connections | 16 |
max-active |
Maximum active connections | 32 |
max-wait |
Maximum wait time | 1000ms |
spring:
data:
redis:
cluster:
nodes:
- redis-node-1:6379
- redis-node-2:6379
- redis-node-3:6379
max-redirects: 3
lettuce:
cluster:
refresh:
adaptive: true
period: 30sspring:
data:
redis:
sentinel:
master: mymaster
nodes:
- sentinel-1:26379
- sentinel-2:26379
- sentinel-3:26379The Redis extension automatically uses Pipeline to optimize batch operations, reducing network round trips.
- Set Reasonable TTL: Set expiration time for temporary data
- Compressed Storage: Enable data compression to reduce memory usage
- Monitor Memory: Regularly check memory usage
# Redis server configuration recommendations
maxmemory 4gb
maxmemory-policy allkeys-lru
tcp-keepalive 300
timeout 0org.springframework.data.redis.RedisConnectionFailureException
Solutions:
- Check Redis service status
- Verify network connectivity
- Adjust connection timeout configuration
OOM command not allowed when used memory > 'maxmemory'
Solutions:
- Increase Redis memory limit
- Configure reasonable eviction policy
- Clean up unnecessary data
Solutions:
- Increase consumer count
- Optimize message processing logic
- Check Redis service performance
The following Redis metrics should be monitored:
| Metric | Description | Alert Threshold |
|---|---|---|
used_memory |
Memory usage | > 80% maxmemory |
connected_clients |
Connection count | > 1000 |
blocked_clients |
Blocked clients | > 10 |
keyspace_hits/misses |
Cache hit rate | < 90% |
spring:
data:
redis:
host: localhost
port: 6379
password: your-password
database: 0
lettuce:
pool:
min-idle: 8
max-idle: 16
max-active: 32
max-wait: 1000ms
shutdown-timeout: 100ms
wow:
command:
bus:
type: redis
local-first:
enabled: true
event:
bus:
type: redis
local-first:
enabled: true
eventsourcing:
store:
storage: redis
snapshot:
enabled: true
strategy: all
storage: redis
state:
bus:
type: redis
local-first:
enabled: true
redis:
enabled: true- Enable LocalFirst Mode: Process local messages first to reduce network latency
- Use Cluster Mode: Use Redis cluster in production for high availability and scalability
- Configure Connection Pool Properly: Configure appropriate connection pool size based on concurrency
- Monitor Memory Usage: Regularly monitor Redis memory usage to avoid OOM
- Enable Persistence: Configure RDB or AOF persistence to prevent data loss