Valkey 9.0 深度实战:当开源社区重塑内存数据库——从异步 IO 到原子槽位迁移的生产级完全指南(2026)
2024 年 Redis 换证风暴后,Valkey 从 Redis 7.2.4 分叉而出。两年后的今天,Valkey 已经发展到 9.0 大版本——25.4k GitHub Stars、2000 节点集群、单节点 120 万 QPS、集群 10 亿 RPS。它不再是一个「Redis 替代品」,而是用自己的架构重新定义了内存数据库这个品类。
一、背景:一场由许可证引发的开源革命
1.1 Redis 换证事件始末
2024 年 3 月,Redis Labs(后更名为 Redis Inc.)宣布将 Redis 核心代码的许可证从 BSD 变更为 RSALv2(Redis Source Available License v2)和 SSPL v1 双许可证模式。这意味着:
- 云厂商(AWS、Google Cloud、Oracle 等)不能再将 Redis 作为托管服务提供给客户
- 任何修改后的版本也不能作为云服务提供
- 许可证从「真正的开源」变成了「源代码可用」
这一决定在开源社区引发了巨大震动。Redis 作为全球使用最广泛的内存数据库,支撑着数百万应用的生产环境。许可证变更直接威胁到了整个云原生生态的自由度。
1.2 Valkey 的诞生
仅仅 8 天之后,Linux 基金会联合 AWS、Google Cloud、Oracle、Snap 等多家科技公司宣布支持 Valkey 项目。Valkey 基于 Redis 7.2.4(BSD 许可证下的最后一个稳定版本)分叉,在 Linux 基金会托管下继续以 BSD 3-Clause 许可证开源。
2024 年 4 月 16 日,Valkey 在北美开源峰会(Open Source Summit North America 2024)上正式发布首个版本 7.2.5 RC。从分叉到发布,仅用了 3 周。
1.3 版本演进时间线
| 版本 | 发布时间 | 核心突破 |
|---|---|---|
| 7.2.5 RC | 2024 年 4 月 | 分叉首个版本,兼容 Redis 7.2.4 |
| 8.0 GA | 2024 年 9 月 | 异步 IO 线程、数据预取、MAA,单节点 100-120 万 QPS |
| 9.0 GA | 2025 年 12 月 | 原子槽位迁移、多数据库集群、哈希字段过期,集群 10 亿 RPS |
1.4 最新动态:Redis 重新开源
值得注意的是,Redis 项目创始人 antirez 在 2025 年加入 Redis Inc. 后,Redis 宣布从 Redis 8 开始重新开源。但 Valkey 已经在这两年间建立了自己的技术路线和社区生态,两者将长期共存竞争。
二、Valkey 8.0 架构革命:异步 IO 线程
2.1 Redis 6.0 多线程 IO 的局限
在理解 Valkey 的突破之前,先回顾 Redis 6.0 的多线程 IO:
Redis 6.0 引入了多线程 IO 来处理网络数据的读写和协议解析,但存在明显问题:
- 同步等待模型:主线程将所有可读客户端加入队列后,需要等待所有 IO 线程完成读写操作
- IO 线程利用率低:主线程处理命令时,IO 线程全部空闲;主线程执行 IO 任务时,又受最慢线程拖累
- 任务范围窄:IO 线程仅执行读取解析和写入操作,命令查找等仍然在主线程
这使得 Redis 6.0 将单节点 QPS 从 10 万提升到约 20 万,但天花板明显。
2.2 Valkey 8.0 的异步 IO 架构
Valkey 8.0 彻底重构了 IO 模型,核心变化是从同步等待变为异步任务队列:
Redis 6.0 流程:
主线程收集事件 → 暂停 → 唤醒所有IO线程 → 等待全部完成 → 处理命令
(IO线程在主线程收集/等待期间全部空闲)
Valkey 8.0 流程:
主线程监测事件 → 立即派发到任务队列 → IO线程异步执行
(主线程和IO线程并行工作,无阻塞等待)
环形缓冲区任务队列
Valkey 在启动时为每个 IO 线程创建一个静态、无锁、固定大小(2048)的环形缓冲区作为任务队列。主线程通过环形缓冲区向 IO 线程发送任务,IO 线程异步从中获取任务执行。
为什么用环形缓冲区?
- 无锁设计避免了锁竞争的开销
- 固定大小保证内存预分配,无动态分配延迟
- 单向通道(主线程 → IO 线程)简化了并发控制
读数据流程
// Valkey 8.0 读数据流程(简化)
// 1. 主线程检测到可读事件
while ((nread = read(fd, buf, sizeof(buf))) > 0) {
// 2. 如果开启IO线程,将读任务派发到任务队列
if (io_threads_active) {
iothread_post_read(client); // 无锁入队
} else {
// 未开启时主线程直接处理
processInputBuffer(client);
}
}
// 3. IO线程异步执行读数据
// IO线程中:
while (task = ring_buffer_dequeue(my_queue)) {
readQueryFromClient(task->client); // 读取数据
parseCommand(task->client); // 解析命令
lookupCommand(task->client); // 命令查找(Valkey 8.0新增)
}
// 4. 主线程在进入事件监听睡眠前,检查IO线程完成情况
// 通过原子标志 read_state 判断
写数据流程
// 主线程执行命令后
processCommand(client);
// 将响应写入响应缓存
addReply(client, reply);
// 遍历等待写队列
listIter li;
listRewind(server.clients_pending_write, &li);
while ((ln = listNext(&li))) {
client *c = listNodeValue(ln);
// 选择IO线程,通过任务队列派发写任务
iothread_post_write(c);
}
2.3 IO 线程动态调整
Valkey 不是简单地固定 IO 线程数量,而是根据实时负载动态调整活跃线程数:
// 伪代码:动态调整活跃IO线程数
int target_threads = min(
pending_events / events_per_thread, // 按事件数计算
max_io_threads // 最大不超过配置值(默认15)
);
if (active_threads < target_threads) {
// 唤醒更多线程(释放锁)
unlock_thread(thread_id);
} else if (active_threads > target_threads) {
// 暂停多余线程(加锁使其不再轮询)
lock_thread(thread_id);
}
关键设计:
- 减少 IO 线程不直接销毁线程,而是通过加锁使其暂停空轮询
- 增加 IO 线程只需释放锁
- 线程亲和性:同一客户端的 IO 请求尽量由同一个 IO 线程处理,提高缓存局部性
2.4 更多任务卸载到 IO 线程
Valkey 8.0 将远不止读写数据的更多任务卸载到了 IO 线程:
| 任务 | Redis 6.0 | Valkey 8.0 |
|---|---|---|
| 网络数据读写 | IO 线程 | IO 线程 |
| 命令协议解析 | IO 线程 | IO 线程 |
| 命令字典查找 | 主线程 | IO 线程 |
| epoll_wait 系统调用 | 主线程 | IO 线程 |
| 对象内存释放 | 主线程 | IO 线程 |
事件轮询卸载:epoll_wait 是开销很大的系统调用,Valkey 将其分配给 IO 线程执行,主线程直接检查 IO 线程的轮询结果。
对象释放卸载:命令解析过程中分配的参数对象,释放时由分配它的同一个 IO 线程处理(通过客户端 ID 标识),提高内存局部性。
三、数据预取与内存访问分摊
3.1 为什么需要这些技术?
引入异步 IO 线程后,Valkey 单节点 QPS 达到了约 80 万。瓶颈从 IO 转移到了内存访问:
Valkey 使用链式哈希表存储键值对。查找一个 key 的步骤:
- 计算 hash 值,定位 bucket
- 遍历链表找到 key
- 访问 value 对象
- 如果是 RAW 编码,还需再次访问内存获取真实数据
每一步都是串行的内存访问,在高速缓存(L1/L2)未命中时,每次访问主存需要约 100ns。现代 CPU 主频 3GHz+,100ns 意味着白白浪费约 300 个时钟周期。
3.2 数据预取(Prefetch)
Valkey 8.0 利用 GCC 的 __builtin_prefetch() 内置函数,在执行命令前批量预取所有即将操作的数据到 CPU 缓存:
// Valkey 8.0 批量预取(简化示意)
void prefetchCommands(client **clients, int count) {
for (int i = 0; i < count; i++) {
// 预取命令参数
for (int j = 0; j < clients[i]->argc; j++) {
__builtin_prefetch(clients[i]->argv[j]->ptr);
}
// 预取命令对应的字典条目
dictEntry *entry = dictFind(server.db[0]->dict, clients[i]->argv[1]);
if (entry) {
__builtin_prefetch(dictGetKey(entry));
__builtin_prefetch(dictGetVal(entry));
}
}
}
原理:__builtin_prefetch() 告诉 CPU 预取指定地址的数据到缓存。当后续代码真正访问该地址时,数据已经在缓存中了,避免了等待内存读取。
3.3 内存访问分摊(MAA)
但单纯的预取不够。对于多个 key 的批量操作,如果顺序预取每个 key 的所有步骤,每个 key 仍然需要串行等待。
MAA 的核心思想:交错执行多个 key 的预取步骤。
传统顺序预取(3个key,每个4步):
Key1: step1 → step2 → step3 → step4 → Key2: step1 → step2 → ...
(每个key的步骤之间有内存等待间隙)
MAA 交错预取:
Key1:step1 → Key2:step1 → Key3:step1 → Key1:step2 → Key2:step2 → ...
(在等待Key1:step1数据返回期间,已经开始Key2:step1)
// MAA 交错预取伪代码
void maa_batch_prefetch(client **clients, int count) {
// 步骤1:预取所有key的bucket
for (int i = 0; i < count; i++) {
unsigned int hash = dictHashKey(clients[i]->argv[1]->ptr);
__builtin_prefetch(dictGetBucket(table, hash));
}
// 步骤2:预取所有key的entry(此时bucket已在缓存中)
for (int i = 0; i < count; i++) {
dictEntry *entry = dictFindEntry(table, clients[i]->argv[1]->ptr);
if (entry) __builtin_prefetch(entry);
}
// 步骤3:预取所有key的value(此时entry已在缓存中)
for (int i = 0; i < count; i++) {
dictEntry *entry = dictFindEntry(table, clients[i]->argv[1]->ptr);
if (entry) __builtin_prefetch(dictGetVal(entry));
}
// 步骤4:预取所有RAW值的真实数据(此时value已在缓存中)
for (int i = 0; i < count; i++) {
robj *val = dictGetValue(table, clients[i]->argv[1]->ptr);
if (val && val->encoding == OBJ_ENCODING_RAW) {
__builtin_prefetch(val->ptr);
}
}
}
3.4 性能提升效果
| 优化阶段 | 单节点 QPS | 提升幅度 |
|---|---|---|
| Redis 6.0 多线程 IO | ~20 万 | 基准 |
| Valkey 8.0 异步 IO | ~80 万 | 4x |
| Valkey 8.0 + Prefetch + MAA | ~100-120 万 | 5-6x |
Valkey 单节点性能已经比肩甚至超越了低版本 Redis 的中等规模集群。
四、Valkey 9.0:集群规模的量级跃迁
4.1 原子槽位迁移
Valkey 集群使用哈希槽(Hash Slot)来分布数据,共 16384 个槽。传统 Redis 集群中,迁移槽位时需要分多步操作(标记、迁移、确认),中途如果主节点故障,可能导致数据不一致。
Valkey 9.0 引入了原子槽位迁移(Atomic Slot Migration):
# Valkey 9.0 原子槽位迁移命令
CLUSTER MIGRATE-SLOT <slot> <target-node-id>
# 一次性完成,不需要 CLUSTER SETSLOT 和 MIGRATE 的多步操作
原子性保证:
- 槽位要么在源节点,要么在目标节点,不存在中间状态
- 迁移过程中客户端请求自动路由
- 主节点故障不影响迁移一致性
实现原理:
- 源节点将槽位状态标记为 MIGRATING
- 通过内部通道将所有 key 同步到目标节点
- 同步完成后,原子性地更新集群元数据
- 通知所有节点槽位归属已变更
4.2 集群模式多数据库支持
传统 Redis 集群中,只能使用数据库 0(SELECT 0),这严重限制了集群的使用场景。
Valkey 9.0 打破了这个限制,支持集群模式下的多数据库:
# Valkey 9.0 集群中可以使用多个数据库
SELECT 1
SET user:1001 "Alice"
SELECT 2
SET cache:home "cached_data"
不同应用可以共享同一个 Valkey 集群实例,通过数据库编号隔离数据,解决了资源配置的挑战。
4.3 哈希字段过期
长期以来,Redis 的哈希类型只支持整个 key 的过期,不支持单个字段的过期。Valkey 9.0 引入了哈希字段级过期:
# Valkey 9.0 哈希字段过期
HSET session:user123 token "abc123" FIELDEX 3600
# 字段 token 将在 3600 秒后过期
# 检查字段是否过期
HEXPIRE session:user123 300 FIELDS 1 token
# 给 token 字段设置 300 秒过期
这对 session 管理、缓存场景非常实用,不再需要额外的过期管理逻辑。
4.4 集群性能:10 亿 RPS
Valkey 9.0 集群扩展到 2000 个节点,集群吞吐量达到每秒超 10 亿次请求。这得益于:
- 异步 IO 线程的单节点性能基础
- 原子槽位迁移降低扩缩容开销
- 智能核心利用和数据预取的持续优化
五、生产级实战:从 Redis 迁移到 Valkey
5.1 兼容性评估
Valkey 基于 Redis 7.2.4 分叉,协议层面完全兼容 Redis OSS 7.2.4 的 RESP 协议。绝大多数应用无需修改代码即可迁移。
兼容性清单:
| 维度 | 兼容性 | 说明 |
|---|---|---|
| RESP 协议 | 100% | 完全兼容 |
| 数据类型 | 100% | String/List/Hash/Set/ZSet/Stream 等全部支持 |
| Lua 脚本 | 95%+ | 绝大多数脚本兼容,极端边界情况需测试 |
| 模块 | 部分 | Redis 模块不兼容,需要找替代方案 |
| Sentinel | 替代 | Valkey 有自己的高可用方案 |
| Cluster | 增强 | 兼容 Redis 集群协议,并增加了新特性 |
5.2 部署 Valkey
Docker 部署(快速体验)
# 拉取 Valkey 镜像
docker pull valkey/valkey:9.0
# 启动单节点
docker run -d \
--name valkey \
-p 6379:6379 \
valkey/valkey:9.0 \
valkey-server --appendonly yes
# 启动时启用异步IO线程
docker run -d \
--name valkey \
-p 6379:6379 \
valkey/valkey:9.0 \
valkey-server \
--io-threads 4 \
--appendonly yes
源码编译部署
# 克隆代码
git clone https://github.com/valkey-io/valkey.git
cd valkey
# 切换到 9.0 分支
git checkout 9.0.0
# 编译(需要 GCC 9+)
make -j$(nproc)
# 运行
./src/valkey-server --io-threads 4
集群部署
# 创建 6 节点配置文件(3主3从)
for port in 7000 7001 7002 7003 7004 7005; do
mkdir -p cluster-${port}
cat > cluster-${port}/valkey.conf << EOF
port ${port}
cluster-enabled yes
cluster-config-file nodes-${port}.conf
cluster-node-timeout 5000
appendonly yes
io-threads 4
EOF
done
# 启动所有节点
for port in 7000 7001 7002 7003 7004 7005; do
./src/valkey-server cluster-${port}/valkey.conf --daemonize yes --pidfile cluster-${port}/valkey.pid
done
# 创建集群
./src/valkey-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
5.3 性能压测
# 安装 valkey-benchmark(随 valkey 一起编译)
# 单线程基准测试
./src/valkey-benchmark -h 127.0.0.1 -p 6379 -t set,get -n 1000000 -c 50
# 多线程压测(对比开启/关闭IO线程的差异)
# 关闭IO线程
./src/valkey-server --port 6380 --io-threads 1 --daemonize yes
./src/valkey-benchmark -h 127.0.0.1 -p 6380 -t set,get -n 1000000 -c 200
# 开启IO线程
./src/valkey-server --port 6381 --io-threads 4 --daemonize yes
./src/valkey-benchmark -h 127.0.0.1 -p 6381 -t set,get -n 1000000 -c 200
# Pipeline 压测(更高吞吐量)
./src/valkey-benchmark -h 127.0.0.1 -p 6379 -t set,get -n 1000000 -c 50 -P 16
5.4 数据迁移方案
方案一:在线同步迁移
# 使用 valkey-cli 的 --replica 选项
# 将 Valkey 作为 Redis 的副本,同步完成后切换
./src/valkey-server --port 6380 --replicaof <redis-host> <redis-port>
# 等待同步完成
./src/valkey-cli -p 6380 INFO replication
# 等待 master_link_status:up 和 master_sync_in_progress:0
# 切换为独立节点
./src/valkey-cli -p 6380 REPLICAOF NO ONE
方案二:RDB 文件迁移
# 1. 在 Redis 上生成 RDB
redis-cli BGSAVE
redis-cli LASTSAVE # 记录时间戳
# 2. 复制 dump.rdb 到 Valkey 数据目录
cp /var/lib/redis/dump.rdb /var/lib/valkey/
# 3. 启动 Valkey(自动加载 RDB)
./src/valkey-server --dir /var/lib/valkey/ --dbfilename dump.rdb
方案三:应用层双写
# Python 双写迁移示例
import redis
redis_client = redis.Redis(host='redis-host', port=6379, decode_responses=True)
valkey_client = redis.Redis(host='valkey-host', port=6379, decode_responses=True)
def dual_write(key, value, ttl=None):
"""双写:先写 Valkey,再写 Redis"""
valkey_client.set(key, value, ex=ttl)
redis_client.set(key, value, ex=ttl)
def read(key):
"""读 Valkey,miss 则回源 Redis"""
value = valkey_client.get(key)
if value is None:
value = redis_client.get(key)
if value is not None:
valkey_client.set(key, value)
return value
5.5 Spring Boot 集成
Valkey 完全兼容 Redis 的连接协议,Spring Boot 应用只需修改连接配置:
# application.yml
spring:
data:
redis:
host: valkey-host
port: 6379
lettuce:
pool:
max-active: 64
max-idle: 32
min-idle: 16
// 代码无需任何修改,Spring Data Redis 直接连接 Valkey
@RestController
@RequestMapping("/api/cache")
public class CacheController {
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping("/{key}")
public String get(@PathVariable String key) {
return redisTemplate.opsForValue().get(key);
}
@PostMapping("/{key}")
public void set(@PathVariable String key, @RequestBody String value) {
redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
}
}
5.6 Go 语言集成
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/valkey-io/valkey-go"
)
func main() {
// 连接 Valkey(使用 valkey-go 客户端)
client, err := valkey.NewClient(valkey.ClientOption{
InitAddress: []string{"127.0.0.1:6379"},
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
ctx := context.Background()
// 基本操作
if err := client.Set(ctx, "user:1001", "Alice", 0).Err(); err != nil {
log.Fatal(err)
}
val, err := client.Get(ctx, "user:1001").Result()
if err != nil {
log.Fatal(err)
}
fmt.Printf("user:1001 = %s\n", val)
// Pipeline 批量操作
pipe := client.Pipeline()
for i := 0; i < 100; i++ {
pipe.Set(ctx, fmt.Sprintf("key:%d", i), fmt.Sprintf("value:%d", i), 0)
}
if err := pipe.Exec(ctx); err != nil {
log.Fatal(err)
}
// 分布式锁
ok, err := client.SetNX(ctx, "lock:resource1", "owner1", 10*time.Second).Result()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Lock acquired: %v\n", ok)
}
六、生产环境调优指南
6.1 核心配置参数
# valkey.conf 关键配置
# === 内存管理 ===
maxmemory 12gb # 物理内存的 70-80%
maxmemory-policy allkeys-lru # LRU 淘汰策略
# === 异步 IO 线程 ===
io-threads 4 # IO 线程数(建议 2-8)
io-threads-do-reads yes # IO 线程也处理读操作
# === 持久化 ===
save 3600 1 # 1 小时内 1 次修改则保存
save 300 100 # 5 分钟内 100 次修改
save 60 10000 # 1 分钟内 10000 次修改
rdbcompression no # 关闭 RDB 压缩(节省 CPU)
appendonly yes # 开启 AOF
appendfsync everysec # 每秒刷盘
# === 复制 ===
repl-diskless-sync yes # 无盘复制(减少磁盘 IO)
repl-diskless-sync-delay 5 # 等待 5 秒让更多副本加入
6.2 IO 线程数量调优
IO 线程数不是越多越好。根据 AWS 的压测数据:
| IO 线程数 | 单节点 QPS(GET) | 单节点 QPS(SET) | 建议场景 |
|---|---|---|---|
| 1(关闭) | ~50 万 | ~40 万 | 低并发场景 |
| 2 | ~80 万 | ~65 万 | 2-4 核机器 |
| 4 | ~120 万 | ~100 万 | 4-8 核机器 |
| 8 | ~130 万 | ~110 万 | 8-16 核机器 |
| 12+ | ~130 万 | ~110 万 | 收益递减,不建议 |
建议:IO 线程数设置为 CPU 核数的 1/2 到 2/3,最高不超过 8。超过 8 后收益递减明显。
6.3 内存优化
# 开启jemalloc(Valkey 推荐)
# 编译时指定
make MALLOC=jemalloc
# 运行时配置
activedefrag yes # 开启主动碎片整理
active-defrag-cycle-min 1 # 碎片整理最小 CPU 占用
active-defrag-cycle-max 25 # 碎片整理最大 CPU 占用
hash-max-listpack-entries 512 # 小哈希使用 listpack
hash-max-listpack-value 64 # 值小于 64 字节用 listpack
6.4 监控与可观测性
# Valkey 提供了每个槽的性能指标
valkey-cli INFO commandstats
valkey-cli INFO memory
valkey-cli INFO cpu
# 慢查询日志
slowlog-log-slower-than 10000 # 超过 10ms 记录
slowlog-max-len 128 # 最多保留 128 条
# 查看慢查询
valkey-cli SLOWLOG GET 10
七、Valkey vs Redis:2026 年技术选型
7.1 核心差异对比
| 维度 | Valkey 9.0 | Redis 8.0 |
|---|---|---|
| 许可证 | BSD 3-Clause(真开源) | RSALv2(重新开源但有争议) |
| 单节点 QPS | ~120 万 | ~20-30 万 |
| 集群最大节点 | 2000 | 1000(官方推荐) |
| IO 模型 | 异步任务队列 | 同步多线程 |
| 槽位迁移 | 原子迁移 | 多步迁移 |
| 哈希字段过期 | 支持 | 不支持 |
| 集群多数据库 | 支持 | 仅 DB0 |
| RDMA 支持 | 实验性支持 | 不支持 |
| 云厂商支持 | AWS/Google/Oracle 原生 | 仅 Redis Inc. |
| 模块生态 | 重建中 | 成熟 |
7.2 选型建议
选 Valkey 的场景:
- 新项目选型,追求性能和开源自由
- 需要大规模集群(数百节点以上)
- 使用 AWS ElastiCache / Google Cloud Memorystore(原生支持 Valkey)
- 需要哈希字段级过期
- 需要集群多数据库隔离
暂时保留 Redis 的场景:
- 强依赖 Redis 模块(如 RediSearch、RedisJSON、RedisBloom)
- 使用 Redis Stack 的组合功能
- 现有 Redis 集群运行稳定,迁移成本高
- 需要 Redis Inc. 的企业级支持
7.3 混合部署策略
对于已有 Redis 基础设施但想逐步迁移的团队,可以采用混合策略:
# 架构示例:Redis + Valkey 混合部署
#
# 写热点 → Valkey(高性能写入)
# 读缓存 → Valkey(高吞吐)
# 搜索索引 → Redis + RediSearch(模块依赖)
# 会话管理 → Valkey(字段级过期)
# 消息队列 → 两者均可(Stream 兼容)
八、从 Valkey 看开源数据库的未来
8.1 技术启示
Valkey 的演进给开源数据库带来几个重要启示:
1. 架构级优化比渐进式改进有效得多
Redis 6.0 的多线程 IO 是渐进式的(同步等待模型),只带来了 2x 提升。Valkey 8.0 的异步 IO 是架构级重构(异步任务队列),带来了 5-6x 提升。这说明:当性能接近天花板时,修补不如重构。
2. 内存墙是下一个战场
CPU 单核性能提升缓慢,但内存延迟没有等比例改善。Valkey 的 Prefetch 和 MAA 技术是应对「内存墙」的经典方案,这种思路可以推广到其他内存数据库甚至应用层。
3. 社区分叉可以比原项目更快
Valkey 分叉两年,25.4k Stars,推出了 Redis 尚不具备的原子槽位迁移、哈希字段过期等特性。开源许可证的选择直接影响项目的创新速度。
8.2 展望
Valkey 正在沿着以下方向继续演进:
- RDMA 支持:实验性支持 RDMA,进一步降低网络延迟
- 多模态扩展:向量搜索能力的持续增强(与 AI 应用深度融合)
- Serverless 原生:支持更细粒度的按需扩缩容
- 可观测性增强:每个槽的细粒度指标,更好的集群诊断能力
九、总结
Valkey 从 Redis 许可证危机中诞生,在两年内完成了从「替代品」到「技术引领者」的蜕变:
- Valkey 8.0 通过异步 IO 线程、数据预取、内存访问分摊,将单节点性能推到 120 万 QPS
- Valkey 9.0 通过原子槽位迁移、集群多数据库、哈希字段过期,将集群能力扩展到 2000 节点和 10 亿 RPS
对于新项目,Valkey 已经是值得优先考虑的选择。对于存量 Redis 部署,建议评估迁移成本后制定渐进式迁移方案。无论选择哪个,Valkey 的架构创新——尤其是异步任务队列和内存访问分摊的思路——都值得每个后端工程师深入理解。
参考资源:
- Valkey 官方仓库:https://github.com/valkey-io/valkey
- Valkey 文档:https://valkey.io/docs/
- AWS Valkey 性能测试报告
- 得物技术博客《Valkey 8.0 新特性分析》