7

在解决了我最近提出的有关 mnesia fragmentation的问题之后,我仍然面临许多挑战。考虑以下场景(我要问的问题基于以下内容):

您有一个数据驱动的企业应用程序,它应该
在企业内高度可用。如果内部信息源因任何原因而关闭,企业应用程序必须切换到从异地(远程)恢复中心
获取数据。

您决定将数据库复制到企业内的两个节点上
(称为DB 端 ADB 端 B)。这两者在单独的
硬件上运行,但通过快速以太网或光纤链路连接在一起。从逻辑上讲,您在这两个 Mnesia DB
之间创建了某种隧道或安全通信。
两者(A 和 B)应该具有相同的数据副本并且
始终保持同步。

现在,与此同时,恢复中心也必须拥有相同的数据副本并
始终保持同步,以防本地数据访问因攻击
或硬件故障而中断。因此,必须在 3
个站点(A面、B 面恢复中心)之间复制相同的数据库模式。

现在,在企业内部,应用程序中间件能够在数据库站点之间切换数据请求。如果 A 宕机,那么在应用程序没有意识到的情况下,请求被重新路由到数据库 B,依此类推。中间件层可以配置为进行负载平衡(请求多路复用)或灵活地使用故障转移技术。

进一步分析

在创建数据库/模式时,所有涉及的节点都必须启动并运行
Mnesia。为了实现这一点,你创建说:'db_side_A@domain.com'
'db_side_B@domain.com'最后,'db_recovery_center@domain.com'

现在,在创建表时,您可能希望将您的 mnesia 表分段。因此,您决定以下参数:

n_disc_only_copies =:= 池中涉及的节点数 =:= 3
原因:您遵循此参数规定
每个片段应具有多少 disc_only_copies 副本的文档。
因此,您希望每个表在每个 mnesia 节点上都有其每个片段。
node_pool =:= 涉及的所有节点 =:= ['db_side_A@domain.com',
'db_side_B@domain.com',
'db_recovery_center@domain.com']
然后根据以下安排创建所有表
节点 = [
                'db_side_A@domain.com',
                'db_side_B@domain.com',
                'db_recovery_center@domain.com'
            ],
    No_of_fragments = 16,
    {atomic,ok} = mnesia:create_table( TABLE_NAME ,[
                    {frag_properties,[
                        {node_pool,Nodes},
                        {n_fragments,No_of_fragments},
                        {n_disc_only_copies,length(Nodes)}]
                    },
                    {指数,[]},
                    {属性,记录信息(字段,RECORD_NAME_HERE)}]
                ),
注意:在上面的语法RECORD_NAME_HERE中,实际上不能是变量,因为在 Erlang 编译时必须知道记录。从安装中,您可以看到对于每个表,每个片段,例如table_name_frag2,出现在每个节点的文件系统上。

挑战和出现的问题
按照上面列出的内容进行操作后,您的第一次数据库启动是可以的,因为 mnesia 正在所有节点上运行。随着应用程序的运行,一些挑战开始出现,并列出以下内容:

  1. 假设您决定首先尝试所有写入,DB Side A并且如果此时 A 端不可用,则重新尝试调用DB Side B,以此类推recovery center,如果调用在所有 3 个数据库节点上均未返回,则应用程序网络中间件层报告数据库服务器全部不可用(这个决定可能受到以下事实的影响:如果您让应用程序随机写入您的 mnesia 副本,则很可能会出现不一致的数据库错误,以防您的 mnesia 节点丢失彼此之间建立网络连接,但不同的 Erlang 应用程序正在各自提交写入。如果您决定拥有master_nodes,那么您可能会面临丢失数据的风险)。所以通过行为,你是在强迫DB Side A成为主人。这使得其他数据库节点一直处于空闲状态,只要DB Side A启动并运行,并且与命中方 A 一样多的请求并且它不会关闭,则根本没有请求会到达 B 方和恢复中心。

  2. 通常,Mnesia 在启动时应该看到所有相关节点都在运行(mnesia 必须在所有相关节点上运行),以便它可以进行协商和一致性检查。这意味着如果 mnesia 在所有节点上都出现故障,则必须在所有节点上启动 mnesia,然后才能完全初始化和加载表。如果 Erlang VM 在远程站点上与 Mnesia 一起死掉,那就更糟了。好吧,这里和那里的一些调整和脚本可以帮助重新启动整个 VM 以及如果它出现故障的预期应用程序。

长话短说,让我回答问题。

问题

  1. 如果 mnesia在不希望inconsistent_database, starting to run database behind a partitioned network设置 a 的情况下(因为担心数据丢失)生成 的事件,数据库管理员会怎么做?mnesia master node

  2. mnesia 事件inconsistent_database, starting to run database behind a partitioned network对我的申请有什么影响?如果我不对这个事件做出反应,让事情继续原样发生怎么办?我会丢失数据吗?

  3. 在大型 mnesia 集群中,如果 Mnesia 与远程站点上的 Erlang VM 一起出现故障,该怎么办?是否有任何已知的自动处理这种情况的好方法?

  4. 有时由于网络问题或故障导致一两个节点无法访问,并且幸存节点上的 mnesia 报告给定文件不存在,尤其是在您拥有indexes. 那么在运行时,如果某些副本出现故障,我的应用程序的行为会怎样?你会建议我在 mnesia 集群中有一个主节点吗?

当您回答上述问题时,您还可以突出显示开头描述的布局,它是否能确保可用性。您可以提供有关在生产中使用 mnesia 碎片和复制数据库的个人经验。关于本文开头的链接(引用)问题,请提供可以在创建数据库时提供更高可靠性的替代设置,例如片段数量、操作系统依赖关系、节点池大小、表副本类型, ETC。

4

0 回答 0