当前位置: 首页 > 科技观察

说说Undermoon-RedisClusterSlots迁移

时间:2023-03-20 18:34:37 科技观察

项目地址:https://github.com/doyoubi/undermoon目标:简单快速的迁移过程基于以下Redis命令:SCANDUMPPPTTLRESTOREDELSCAN命令有一个很好的特性,保证Allkeysset在最终返回SCAN命令之前,但有时会返回多次。我们可以执行3阶段迁移来模拟复制。等待Redis完成所有命令。将所有读写操作重定向到目标Redis。如果key不存在,目标Redis在处理命令之前需要从源Redis中dump出key的数据。开始扫描并将数据转发到对等Redis。迁移代理(migrationproxy)详细步骤通过PreCheck命令检查导入代理(importproxy)是否也收到了迁移任务。迁移代理阻止所有新添加的命令到队列并等待现有命令完成。迁移代理将TmpSwitch命令发送到导入代理。导入代理收到该命令后,开始处理导入槽范围内的密钥。当命令返回时,迁移代理释放队列中的所有命令并将它们重定向到导入代理。迁移代理使用SCAN、PTTL、DUMP、RESTORE、DEL将迁移槽范围内的所有数据转发给对等导入Redis。RESTORE不设置REPLACE标志。导入代理在处理命令时,无论是读操作还是写操作,都会先将EXISTS和处理后的命令发送给本地导入Redis。如果EXISTS返回true,该命令将被转发到本地导入Redis。如果EXISTS返回false,则向迁移后的Redis发送DUMP和PTTL获取数据,RESTORE数据并将命令转发给本地Redis。最后将命令转发到本地导入Redis。如果该命令不会删除密钥,则获取密钥锁,如果该命令可能删除密钥,则获取密钥锁并将UMSYNC发送给迁移代理,让迁移代理使用DUMP、PTTL、RESTORE、DEL传输密钥到进口代理。最后将命令转发到本地导入Redis。当迁移代理完成扫描时,它会向导入代理建议一个CommitSwitch。那么导入代理只需要处理本地Redis中的命令即可。通知协调员并等待UMCTLSETCLUSTER的最终提交。为什么要这样设计整个迁移过程是基于以下命令SCAN、PTTL、DUMP、RESTORE、DELETE。RESTORE命令只发送到导入代理,因此为了获得更好的性能,应该在迁移代理中执行此扫描和传输。由于扫描和传输在服务器代理和Redis上都是CPU密集型的,因此最好在导入代理上处理其他工作负载。因此,一开始我们将所有插槽直接移至导入代理。此时,导入代理仍然只有一小部分数据。当它需要在新添加的插槽上处理命令时,它需要在处理请求之前使用PTTL、DUMP、RESTORE从迁移的服务器代理中拉取数据。它还需要发送DELETE来删除密钥。请注意,对于任何不删除密钥的命令,多次RESTORE相同的密钥仍然是正确的,因为它是幂等的。因此,仅让导入代理拉取数据不会导致任何不一致。但是对于可能删除密钥的命令,如DEL、EXPIRE、KPOP,仅让导入代理拉取数据可能会导致密钥被删除并且有另一个RESTORE命令可以恢复密钥的情况。因此,提取数据时,需要结合导入代理中的其他RESTORE命令。迁移代理中的SCAN和RESTORE。因此,我们需要将key锁定在importingproxy中,需要migratingproxy帮助我们发送数据,而不是从importingproxy中拉取数据,这样对那个key的操作只能顺序处理。性能因此,在迁移过程中,迁移和导入代理的工作量得到了很好的平衡。迁移代理使用130%的CPU,导入代理使用80%的CPU。而且1G的数据迁移不到一分钟。在测试中,边基准边迁移,吞吐量从50k降低到28k,逐渐增加到40k。这是因为SCAN、DUMP、RESTORE在迁移和导入proxy的过程中消耗了Redis大量的吞吐量。但是一旦密钥被迁移到导入服务器代理,它只需要在请求之前发送一个额外的EXISTS命令。一旦提交迁移,吞吐量将翻倍。