-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
1,419 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 0 additions & 7 deletions
7
...oxy-core/src/main/java/com/netease/nim/camellia/redis/proxy/embedded/storage/wal/Wal.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
...n/java/com/netease/nim/camellia/redis/proxy/upstream/embedded/storage/EmbeddedClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.netease.nim.camellia.redis.proxy.upstream.embedded.storage; | ||
|
||
import com.netease.nim.camellia.core.model.Resource; | ||
import com.netease.nim.camellia.redis.proxy.command.Command; | ||
import com.netease.nim.camellia.redis.proxy.reply.ErrorReply; | ||
import com.netease.nim.camellia.redis.proxy.reply.Reply; | ||
import com.netease.nim.camellia.redis.proxy.upstream.IUpstreamClient; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.CompletableFuture; | ||
|
||
/** | ||
* Created by caojiajun on 2025/1/3 | ||
*/ | ||
public class EmbeddedClient implements IUpstreamClient { | ||
|
||
@Override | ||
public void sendCommand(int db, List<Command> commands, List<CompletableFuture<Reply>> futureList) { | ||
if (db > 0) { | ||
for (CompletableFuture<Reply> future : futureList) { | ||
future.complete(ErrorReply.DB_INDEX_OUT_OF_RANGE); | ||
} | ||
return; | ||
} | ||
} | ||
|
||
@Override | ||
public void start() { | ||
|
||
} | ||
|
||
@Override | ||
public void preheat() { | ||
} | ||
|
||
@Override | ||
public boolean isValid() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public void shutdown() { | ||
} | ||
|
||
@Override | ||
public Resource getResource() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public void renew() { | ||
|
||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
...n/java/com/netease/nim/camellia/redis/proxy/upstream/embedded/storage/codec/KeyCodec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.codec; | ||
|
||
import com.netease.nim.camellia.codec.Pack; | ||
import com.netease.nim.camellia.codec.Unpack; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.compress.CompressType; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.compress.CompressUtils; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.compress.ICompressor; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.constants.EmbeddedStorageConstants; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.key.KeyInfo; | ||
import com.netease.nim.camellia.redis.proxy.upstream.kv.utils.BytesUtils; | ||
import com.netease.nim.camellia.redis.proxy.util.RedisClusterCRC16Utils; | ||
import com.netease.nim.camellia.tools.utils.BytesKey; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* Created by caojiajun on 2025/1/3 | ||
*/ | ||
public class KeyCodec { | ||
|
||
public static Map<BytesKey, KeyInfo> decodeSlot(byte[] all) { | ||
ByteBuffer buffer = ByteBuffer.wrap(all); | ||
int bucketSize = all.length / EmbeddedStorageConstants._4k; | ||
Map<BytesKey, KeyInfo> result = new HashMap<>(); | ||
for (int i=0; i<bucketSize; i++) { | ||
byte[] bytes = new byte[EmbeddedStorageConstants._4k]; | ||
buffer.get(bytes); | ||
Map<BytesKey, KeyInfo> map = KeyCodec.decodeBucket(bytes); | ||
result.putAll(map); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* 解码bucket | ||
* @param bytes 固定为4k输入 | ||
* @return 解码结果 | ||
*/ | ||
public static Map<BytesKey, KeyInfo> decodeBucket(byte[] bytes) { | ||
int crc1 = BytesUtils.toInt(bytes, 0);//0,1,2,3 | ||
int crc2 = RedisClusterCRC16Utils.getCRC16(bytes, 5, bytes.length); | ||
if (crc1 != crc2) { | ||
return new HashMap<>(); | ||
} | ||
int decompressLen = BytesUtils.toShort(bytes, 4);//4,5 | ||
byte compressType = bytes[6];//6 | ||
ICompressor compressor = CompressUtils.get(CompressType.getByValue(compressType)); | ||
byte[] decompressData = compressor.decompress(bytes, 7, bytes.length - 7, decompressLen); | ||
Unpack unpack = new Unpack(decompressData); | ||
int size = unpack.popVarUint(); | ||
Map<BytesKey, KeyInfo> map = new HashMap<>(); | ||
for (int i=0; i<size; i++) { | ||
KeyInfo key = new KeyInfo(); | ||
unpack.popMarshallable(key); | ||
map.put(new BytesKey(key.getKey()), key); | ||
} | ||
return map; | ||
} | ||
|
||
/** | ||
* 编码bucket,可能会压缩 | ||
* 如果编码后超过了4k,则返回null,上层自行拆分;如果不足4k,则补0 | ||
* @param keys keys | ||
* @return 编码结果,固定为4k | ||
*/ | ||
public static byte[] encodeBucket(Map<BytesKey, KeyInfo> keys) { | ||
Pack pack = new Pack(); | ||
pack.putVarUint(keys.size()); | ||
for (Map.Entry<BytesKey, KeyInfo> entry : keys.entrySet()) { | ||
pack.putMarshallable(entry.getValue()); | ||
} | ||
pack.getBuffer().capacity(pack.getBuffer().readableBytes()); | ||
byte[] array = pack.getBuffer().array(); | ||
short decompressLen = (short) array.length; | ||
CompressType compressType = CompressType.zstd; | ||
ICompressor compressor = CompressUtils.get(compressType); | ||
byte[] compressed = compressor.compress(array, 0, array.length); | ||
if (compressed.length > array.length) { | ||
compressType = CompressType.none; | ||
compressed = array; | ||
} | ||
if (compressed.length + 5 > EmbeddedStorageConstants._4k) { | ||
return null; | ||
} | ||
int crc = RedisClusterCRC16Utils.getCRC16(compressed, 0, compressed.length); | ||
ByteBuffer buffer = ByteBuffer.allocate(EmbeddedStorageConstants._4k); | ||
buffer.putInt(crc); | ||
buffer.putShort(decompressLen); | ||
buffer.put(compressType.getType()); | ||
buffer.put(compressed); | ||
return buffer.array(); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
.../nim/camellia/redis/proxy/upstream/embedded/storage/command/CommandOnEmbeddedStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.command; | ||
|
||
import com.netease.nim.camellia.redis.proxy.command.Command; | ||
import com.netease.nim.camellia.redis.proxy.enums.RedisCommand; | ||
import com.netease.nim.camellia.redis.proxy.reply.Reply; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.key.KeyReadWrite; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.value.string.StringReadWrite; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.wal.WalGroup; | ||
|
||
/** | ||
* Created by caojiajun on 2025/1/3 | ||
*/ | ||
public abstract class CommandOnEmbeddedStorage { | ||
|
||
protected WalGroup walGroup; | ||
|
||
protected KeyReadWrite keyReadWrite; | ||
protected StringReadWrite stringReadWrite; | ||
|
||
/** | ||
* redis command of commander | ||
* @return redis-command | ||
*/ | ||
public abstract RedisCommand redisCommand(); | ||
|
||
/** | ||
* check param | ||
* @param command command | ||
* @return success or fail | ||
*/ | ||
protected abstract boolean parse(Command command); | ||
|
||
/** | ||
* execute command | ||
* @param slot slot | ||
* @param command command | ||
* @return reply | ||
*/ | ||
protected abstract Reply execute(short slot, Command command) throws Exception; | ||
} |
42 changes: 42 additions & 0 deletions
42
.../nim/camellia/redis/proxy/upstream/embedded/storage/command/EmbeddedStorageExecutors.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.command; | ||
|
||
|
||
import com.netease.nim.camellia.redis.proxy.conf.ProxyDynamicConf; | ||
import com.netease.nim.camellia.redis.proxy.util.MpscSlotHashExecutor; | ||
import com.netease.nim.camellia.tools.utils.SysUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Created by caojiajun on 2025/1/3 | ||
*/ | ||
public class EmbeddedStorageExecutors { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(EmbeddedStorageExecutors.class); | ||
|
||
private static volatile EmbeddedStorageExecutors INSTANCE; | ||
|
||
private final MpscSlotHashExecutor commandExecutor; | ||
|
||
private EmbeddedStorageExecutors() { | ||
int threads = ProxyDynamicConf.getInt("embedded.storage.command.executor.threads", SysUtils.getCpuNum() * 4); | ||
int queueSize = ProxyDynamicConf.getInt("embedded.storage.command.executor.queue.size", 1024*128); | ||
commandExecutor = new MpscSlotHashExecutor("embedded-storage-command-executor", threads, queueSize, new MpscSlotHashExecutor.AbortPolicy()); | ||
logger.info("EmbeddedStorageExecutors init success, threads = {}, queueSize = {}", threads, queueSize); | ||
} | ||
|
||
public static EmbeddedStorageExecutors getInstance() { | ||
if (INSTANCE == null) { | ||
synchronized (EmbeddedStorageExecutors.class) { | ||
if (INSTANCE == null) { | ||
INSTANCE = new EmbeddedStorageExecutors(); | ||
} | ||
} | ||
} | ||
return INSTANCE; | ||
} | ||
|
||
public MpscSlotHashExecutor getCommandExecutor() { | ||
return commandExecutor; | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...va/com/netease/nim/camellia/redis/proxy/upstream/embedded/storage/command/string/Get.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.command.string; | ||
|
||
import com.netease.nim.camellia.redis.proxy.command.Command; | ||
import com.netease.nim.camellia.redis.proxy.enums.RedisCommand; | ||
import com.netease.nim.camellia.redis.proxy.reply.BulkReply; | ||
import com.netease.nim.camellia.redis.proxy.reply.ErrorReply; | ||
import com.netease.nim.camellia.redis.proxy.reply.Reply; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.command.CommandOnEmbeddedStorage; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.enums.DataType; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.key.KeyInfo; | ||
import com.netease.nim.camellia.redis.proxy.upstream.embedded.storage.value.ValueLocation; | ||
import com.netease.nim.camellia.tools.utils.BytesKey; | ||
|
||
/** | ||
* GET key | ||
* <p> | ||
* Created by caojiajun on 2025/1/3 | ||
*/ | ||
public class Get extends CommandOnEmbeddedStorage { | ||
|
||
@Override | ||
public RedisCommand redisCommand() { | ||
return RedisCommand.GET; | ||
} | ||
|
||
@Override | ||
protected boolean parse(Command command) { | ||
byte[][] objects = command.getObjects(); | ||
return objects.length == 2; | ||
} | ||
|
||
@Override | ||
protected Reply execute(short slot, Command command) throws Exception { | ||
byte[][] objects = command.getObjects(); | ||
BytesKey key = new BytesKey(objects[1]); | ||
KeyInfo keyInfo = keyReadWrite.get(slot, key); | ||
return execute0(keyInfo); | ||
} | ||
|
||
private Reply execute0(KeyInfo keyInfo) { | ||
if (keyInfo == null) { | ||
return BulkReply.NIL_REPLY; | ||
} | ||
if (keyInfo.getDataType() != DataType.string) { | ||
return ErrorReply.WRONG_TYPE; | ||
} | ||
if (keyInfo.containsExtra()) { | ||
return new BulkReply(keyInfo.getExtra()); | ||
} | ||
ValueLocation valueLocation = keyInfo.getValueLocation(); | ||
byte[] bytes = stringReadWrite.get(valueLocation); | ||
if (bytes == null) { | ||
return BulkReply.NIL_REPLY; | ||
} | ||
return new BulkReply(bytes); | ||
} | ||
} |
Oops, something went wrong.