gpt4 book ai didi

mysql - Aurora Serverless Mysql 上的一致读/写

转载 作者:行者123 更新时间:2023-11-29 05:48:35 25 4
gpt4 key购买 nike

拥有分布式无服务器应用程序,基于 AWS Aurora Serverless MySQL 5.6 和多个 Lambda 函数。一些 Lambda 代表写入线程,另一些是读取线程。为了表示最重要的细节,让我们假设只有一个具有以下结构的表:

id: bigint primary key autoincrement
key1: varchar(700)
key2: bigint
content: blob
unique(key1, key2)

写线程按以下方式执行 INSERT:每个写线程生成一个带有 key1+key2+content 的条目,其中 key1+key2 对是唯一的,并且 id 是通过自动增量自动生成的。如果 key1+key2 具有重复值,一些写入线程可能会因 DUPLICATE KEY ERROR 而失败,但这无关紧要。

还有一些读取线程,它们是轮询表并尝试处理新插入的条目。读取线程的目标是检索所有新条目并以某种方式处理它们。读取线程数量不受控制,它们之间不通信,不在上面的表中写入任何内容,但可以在自定义表中写入一些状态。

首先,轮询似乎非常简单 - 读取进程存储已处理的最后一个 id 并从中继续轮询就足够了,例如SELECT * FROM table WHERE id > ${lastId}。上面的方法适用于小负载,但不适用于高负载,原因很明显:有一些插入条目尚未出现在数据库中,因为此时集群尚未同步。

让我们看看在集群的角度会发生什么,事件如果它只包含两台服务器 A 和 B。
1) Server A 接受写入事务并插入条目并获取自增数 100500
2) Server B 接受写入事务并插入条目并获取自增数 100501
3)服务器B提交写事务
4) Server B接受读事务,返回id > 100499的条目,也就是100501条目。
5)服务器A提交写事务。
6) 读取线程仅接收到100501 条目并将lastId 游标移动到100501。当前读取线程的条目 100500 将永远丢失。

问题:有没有办法在所有集群上都没有硬锁表的情况下以某种无锁感知方式或类似方式解决上述问题?

最佳答案

这里的问题是每个 lambda(线程)中的局部状态并不反射(reflect)所述表的全局状态。

作为第一个电话,在阅读具有该 ID 的条目之前,我会尝试始终查询表中最新的 ID 是什么。

查看内置函数 LAST_INSERT_ID()在 MySQL 中。


注意事项

[...] the most recently generated ID is maintained in the server on a per-connection basis

你的 lambda 可能会在 handler 函数/方法之前创建连接,这将使它们的生命周期更长(这是一个已知的技巧,但它在这里不是防弹的),但我认为新的同时执行的 lambda 函数将获得一个新的连接,在这种情况下,上述解决方案将分崩离析。

幸运的是,您接下来要做的是将所有 WRITES 和所有 READS 包装在事务中,以便在同时读取和写入同一个表时进行额外的协调。

在你的任务中你可能会遇到 transaction isolation levels SEERIALIZEABLE 将是最安全且性能最差,但是apparently AWS Aurora does not support it (我没有证实那个说法)。

HTH

关于mysql - Aurora Serverless Mysql 上的一致读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57090226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com