OrientDB可以分布在不同的服务器上,并以不同的方式使用,以实现性能、可扩展性和健壮性的最大化。
OrientDB使用Hazelcast开源项目自动发现节点,存储运行时集群配置,并在节点之间同步某些操作。本页中的一些参考资料链接到Hazelcast官方文档,以获取有关此类主题的更多信息。
注意:在分布式模式下运行时,OrientDB需要更多的RAM。最小值是2GB堆,但我们建议至少使用4GB堆内存。要更改堆,请修改文件bin/server.sh(或Windows上的server.bat)中的Java内存设置
基本概念
服务器角色
OrientDB有一个多主机分布式体系结构(也称为“无主机”),其中每个服务器都可以读写。从v2.1开始,OrientDB支持“副本”角色,其中服务器处于只读模式,只接受幂等命令,如Reads和Query。此外,当服务器作为“副本”加入分布式集群时,不会像“主”节点那样创建自己的记录集群。
从v2.2开始,拥有多个副本服务器的最大优点是它们在writeQuorum中不一致,因此如果您有3个主服务器和100个副本服务器,则每个写操作都将在103个服务器上复制,但大多数writeQuorum将只有2个,因为给定N/2+1,N是主服务器的数量。在这种情况下,在本地执行操作之后,写操作的服务器协调器只需等待另外一个主服务器。
集群所有权
当在分布式模式下创建新记录(文档、顶点和边)时,RID是通过遵循“集群位置”来分配的,其中每个服务器定义一个“自己的”记录集群,它可以在其中创建记录。如果您有Customer类和3个服务器节点(node1、node2、node3),那么您将拥有这些集群(名称可以不同):
customer
with id=#15 (这是默认值,分配给node1)customer_node2
with id=#16customer_node3
with id=#17
因此,如果在node1上创建一个新客户,它将获得集群id为“Customer”cluster:#15的RID。在node2上的相同操作将在node3上生成集群id=16和17的RID。这样RID就不会发生冲突,每个节点都可以在插入时成为主节点,而不会发生任何冲突,因为每个节点都管理自己的RID。从v2.2开始,如果一个节点每个类有多个集群,则使用循环策略来平衡所有可用本地集群之间的分配。
所有权配置存储在default-distributed-db-config.json文件中。默认情况下,集群的服务器所有者是服务器列表中的第一个。例如,使用此配置:
"client_usa": {
"servers" : [ "usa", "europe", "asia" ]
},
"client_europe": {
"servers" : [ "europe", "asia", "usa" ]
}
服务器节点“usa”是集群客client_usa的所有者,因此“usa”是唯一可以在此类集群上创建记录的服务器。因为每个服务器节点每个类都有自己的集群,所以每个节点都可以在不同的集群上创建记录。由于记录集群是类的一部分,当用户执行INSERT INTO client SET name=“Jay”时,OrientDB会自动选择本地集群来存储新的“client”记录。如果在服务器“usa”上执行此插入操作,则选择“client_usa”集群。如果在服务器“europe”上执行sam操作,则会选择群集“client_europe”。重要的是,从逻辑的角度来看,来自集群“client_usa”和“client_europe”的两个记录总是“client”类的实例,因此如果执行以下查询SELECT*from client,两个记录都将被检索。
静态所有者
从v2.2开始,无论运行时配置如何,都可以将节点作为所有者。我们称之为“静态所有者”。为此,请使用“owner”:“<NODE_NAME>”。例子:
"client_usa": {
"owner": "usa",
"servers" : [ "usa", "europe", "asia" ]
}
分布式事务
OrientDB支持分布式事务。提交事务时,所有更新的记录都会跨所有服务器发送,因此每个服务器都负责提交事务。如果一个或多个节点在提交时失败,将检查仲裁。如果遵守了仲裁,则失败节点将与获胜节点对齐,否则所有节点将回滚事务。
当运行分布式时,事务使用类似于2阶段锁的协议,很酷的一点是,一切都是乐观的,因此在begin和commit之间没有锁,但是一切都只在commit时执行。
在提交期间,OrientDB会获取所接触记录的锁,并检查记录的版本(乐观MVCC方法)。在这一点上,这可能发生:
- 所有的记录都可以被锁定,而且从发送开始就没有人碰过这些记录,所以事务被提交。很酷。
- 如果有人修改了作为事务一部分的任何记录,事务将失败,客户端可以重试
- 如果在提交时,另一个事务锁定了任何相同的记录,则该事务将失败,但在这种情况下,重试是自动的,并且是可配置的
如果您有5台服务器,并且writeQuorum占大多数(N/2+1=3),则可能会发生这种情况:
- 所有5台服务器都提交TX:cool
- 1或2台服务器报告任何错误,发送仍然提交(仲裁通过),1或2台服务器将被迫与其他服务器具有相同的结果
- 3台或更多服务器有不同的结果/错误,因此所有服务器上的tx都回滚到初始状态
分布式事务期间的可见性如何?
在分布式事务期间,在回滚的情况下,记录在回滚之前可能会有一段时间发生更改。
分裂脑网络问题
如果将OrientDB配置为将writeQuorum设置为大多数节点数的值,则OrientDB可以保证强一致性。如果你有5个节点,它是3,但如果你有4个节点,它仍然是3有一个多数。虽然writeQuorum设置也可以在数据库和集群级别进行配置,但不建议设置一个比大多数节点小的值,因为在重新合并2个拆分的网络的情况下,两个网络分区都有更新的数据,并且OrientDB还不支持合并2个非只读网络。因此,建议始终为writeQuorum提供一个值,至少为大多数节点提供一个值。
冲突解决策略
如果服务器数量为偶数或数据库未对齐,OrientDB将使用冲突解决策略链。此默认链定义为全局设置(distributed.conflictResolverRepairerChain):
-Ddistributed.conflictResolverRepairerChain=majority,content,version
- 首先检查在记录版本方面是否有严格多数的记录。如果多数票存在,就选出胜利者
- 如果没有找到严格多数,则分析记录内容。如果通过创建一个版本不同但内容相同的记录来达到多数,那么通过在两个版本之间使用较高的版本,该记录将成为赢家
- 如果没有发现内容占多数,则较高的版本获胜(假设较高的版本意味着更新最多的记录)
OrientDB Enterprise Edition支持附加的数据中心冲突解决(dc)。
在链的最后,如果没有找到赢家,记录将保持不变,只有人工干预才能决定谁是赢家。在这种情况下,控制台中会显示一条带有文本的警告消息 Auto repair cannot find a winner for record <rid> and the following groups of contents: [<records>]
局限性
OrientDB v2.2.x在分布式模式下工作时有一些限制:
- 不支持内存中的数据库。
- 不支持在运行分布式时导入数据库。以非分布式模式导入数据库,然后以分布式模式运行OrientDB。
- 在版本<v2.2.6的情况下,当自动创建集群时,在多个节点上创建数据库可能会导致同步问题。在以分布式模式运行之前,请先创建数据库。
- 分布式数据库的约束可能会导致问题,因为有些操作是通过两个步骤执行的:创建+更新。例如,在某些情况下,可以先创建边,然后再进行更新,但是针对字段的强制和NOTNULL等约束在第一步将失败,这使得在分布式模式下无法创建边。
- 分布式哈希表(DHT)通常不支持自动分片。选择正确的shard(集群)取决于应用程序。下一个版本将解决这个问题。
- 尚不支持分片索引,因此针对分片类创建唯一索引并不能保证键是唯一的。这将在以后的版本中通过自动分片来解决。
- 分布式配置的热更改仅在企业版(商业许可)中可用。
- 在sharder配置上运行时,没有完全合并所有投影的结果。有些函数如AVG()在map/reduce上不起作用。
注意:本文归作者所有,未经作者允许,不得转载