暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

晨章KV的多线程性能以及跨分片事务测试

晨章数据 2024-11-26
45

前言

Redis是一款高性能的开源内存数据库,广泛用于缓存和简单的KV数据存储,但在事务支持方面有所局限。

Redis事务

Redis使用 *MULTI  EXEC* 实现事务,MULTI 开启事务,然后将事务中的命令放入一个队列中,EXEC 执行事务队列的命令,这些命令会按顺序执行,且具有以下特点:

1.原子性(部分):要么所有命令都执行,要么所有命令都不执行,且 Redis 在发生失败时不会回滚已成功执行的命令。

2.顺序性: 事务中的命令严格按提交顺序执行。

3.隔离性: 在事务执行期间,其他客户端的命令不会插入到当前事务的执行中

可以看出,与MySQL这种关系型数据库事务的不同之处,MySQL的事务中只要一个命令出现异常,所有的命令都不会执行(回滚),而Redis无法做到这一点。

如图,我们在Redis中开启了一个事务,第二条hset命令和第一条set命令都操作了同一个key,执行时显然是要报错的,我们看第二条和第三条命令是否可以正常执行。

如图,exec执行事务队列中的命令,第二条命令报错,但是第一、三条命令都正常执行。所以,*Redis的事务不具备原子性*

除此之外,Redis在事务原子性方面的不足,还表现在以下几个方面:

1.单线程模型

Redis采用单线程处理请求,这虽然简化了设计,避免了锁的复杂性,但也限制了其垂直扩展能力。在多核现代服务器上,Redis的性能提升有限,无法充分利用多线程处理能力,导致高并发时的性能瓶颈。

 Redis 6 开始,虽然可以通过配置文件显式启用多线程功能,但多线程被用于处理网络请求的读写操作,比如接受客户端连接、读取请求数据、发送响应。Redis 的核心执行逻辑仍然保持单线程模型。

2.不支持跨分片通信

Redis Cluster模式下,key是通过哈希槽分配到不同的节点(分片)上的,因为Redis的多个分片实例之间无法相互通信,这意味着无法在多个分片之间实现一致的原子性事务。

Redis WATCH 命令来监控一个或多个键的变化。在 WATCH 后,如果这些键在执行 MULTI  EXEC 之间发生了变化,Redis 会自动放弃执行事务。

假如我们在节点A上执行上述命令,key1在节点Akey2在节点B,当你执行 MULTI  EXEC 时,节点 A 将会尝试提交包含 SET key1  SET key2 的事务,但由于 key2 在节点 B 上,节点 A 无法知道 key2 是否已经被修改。

节点A不能跨节点监听到其他节点上键的变化,期间如果key2发生变化,所以就无法取消key1的操作,不能保证事务的原子性。

3.手动管理Key映射

为了解决上面跨分片的事务问题,Redis 给开发者提供了 *hashtag* 的方式,以确保这些Key映射到同一分片。hashtag 是一种通过在键名中使用特定的标记(例如 {})来限制哈希槽范围的方式。只有被括起来的部分会参与哈希计算,确保多个键在同一个分片上。

例如,key1  key2 默认情况下可能会分配到不同的分片,但如果你指定了 hashtag(如 {key1}  {key2}),Redis 会计算{key1}  {key2} 中的大括号部分来计算哈希槽,从而确保这两个键落在同一个分片上。

{user:1000}:name {user:1000}:age 会被视为同一个“hashtag”部分,即 user:1000,这确保了这两个键会被映射到同一个分片

这种方式对业务代码的侵入性较强,增加业务代码的复杂性,并增加了管理复杂性。

晨章KV

晨章KV是一款兼容Redis协议的分布式Key-Value数据库,旨在解决这些不足之处。作为高性能、弹性扩展、支持事务的分布式数据库,晨章KV具有以下特点:

1.多线程架构

晨章KV支持多线程,能够利用现代多核服务器资源,提升吞吐量并实现垂直扩展。

2.分片之间支持通信

晨章KV的分布式架构支持不同分片之间的通信,使其能够在跨分片的事务中保持一致性。 晨章KV可以根据业务增长动态扩展,满足大规模分布式场景需求,并为开发者提供一致的体验。

测试环境

本次测试在两台服务器上进行配置:

1.服务器一:32核物理机,部署晨章KV/Redis实例。

2.服务器二:32核物理机,部署测试服务器。

本实验主要是为了验证多Key访问的原子性能力,因此Redis 没有开启 RDBAOF,晨章KV没有开启enable_data_store enable_wal。其他选项可以根据自己需要灵活配置。

景模拟:社交软件中的点赞事务

在社交应用场景中,点赞操作通常包含两个步骤:更新点赞计数、将用户ID添加到点赞用户列表中。这两个步骤需要原子性,即它们要么全部成功,要么全部失败,以确保数据的一致性。

Redis中,我们可以通过MULTI/EXEC命令来实现多步操作的事务,但这种事务仅在单分片内有效。在跨分片的场景中,Redis要求手动调整Key的分片映射,使其都在同一实例上。

相比之下,晨章KV能够在不同分片之间进行通信,直接支持多分片事务,这对于需要分布式事务的业务场景尤为重要。

实验Benchmark

在本实验中,我们使用Go语言编写了一段模拟代码,以实现上述社交软件点赞场景的事务操作。代码会统计QPSLatency等性能指标,以评估在高并发场景下两种数据库的性能差异。

Go语言代码示例:

Python语言代码示例:

测试结果

我们通过运行上面高并发调用模拟点赞操作的代码,并分别记录在Redis和晨章KV下的QPS(每秒查询数)和平均延迟(Latency)指标。

Redis测试结果:*10QPS,延迟0.01ms*

晨章KV测试结果:*40QPS,延迟0.00ms*

从上面的测试结果我们可以得出结论:*Redis在高并发环境下,由于单线程限制,RedisQPS受到瓶颈限制,平均延迟较高。而晨章KV的多线程架构能够支持更高的QPS,延迟显著降低。

补充实验:跨分片事务

Redis要求所有涉及事务性操作的键必须映射到同一个分片上,所以Redis Cluster 默认不支持跨分片的事务操作。那么晨章KV是否支持跨分片的是事务场景。

这里我们同样使用pythongo实现了跨分片事务的测试代码,在代码中只需要修改IP和端口,就能分别对 Redis Cluster 和 晨章KV 的分片事务测试。

Python代码如下:

go语言示例代码如下:

运行以上代码,因为在水平扩展场景下,Redis Cluster 默认不支持跨分片的事务操作,所以Redis Cluster会返回错误:*CROSSSLOT Keys in request don't hash to the same slot*

如果开启了重定向,虽然不同的key会被重定向到对应的节点上,但是最后exec执行也是失败的。

如果没有开启重定向,key无法重定向,在exec也会报错。

而晨章KV cluster可以正确处理跨分片事务请求,运行结果如图:

我们进入晨章KV的命令行,查看数据是否已经被放入到晨章KV中。

我们通过*cluster keyslot*进一步验证两条数据的key是否在不同的分片上。

如图,user:1  user:2 所在的slot在不同的分片上。

总结

通过本次测试,我们可以清晰地看到晨章KV在事务能力上相较Redis的显著优势:

1.跨分片事务支持

晨章KV支持跨分片事务,实现了在水平扩展环境中的一致性事务处理,降低了对业务代码的侵入性。

2.多线程架构

晨章KV的多线程架构在高并发场景下能够提供更高的QPS和更低的延迟,充分利用多核服务器资源,提升了整体性能。

 3.一致的开发体验

晨章KV提供了兼容Redis协议的接口,使开发者无需更改代码,即可在大规模分布式环境中获得一致的事务体验。

结语

晨章KV不仅为开发者提供了与Redis兼容的接口,还通过其高效的事务处理能力为复杂的分布式应用提供了更强大的支持,满足了现代业务对事务性和扩展性的需求。


文章转载自晨章数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论