diff --git a/README.md b/README.md
index 8b5c53a241956c88222267e8368cd3a510bf7d22..017d81ee08a49be719874a54f4338170b875a734 100644
--- a/README.md
+++ b/README.md
@@ -1,751 +1,192 @@
-Table of Contents([中文说明](./README.zh_CN.md))
-=================
-
- * [1. Redis-replicator](#1-redis-replicator)
- * [1.1. Brief introduction](#11-brief-introduction)
- * [1.2. Chat with author](#12-chat-with-author)
- * [1.3. Contract the author](#13-contract-the-author)
- * [2. Install](#2-install)
- * [2.1. Requirements](#21-requirements)
- * [2.2. Maven dependency](#22-maven-dependency)
- * [2.3. Install from source code](#23-install-from-source-code)
- * [2.4. Select a version](#24-select-a-version)
- * [3. Simple usage](#3-simple-usage)
- * [3.1. Usage](#31-usage)
- * [3.2. Backup remote rdb snapshot](#32-backup-remote-rdb-snapshot)
- * [3.3. Backup remote commands](#33-backup-remote-commands)
- * [3.4. Convert rdb to dump format](#34-convert-rdb-to-dump-format)
- * [3.5. Rdb check](#35-rdb-check)
- * [3.6. Scan and PSYNC](#36-scan-and-psync)
- * [3.7. Other examples](#37-other-examples)
- * [4. Advanced topics](#4-advanced-topics)
- * [4.1. Command extension](#41-command-extension)
- * [4.1.1. Write a command](#411-write-a-command)
- * [4.1.2. Write a command parser](#412-write-a-command-parser)
- * [4.1.3. Register this parser](#413-register-this-parser)
- * [4.1.4. Handle command event](#414-handle-command-event)
- * [4.1.5. Put them together](#415-put-them-together)
- * [4.2. Module extension](#42-module-extension)
- * [4.2.1. Compile redis test modules](#421-compile-redis-test-modules)
- * [4.2.2. Open comment in redis.conf](#422-open-comment-in-redisconf)
- * [4.2.3. Write a module parser](#423-write-a-module-parser)
- * [4.2.4. Write a command parser](#424-write-a-command-parser)
- * [4.2.5. Register this module parser and command parser and handle event](#425-register-this-module-parser-and-command-parser-and-handle-event)
- * [4.2.6. Put them together](#426-put-them-together)
- * [4.3. Stream](#43-stream)
- * [4.4. Write your own rdb parser](#44-write-your-own-rdb-parser)
- * [4.5. Redis URI](#45-redis-uri)
- * [5. Other topics](#5-other-topics)
- * [5.1. Built-in command parser](#51-built-in-command-parser)
- * [5.2. EOFException](#52-eofexception)
- * [5.3. Trace event log](#53-trace-event-log)
- * [5.4. SSL connection](#54-ssl-connection)
- * [5.5. Auth](#55-auth)
- * [5.6. Avoid full sync](#56-avoid-full-sync)
- * [5.7. Lifecycle event](#57-lifecycle-event)
- * [5.8. Handle huge key value pair](#58-handle-huge-key-value-pair)
- * [5.9. Redis6 support](#59-redis6-support)
- * [5.9.1. SSL support](#591-ssl-support)
- * [5.9.2. ACL support](#592-acl-support)
- * [5.10. Redis7 support](#510-redis7-support)
- * [5.10.1. Function](#5101-function)
- * [5.11. Redis7.4 support](#511-redis74-support)
- * [5.11.1. TTL Hash](#5111-ttl-hash)
- * [6. Contributors](#6-contributors)
- * [7. Consulting](#7-consulting)
- * [8. References](#8-references)
- * [9. Supported by](#9-supported-by)
- * [9.1. 宁文君](#91-宁文君)
- * [9.2. YourKit](#92-yourkit)
- * [9.3. IntelliJ IDEA](#93-intellij-idea)
- * [9.4. Redisson](#94-redisson)
-
-# 1. Redis-replicator
-
-
-
-## 1.1. Brief introduction
-[](https://github.com/leonchen83/redis-replicator/actions/workflows/maven.yml)
-[](https://coveralls.io/github/leonchen83/redis-replicator?branch=master)
-[](https://maven-badges.herokuapp.com/maven-central/com.moilioncircle/redis-replicator)
-[](http://www.javadoc.io/doc/com.moilioncircle/redis-replicator)
-[](https://github.com/leonchen83/redis-replicator/blob/master/LICENSE)
-[](./ANTI-996-LICENSE)
-
-Redis Replicator implement Redis Replication protocol written in java. It can parse, filter, broadcast the RDB and AOF events in a real time manner. It also can synchronize redis data to your local cache or to database. The following I mentioned `Command` which means `Writable Command`(e.g. `set`,`hmset`) in Redis and excludes the `Readable Command`(e.g. `get`,`hmget`), Supported redis-8.0.x and former redis versions.
-
-## 1.2. Chat with author
-
-[](https://gitter.im/leonchen83/redis-replicator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-
-## 1.3. Contract the author
-
-**chen.bao.yi@gmail.com**
-
-# 2. Install
-## 2.1. Requirements
-compile minimal jdk 9+
-runtime minimal jdk 8+
-maven-3.3.1+
-redis 2.6 - 7.0
-
-## 2.2. Maven dependency
-```xml
-
- com.moilioncircle
- redis-replicator
- 3.9.0
-
-```
-## 2.3. Install from source code
-
-```
- step 1: install jdk-11.0.x for compile
- step 2: git clone https://github.com/leonchen83/redis-replicator.git
- step 3: $cd ./redis-replicator
- step 4: $mvn clean install package -DskipTests
-```
-
-## 2.4. Select a version
-
-| **redis version** | **redis-replicator version** |
-|--------------------|------------------------------|
-| \[2.6, 8.0.x\] | \[3.9.0, \] |
-| \[2.6, 7.2.x\] | \[3.8.0, 3.8.1\] |
-| \[2.6, 7.0.x\] | \[3.6.4, 3.7.0\] |
-| \[2.6, 7.0.x-RC2\] | \[3.6.2, 3.6.3\] |
-| \[2.6, 7.0.0-RC1\] | \[3.6.0, 3.6.1\] |
-| \[2.6, 6.2.x\] | \[3.5.2, 3.5.5\] |
-| \[2.6, 6.2.0-RC1\] | \[3.5.0, 3.5.1\] |
-| \[2.6, 6.0.x\] | \[3.4.0, 3.4.4\] |
-| \[2.6, 5.0.x\] | \[2.6.1, 3.3.3\] |
-| \[2.6, 4.0.x\] | \[2.3.0, 2.5.0\] |
-| \[2.6, 4.0-RC3\] | \[2.1.0, 2.2.0\] |
-| \[2.6, 3.2.x\] | \[1.0.18\](not supported) |
-
-
-# 3. Simple usage
-
-## 3.1. Usage
-
-```java
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof KeyStringValueString) {
- KeyStringValueString kv = (KeyStringValueString) event;
- System.out.println(new String(kv.getKey()));
- System.out.println(new String(kv.getValue()));
- } else {
- ....
- }
- }
- });
- replicator.open();
-```
-## 3.2. Backup remote rdb snapshot
+# Redis Replicator
-See [RdbBackupExample.java](./examples/com/moilioncircle/examples/backup/RdbBackupExample.java)
+Redis-replicator 是一个用于解析 Redis RDB 文件和监听实时 Redis replication 命令的 Java 类库。它支持从 Redis 服务器获取 RDB 快照、监听 replication 流,并解析 Redis 的持久化数据。
-## 3.3. Backup remote commands
+## 功能特性
-See [CommandBackupExample.java](./examples/com/moilioncircle/examples/backup/CommandBackupExample.java)
+- **RDB 文件解析**:读取并解析 Redis RDB 快照文件。
+- **AOF 文件解析**:支持读取和解析 Redis Append-Only 文件。
+- **实时命令监听**:连接 Redis 主服务器并监听所有写入命令。
+- **模块扩展**:支持自定义模块命令和数据类型的解析。
+- **支持 Redis 6 和 Redis 7 的新特性**:包括 SSL、ACL 以及 Redis Function。
+- **支持 Sentinel 和 Cluster**:可以处理高可用 Redis 部署。
+- **流式处理**:支持 Redis Stream 数据结构的解析。
+- **TTL Hash 扩展**:支持 Redis 7.4 的 TTL Hash 特性。
-## 3.4. Convert rdb to dump format
+## 安装
-We can use `DumpRdbVisitor` to convert rdb to redis [DUMP](https://redis.io/commands/dump) format.
-
-```java
+### Maven 依赖
- Replicator r = new RedisReplicator("redis:///path/to/dump.rdb");
- r.setRdbVisitor(new DumpRdbVisitor(r));
- r.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (!(event instanceof DumpKeyValuePair)) return;
- DumpKeyValuePair dkv = (DumpKeyValuePair) event;
- byte[] serialized = dkv.getValue();
- // we can use redis RESTORE command to migrate this serialized value to another redis.
- }
- });
- r.open();
+在你的 `pom.xml` 文件中添加如下依赖:
+```xml
+
+ com.moilioncircle
+ redis-replicator
+ 3.9.0
+
```
-## 3.5. Rdb check
-
-We can use `SkipRdbVisitor` to check rdb's correctness.
+### 源码安装
-```java
-
- Replicator r = new RedisReplicator("redis:///path/to/dump.rdb");
- r.setRdbVisitor(new SkipRdbVisitor(r));
- r.open();
+你也可以从源码安装,运行以下命令:
+```bash
+git clone https://gitee.com/redis-replicator/redis-replicator.git
+cd redis-replicator
+mvn clean install
```
-## 3.6. Scan and PSYNC
-
-By default, redis-replicator uses PSYNC to pretend as slave to receives commands. examples like following
-```java
- Replicator r = new RedisReplicator("redis://127.0.0.1:6379");
- r.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- System.out.println(event);
- }
- });
-
- r.open();
+## 使用示例
-```
+### 备份远程 RDB 快照
-However, under some cloud services, the PSYNC command is prohibited, so we use the Scan command instead of the PSYNC command
```java
-
- Replicator r = new RedisReplicator("redis://127.0.0.1:6379?enableScan=yes&scanStep=256");
- r.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- System.out.println(event);
- }
- });
-
- r.open();
-
-```
-
-## 3.7. Other examples
-
-See [examples](./examples/com/moilioncircle/examples/README.md)
-
-# 4. Advanced topics
-
-## 4.1. Command extension
-
-### 4.1.1. Write a command
-```java
- @CommandSpec(command = "APPEND")
- public static class YourAppendCommand extends AbstractCommand {
- private final String key;
- private final String value;
-
- public YourAppendCommand(String key, String value) {
- this.key = key;
- this.value = value;
- }
-
- public String getKey() {
- return key;
- }
-
- public String getValue() {
- return value;
- }
- }
-```
-
-### 4.1.2. Write a command parser
-```java
-
- public class YourAppendParser implements CommandParser {
-
- @Override
- public YourAppendCommand parse(Object[] command) {
- return new YourAppendCommand(new String((byte[]) command[1], UTF_8), new String((byte[]) command[2], UTF_8));
- }
+public class RdbBackupExample {
+ public static void main(String[] args) throws IOException, URISyntaxException {
+ Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
+ RdbVisitor visitor = new DefaultRdbVisitor(replicator);
+ replicator.setRdbVisitor(visitor);
+ replicator.open();
}
-
+}
```
-
-### 4.1.3. Register this parser
-```java
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.addCommandParser(CommandName.name("APPEND"),new YourAppendParser());
-```
-
-### 4.1.4. Handle command event
-```java
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if(event instanceof YourAppendCommand){
- YourAppendCommand appendCommand = (YourAppendCommand)event;
- // your code goes here
- }
- }
- });
-```
-
-### 4.1.5. Put them together
-See [CommandExtensionExample.java](./examples/com/moilioncircle/examples/extension/CommandExtensionExample.java)
-
-## 4.2. Module extension
-### 4.2.1. Compile redis test modules
-```java
- $cd /path/to/redis-4.0-rc2/src/modules
- $make
-```
-### 4.2.2. Open comment in redis.conf
-
-```java
- loadmodule /path/to/redis-4.0-rc2/src/modules/hellotype.so
-```
-### 4.2.3. Write a module parser
-```java
- public class HelloTypeModuleParser implements ModuleParser {
-
- @Override
- public HelloTypeModule parse(RedisInputStream in, int version) throws IOException {
- DefaultRdbModuleParser parser = new DefaultRdbModuleParser(in);
- int elements = parser.loadUnsigned(version).intValue();
- long[] ary = new long[elements];
- int i = 0;
- while (elements-- > 0) {
- ary[i++] = parser.loadSigned(version);
- }
- return new HelloTypeModule(ary);
- }
- }
+### 备份实时命令
- public class HelloTypeModule implements Module {
- private final long[] value;
-
- public HelloTypeModule(long[] value) {
- this.value = value;
- }
-
- public long[] getValue() {
- return value;
- }
- }
-```
-### 4.2.4. Write a command parser
-```java
-
- public class HelloTypeParser implements CommandParser {
- @Override
- public HelloTypeCommand parse(Object[] command) {
- String key = new String((byte[]) command[1], Constants.UTF_8);
- long value = Long.parseLong(new String((byte[]) command[2], Constants.UTF_8));
- return new HelloTypeCommand(key, value);
- }
- }
-
- @CommandSpec(command = "hellotype.insert")
- public class HelloTypeCommand extends AbstractCommand {
- private final String key;
- private final long value;
-
- public long getValue() {
- return value;
- }
-
- public String getKey() {
- return key;
- }
-
- public HelloTypeCommand(String key, long value) {
- this.key = key;
- this.value = value;
- }
- }
-```
-### 4.2.5. Register this module parser and command parser and handle event
-
-```java
- public static void main(String[] args) throws IOException {
+```java
+public class CommandBackupExample {
+ public static void main(String[] args) throws IOException, URISyntaxException {
Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.addCommandParser(CommandName.name("hellotype.insert"), new HelloTypeParser());
- replicator.addModuleParser("hellotype", 0, new HelloTypeModuleParser());
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof KeyStringValueModule) {
- System.out.println(event);
- }
-
- if (event instanceof HelloTypeCommand) {
- System.out.println(event);
- }
- }
+ replicator.addEventListener((rep, event) -> {
+ System.out.println(event);
});
replicator.open();
}
+}
```
-### 4.2.6. Put them together
-
-See [ModuleExtensionExample.java](./examples/com/moilioncircle/examples/extension/ModuleExtensionExample.java)
-
-## 4.3. Stream
-
-Since Redis 5.0+, Redis add a new data structure `STREAM`. Redis-replicator parse the `STREAM` like the following:
-
-```java
-
- Replicator r = new RedisReplicator("redis://127.0.0.1:6379");
- r.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof KeyStringValueStream) {
- KeyStringValueStream kv = (KeyStringValueStream)event;
- // key
- String key = kv.getKey();
-
- // stream
- Stream stream = kv.getValueAsStream();
- // last stream id
- stream.getLastId();
-
- // entries
- NavigableMap entries = stream.getEntries();
-
- // optional : group
- for (Stream.Group group : stream.getGroups()) {
- // group PEL(pending entries list)
- NavigableMap gpel = group.getPendingEntries();
-
- // consumer
- for (Stream.Consumer consumer : group.getConsumers()) {
- // consumer PEL(pending entries list)
- NavigableMap cpel = consumer.getPendingEntries();
- }
- }
- }
- }
- });
- r.open();
+### 将 RDB 转换为 DUMP 格式
+```java
+public class DumpParserExample {
+ public static void main(String[] args) throws Exception {
+ Replicator replicator = new RedisReplicator(new File("dump.rdb"), FileType.RDB, Configuration.defaultSetting());
+ RdbVisitor visitor = new DumpRdbVisitor(replicator);
+ replicator.setRdbVisitor(visitor);
+ replicator.open();
+ }
+}
```
-## 4.4. Write your own rdb parser
-
-* Write `YourRdbVisitor` extends `RdbVisitor`
-* Register your `RdbVisitor` to `Replicator` using `setRdbVisitor` method.
-
-## 4.5. Redis URI
-
-Before redis-replicator-2.4.0, We construct `RedisReplicator` like the following:
+### RDB 校验
-```java
-Replicator replicator = new RedisReplicator("127.0.0.1", 6379, Configuration.defaultSetting());
-Replicator replicator = new RedisReplicator(new File("/path/to/dump.rdb", FileType.RDB, Configuration.defaultSetting());
-Replicator replicator = new RedisReplicator(new File("/path/to/appendonly.aof", FileType.AOF, Configuration.defaultSetting());
-Replicator replicator = new RedisReplicator(new File("/path/to/appendonly.aof", FileType.MIXED, Configuration.defaultSetting());
+```java
+public class RdbFilterExample {
+ public static void main(String[] args) throws IOException {
+ Replicator replicator = new RedisReplicator(new File("dump.rdb"), FileType.RDB, Configuration.defaultSetting());
+ RdbVisitor visitor = new DefaultRdbVisitor(replicator);
+ replicator.setRdbVisitor(visitor);
+ replicator.open();
+ }
+}
```
-After redis-replicator-2.4.0, We introduced a new concept(Redis URI) which simplify the construction process of `RedisReplicator`.
-
-```java
-Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
-Replicator replicator = new RedisReplicator("redis:///path/to/dump.rdb");
-Replicator replicator = new RedisReplicator("redis:///path/to/appendonly.aof");
+### Scan 与 PSYNC
-// configuration setting example
-Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379?authPassword=foobared&readTimeout=10000&ssl=yes");
-Replicator replicator = new RedisReplicator("redis:///path/to/dump.rdb?rateLimit=1000000");
-Replicator replicator = new RedisReplicator("rediss://user:pass@127.0.0.1:6379?rateLimit=1000000");
-```
-
-# 5. Other topics
-
-## 5.1. Built-in command parser
-
-| **commands** |**commands** | **commands** | **commands** | **commands** | **commands** |
-|--------------| -------------- |--------------------|--------------|---------------|----------------------|
-| **PING** | **APPEND** | **SET** | **SETEX** | **MSET** | **DEL** |
-| **SADD** | **HMSET** | **HSET** | **LSET** | **EXPIRE** | **EXPIREAT** |
-| **GETSET** | **HSETNX** | **MSETNX** | **PSETEX** | **SETNX** | **SETRANGE** |
-| **HDEL** | **UNLINK** | **SREM** | **LPOP** | **LPUSH** | **LPUSHX** |
-| **LRem** | **RPOP** | **RPUSH** | **RPUSHX** | **ZREM** | **ZINTERSTORE** |
-| **INCR** | **DECR** | **INCRBY** | **PERSIST** | **SELECT** | **FLUSHALL** |
-| **FLUSHDB** | **HINCRBY** | **ZINCRBY** | **MOVE** | **SMOVE** | **BRPOPLPUSH** |
-| **PFCOUNT** | **PFMERGE** | **SDIFFSTORE** | **RENAMENX** | **PEXPIREAT** | **SINTERSTORE** |
-| **ZADD** | **BITFIELD** | **SUNIONSTORE** | **RESTORE** | **LINSERT** | **ZREMRANGEBYLEX** |
-| **GEOADD** | **PEXPIRE** | **ZUNIONSTORE** | **EVAL** | **SCRIPT** | **ZREMRANGEBYRANK** |
-| **PUBLISH** | **BITOP** | **SETBIT** | **SWAPDB** | **PFADD** | **ZREMRANGEBYSCORE** |
-| **RENAME** | **MULTI** | **EXEC** | **LTRIM** | **RPOPLPUSH** | **SORT** |
-| **EVALSHA** | **ZPOPMAX** | **ZPOPMIN** | **XACK** | **XADD** | **XCLAIM** |
-| **XDEL** | **XGROUP** | **XTRIM** | **XSETID** | **COPY** | **LMOVE** |
-| **BLMOVE** | **ZDIFFSTORE** | **GEOSEARCHSTORE** | **FUNCTION** | **SPUBLISH** | **HPERSIST** |
-| **HSETEX** | **HPEXPIREAT** | | | | |
-
-## 5.2. EOFException
-
-* Adjust redis server setting like the following. more details please refer to [redis.conf](https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf)
-
-```java
- client-output-buffer-limit slave 0 0 0
-```
-**WARNNING: this setting may run out of memory of redis server in some cases.**
-
-## 5.3. Trace event log
-
-* Set log level to **debug**
-* If you are using log4j2, add logger like the following:
-
-```xml
-
-
-
-```
-
-```java
- Configuration.defaultSetting().setVerbose(true);
- // redis uri
- "redis://127.0.0.1:6379?verbose=yes"
-```
-
-## 5.4. SSL connection
-
-```java
- System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore");
- System.setProperty("javax.net.ssl.keyStorePassword", "password");
- System.setProperty("javax.net.ssl.keyStoreType", "your_type");
-
- System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore");
- System.setProperty("javax.net.ssl.trustStorePassword", "password");
- System.setProperty("javax.net.ssl.trustStoreType", "your_type");
-
- Configuration.defaultSetting().setSsl(true);
-
- // optional setting
- Configuration.defaultSetting().setSslSocketFactory(sslSocketFactory);
- Configuration.defaultSetting().setSslParameters(sslParameters);
- Configuration.defaultSetting().setHostnameVerifier(hostnameVerifier);
- // redis uri
- "redis://127.0.0.1:6379?ssl=yes"
- "rediss://127.0.0.1:6379"
-```
-
-## 5.5. Auth
-
-```java
- Configuration.defaultSetting().setAuthUser("default");
- Configuration.defaultSetting().setAuthPassword("foobared");
- // redis uri
- "redis://127.0.0.1:6379?authPassword=foobared&authUser=default"
- "redis://default:foobared@127.0.0.1:6379"
-```
-
-## 5.6. Avoid full sync
-
-* Adjust redis server setting like the following
-
-```java
- repl-backlog-size
- repl-backlog-ttl
- repl-ping-slave-periods
-```
-`repl-ping-slave-period` **MUST** less than `Configuration.getReadTimeout()`, default `Configuration.getReadTimeout()` is 60 seconds
-
-## 5.7. Lifecycle event
-
-```java
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- final long start = System.currentTimeMillis();
- final AtomicInteger acc = new AtomicInteger(0);
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if(event instanceof PreRdbSyncEvent) {
- System.out.println("pre rdb sync");
- } else if(event instanceof PostRdbSyncEvent) {
- long end = System.currentTimeMillis();
- System.out.println("time elapsed:" + (end - start));
- System.out.println("rdb event count:" + acc.get());
- } else {
- acc.incrementAndGet();
- }
- }
+```java
+public class ScanExample {
+ public void scan() throws Exception {
+ Replicator replicator = new RedisScanReplicator("127.0.0.1", 6379, Configuration.defaultSetting());
+ replicator.addEventListener((r, event) -> {
+ System.out.println(event);
});
replicator.open();
-```
-
-## 5.8. Handle huge key value pair
-
-According to [4.3. Write your own rdb parser](#43-write-your-own-rdb-parser), This tool built in an [Iterable Rdb Parser](./src/main/java/com/moilioncircle/redis/replicator/rdb/iterable/ValueIterableRdbVisitor.java) so that handle huge key value pair.
-More details please refer to:
-[1] [HugeKVFileExample.java](./examples/com/moilioncircle/examples/huge/HugeKVFileExample.java)
-[2] [HugeKVSocketExample.java](./examples/com/moilioncircle/examples/huge/HugeKVSocketExample.java)
-
-## 5.9. Redis6 support
-
-### 5.9.1. SSL support
-
+ }
+}
```
- $cd /path/to/redis
- $./utils/gen-test-certs.sh
- $cd tests/tls
- $openssl pkcs12 -export -CAfile ca.crt -in redis.crt -inkey redis.key -out redis.p12
- $cd /path/to/redis
- $./src/redis-server --tls-port 6379 --port 0 --tls-cert-file ./tests/tls/redis.crt \
- --tls-key-file ./tests/tls/redis.key --tls-ca-cert-file ./tests/tls/ca.crt \
- --tls-replication yes --bind 0.0.0.0 --protected-mode no
-
- System.setProperty("javax.net.ssl.keyStore", "/path/to/redis/tests/tls/redis.p12");
- System.setProperty("javax.net.ssl.keyStorePassword", "password");
- System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
- System.setProperty("javax.net.ssl.trustStore", "/path/to/redis/tests/tls/redis.p12");
- System.setProperty("javax.net.ssl.trustStorePassword", "password");
- System.setProperty("javax.net.ssl.trustStoreType", "pkcs12");
+### Redis URI 支持
- Replicator replicator = new RedisReplicator("rediss://127.0.0.1:6379");
+Redis-replicator 支持使用 URI 来连接 Redis 实例,包括 `redis://`, `rediss://` (SSL), `file://` 以及 `redis-sentinel://`。
+```java
+Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379", Configuration.defaultSetting());
```
-
-If you don't want to use `System.setProperty` you can programing as following
-
-```java
-
- RedisSslContextFactory factory = new RedisSslContextFactory();
- factory.setKeyStorePath("/path/to/redis/tests/tls/redis.p12");
- factory.setKeyStoreType("pkcs12");
- factory.setKeyStorePassword("password");
-
- factory.setTrustStorePath("/path/to/redis/tests/tls/redis.p12");
- factory.setTrustStoreType("pkcs12");
- factory.setTrustStorePassword("password");
-
- SslConfiguration ssl = SslConfiguration.defaultSetting().setSslContextFactory(factory);
- Replicator replicator = new RedisReplicator("rediss://127.0.0.1:6379", ssl);
-
-```
-### 5.9.2. ACL support
+## 高级用法
-```java
+### 自定义命令扩展
- Replicator replicator = new RedisReplicator("redis://user:pass@127.0.0.1:6379");
+你可以通过实现 `CommandParser` 接口来解析未内置支持的命令。
+```java
+public static class YourAppendParser implements CommandParser {
+ @Override
+ public YourAppendCommand parse(Object[] command) {
+ // 解析逻辑
+ return new YourAppendCommand(key, value);
+ }
+}
```
-## 5.10. Redis7 support
-
-### 5.10.1. Function
+### 模块扩展
-Since redis 7.0 add `function` support. and `function` structure stored in rdb file. we can use following method to parse `function`.
+支持解析 Redis 模块数据,如 RedisJSON、RedisGraph � - 通过实现 `ModuleParser` 接口。
-```java
-
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof Function) {
- Function function = (Function) event;
- function.getCode();
-
- // your code goes here
- }
- }
- });
- replicator.open();
+```java
+public static class HelloTypeModuleParser implements ModuleParser {
+ @Override
+ public HelloTypeModule parse(RedisInputStream in, int version) throws IOException {
+ // 解析模块逻辑
+ return new HelloTypeModule(value);
+ }
+}
```
-you can also parse `function` to `serialized` data so that use `FUNCTION RESTORE` to restore `serialized` data to target redis
-
-```java
-
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.setRdbVisitor(new DumpRdbVisitor(replicator));
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof DumpFunction) {
- DumpFunction function = (DumpFunction) event;
- byte[] serialized = function.getSerialized();
- // your code goes here
- // you can use FUNCTION RESTORE to restore above serialized data to target redis
- }
- }
- });
- replicator.open();
-```
+### 流式处理 (Redis Stream)
-## 5.11. Redis7.4 support
-
-### 5.11.1. TTL Hash
-
-Since redis 7.4 add `ttl hash` support. and `ttl hash` structure stored in rdb file. we can use following method to parse `ttl hash`.
-
-```java
-
- Replicator replicator = new RedisReplicator("redis://127.0.0.1:6379");
- replicator.addEventListener(new EventListener() {
- @Override
- public void onEvent(Replicator replicator, Event event) {
- if (event instanceof KeyStringValueTTLHash) {
- KeyStringValueTTLHash skv = (KeyStringValueTTLHash) event;
- // key
- byte[] key = skv.getKey();
-
- // ttl hash
- Map ttlHash = skv.getValue();
- for (Map.Entry entry : ttlHash.entrySet()) {
- System.out.println("field:" + Strings.toString(entry.getKey()));
- System.out.println("value:" + Strings.toString(entry.getValue().getValue()));
- System.out.println("field ttl:" + entry.getValue().getExpires());
- }
+```java
+public class StreamExample {
+ public static void main(String[] args) throws Exception {
+ Replicator replicator = new RedisSocketReplicator("127.0.0.1", 6379, Configuration.defaultSetting());
+ replicator.addEventListener((r, event) -> {
+ if (event instanceof KeyStringValueStream) {
+ KeyStringValueStream kv = (KeyStringValueStream) event;
+ System.out.println("Stream Key: " + kv.getKey());
}
- }
- });
- replicator.open();
+ });
+ replicator.open();
+ }
+}
```
-# 6. Contributors
-* [Leon Chen](https://github.com/leonchen83)
-* [Adrian Yao](https://github.com/adrianyao89)
-* [Trydofor](https://github.com/trydofor)
-* [Argun](https://github.com/Argun)
-* [Sean Pan](https://github.com/XinYang-Pan)
-* [René Kerner](https://github.com/rk3rn3r)
-* [Maplestoria](https://github.com/maplestoria)
-* Special thanks to [Kevin Zheng](https://github.com/KevinZheng001)
-
-# 7 Consulting
-
-Commercial support for `redis-replicator` is available. The following services are currently available:
-* Onsite consulting. $10,000 per day
-* Onsite training. $10,000 per day
-
-You may also contact Baoyi Chen directly, mail to [chen.bao.yi@gmail.com](mailto:chen.bao.yi@gmail.com).
-
-# 8. References
- * [rdb.c](https://github.com/antirez/redis/blob/unstable/src/rdb.c)
- * [Redis RDB File Format](https://github.com/leonchen83/redis-replicator/wiki/RDB-dump-data-format)
- * [Redis Protocol specification](http://redis.io/topics/protocol)
- * [Redis Replication](http://redis.io/topics/replication)
- * [Redis-replicator Design and Implementation](https://github.com/leonchen83/mycode/blob/master/redis/redis-share/Redis-replicator%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0.md)
+## 支持的 Redis 版本
-# 9. Supported by
+- **Redis 6**:支持 SSL 和 ACL。
+- **Redis 7**:支持 Function、JSON 数据类型等。
+- **Redis 7.4**:支持 TTL Hash。
-## 9.1. 宁文君
+## 社区与支持
-27 January 2023, A sad day that I lost my mother 宁文君, She was encouraging and supporting me in developing this tool. Every time a company uses this tool, she got excited like a child and encouraged me to keep going.
-Without her I couldn't have maintained this tool for so many years. Even I didn't achieve much but she is still proud of me, R.I.P and hope God bless her.
+- **贡献者**:本项目由社区驱动,感谢所有贡献者。
+- **咨询**:如需商业支持或定制开发,请联系作者。
-## 9.2. YourKit
+## 相关引用
-
-YourKit is kindly supporting this open source project with its full-featured Java Profiler.
-YourKit, LLC is the creator of innovative and intelligent tools for profiling
-Java and .NET applications. Take a look at YourKit's leading software products:
-YourKit Java Profiler and
-YourKit .NET Profiler.
+- [Redis 官方文档](https://redis.io/documentation)
+- [Redis RDB 格式解析](https://rdb.fnordian.com/)
+- [Redis 复制机制](https://redis.io/topics/replication)
-## 9.3. IntelliJ IDEA
+## 致谢
-[IntelliJ IDEA](https://www.jetbrains.com/?from=redis-replicator) is a Java integrated development environment (IDE) for developing computer software.
-It is developed by JetBrains (formerly known as IntelliJ), and is available as an Apache 2 Licensed community edition,
-and in a proprietary commercial edition. Both can be used for commercial development.
+- 宁文君
+- YourKit
+- IntelliJ IDEA
+- Redisson
-## 9.4. Redisson
+## 开源许可
-[Redisson](https://github.com/redisson/redisson) is Redis based In-Memory Data Grid for Java offers distributed objects and services (`BitSet`, `Set`, `Multimap`, `SortedSet`, `Map`, `List`, `Queue`, `BlockingQueue`, `Deque`, `BlockingDeque`, `Semaphore`, `Lock`, `AtomicLong`, `CountDownLatch`, `Publish / Subscribe`, `Bloom filter`, `Remote service`, `Spring cache`, `Executor service`, `Live Object service`, `Scheduler service`) backed by Redis server. Redisson provides more convenient and easiest way to work with Redis. Redisson objects provides a separation of concern, which allows you to keep focus on the data modeling and application logic.
+本项目采用 [ANTI-996 License](./ANT-996-LICENSE)。
\ No newline at end of file