Mnesia碎片和复制:由此产生的可用性和可靠性

Muz*_*hua 7 erlang yaws mnesia erlang-otp nitrogen

我最近询问有关mnesia碎片问题的解决方案之后,我仍然面临许多挑战.请考虑以下场景(我要问的问题基于以下内容):

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

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

现在,同时,恢复中心也必须具有相同的数据副本并且
始终同步,以防因本地数据访问因攻击
或硬件故障而中断.因此,相同的数据库架构必须在3个复制
位点(A面,B面恢复中心).

现在,在企业内,应用程序中间件能够在数据库站点之间切换数据请求.如果A已关闭,那么在应用程序未实现的情况下,请求将重新路由到数据库B,依此类推.中间件层可以配置为执行负载平衡(请求多路复用)或使用故障转移技术灵活.

进一步分析:

At Database/Schema creation time, all involved Nodes must be up and running 
Mnesia. To achieve this, you create say: 'db_side_A@domain.com',
'db_side_B@domain.com' and finally, 'db_recovery_center@domain.com'

现在,在创建表时,您可能希望将mnesia表分段.所以你决定以下参数:

n_disc_only_copies =:= number of nodes involved in the pool =:= 3 
Reason: You are following the documentation that this parameter regulates how 
many disc_only_copies replicas that each fragment should have.
So you want each table to have each of its fragments on each mnesia Node.
node_pool =:= all nodes involved =:= ['db_side_A@domain.com',
'db_side_B@domain.com',
'db_recovery_center@domain.com']
然后根据以下安排创建所有表格
Nodes = [
                '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)}]
                    },
                    {index,[]},
                    {attributes,record_info(fields,RECORD_NAME_HERE)}]
                ),
注意:在上面的语法中,RECORD_NAME_HERE实际上不能是变量,因为在编译时必须使用Erlang知道记录.从安装中可以看出,对于每个表,每个片段table_name_frag2都会出现在每个Node的文件系统上.

挑战和出现的问题:
按照上面列出的内容,您的第一个数据库启动是可以的,因为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一起死亡,那就更糟了.好吧,这里和那里的一些调整和脚本可以帮助重新启动整个虚拟机以及预期的应用程序(如果它发生故障).

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

问题:

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

  2. inconsistent_database, starting to run database behind a partitioned network关于我的申请,mnesia事件的后果是什么?如果我对这个事件没有反应并让事情继续发展,那该怎么办?我丢失了数据吗?

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

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

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