15.25. 常见复制冲突

多层次复制使用最终一致性复制模型。这意味着在不同服务器上可以更改相同的条目。当在两个服务器之间进行复制时,需要解决冲突的更改。大部分情况下,根据与每台服务器上更改相关的时间戳自动进行解析。最新的更改具有优先权。
然而,在有些情况下,冲突需要人工干预才能到达分辨率。复制过程无法自动解析的更改冲突的条目。
要列出冲突条目,请输入:
# dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict list dc=example,dc=com

15.25.1. 命名冲突

当在不同的服务器上使用相同的 DN 创建两个条目时,复制过程中自动冲突解析过程会重命名创建的最后一个条目,包括 DN 中条目的唯一标识符。每个目录条目都包含存储在 nsuniqueid 操作属性中的唯一标识符。当发生命名冲突时,这个唯一 ID 会附加到非唯一的 DN 中。
例如,如果在两个不同的服务器上创建了 uid=user_name,ou=People,dc=example,dc=com 条目,复制会将唯一 ID 添加到创建的最后一个条目的 DN 中。这意味着存在以下条目:
  • uid=user_name,ou=People,dc=example,dc=com
  • nsuniqueid=66446001-1dd211b2+uid=user_name,ou=People,dc=example,dc=com
要解决复制冲突,您必须手动决定如何继续:
  • 要只保留有效的条目(uid=user_name,ou=People,dc=example,dc=com)并删除冲突条目,请输入:
    # dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict delete nsuniqueid=66446001-1dd211b2+uid=user_name,ou=People,dc=example,dc=com
  • 要只保留冲突条目(nsuniqueid=66446001-1dd211b2+uid=user_name,ou=People,dc=example,dc=com),请输入:
    # dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict swap nsuniqueid=66446001-1dd211b2+uid=user_name,ou=People,dc=example,dc=com
  • 要保留这两个条目,请输入:
    # dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict convert --new-rdn=uid=user_name_NEW nsuniqueid=66446001-1dd211b2+uid=user_name,ou=People,dc=example,dc=com
    要保留冲突条目,您必须在 --new-rdn 选项指定一个新的 Relative Distinguished Name (RDN)来重命名冲突条目。上一命令将冲突条目重命名为 uid=user_name_NEW,ou=People,dc=example,dc=com

15.25.2. Orphan Entry Conflicts

当复制删除操作并且消费者服务器发现要删除的条目具有子条目时,冲突解析过程会创建一个 粘滞 条目以避免目录中有孤立的条目。
同样,当复制 add 操作且消费者服务器无法找到父条目时,冲突解析过程会创建一个代表父条目的 glue 条目,以便新条目不是孤立条目。
glue 条目是 包括对象类 glue 和 Scalable Object 的临时条目。可使用几种方式创建 glue 条目:
  • 如果冲突解析流程发现带有匹配唯一标识符的已删除条目,glue 条目是该条目的重新发送,添加了 glue 对象类和 nsds5ReplConflict 属性。
    在这种情况下,修改 glue 条目以删除 glue 对象类和 nsds5ReplConflict 属性,以将条目保留为正常条目或删除 glue 条目及其子条目。
  • 服务器使用 glue 和 Scalable Object 对象类创建一个最小的条目。
在这种情况下,修改条目使其转换为有意义的条目,或者将其删除及其所有子条目。
列出所有 glue 条目:
# dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict list-glue suffix
删除 glue 条目及其子条目:
# dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict delete-glue DN_of_glue_entry
将 glue 条目转换为常规条目:
# dsconf -D "cn=Directory Manager" ldap://server.example.com repl-conflict convert-glue DN_of_glue_entry

15.25.3. 解决 Obsolete 或 Missing Suppliers 的错误

有关复制拓扑的信息,这是所有供应商为同一复制组中的相互更新和其他副本都包含在一组称为 副本更新向量(RUV)的元数据中。RUV 包含有关供应商的信息,如其 ID 和 URL、本地服务器上最新的更改状态号(CSN),以及第一个更改的 CSN。供应商和消费者存储 RUV 信息,它们使用它来控制复制更新。
当从复制拓扑中删除一个供应商时,它可能会保留在另一个副本的 RUV 中。当其他副本重启时,它可以记录日志中的错误,警告复制插件无法识别删除的供应商。这个错误类似以下示例:
[22/Jan/2021:17:16:01 -0500] NSMMReplicationPlugin - ruv_compare_ruv: RUV [changelog max RUV] does not contain element [{replica 8 ldap://m2.example.com:389} 4aac3e59000000080000 4c6f2a02000000080000] which is present in RUV [database RUV]

<...several more samples...>

[22/Jan/2021:17:16:01 -0500] NSMMReplicationPlugin - replica_check_for_data_reload: Warning: for replica dc=example,dc=com there were some differences between the changelog max RUV and the database RUV. If there are obsolete elements in the database RUV, you should remove them using the CLEANALLRUV task. If they are not obsolete, you should check their status to see why there are no changes from those servers in the changelog.
请注意,哪些副本及其 ID;本例中,副本 8
当供应商从拓扑中永久删除时,应从其他供应商的 RUV 条目中清除有关该供应商的任何闲置元数据。使用 cleanallruv 目录任务从拓扑中的所有供应商中删除 RUV 条目。
注意
cleanallruv 任务被复制。因此,您只需要在一个供应商上运行它。

过程 15.1. 使用 cleanallruv 任务操作删除 Obsolete 或 Missing Supplier

  1. 列出所有 RUV 记录和副本 ID (有效且无效),因为删除的供应商可能在其他供应商上具有保留的元数据:
    # ldapsearch -o ldif-wrap=no -xLLL -H m1.example.com -D "cn=Directory Manager" -W -b dc=example,dc=com '(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))' nsDS5ReplicaId nsDS5ReplicaType nsds50ruv
    dn: cn=replica,cn=dc\3Dexample\2Cdc\3Dcom,cn=mapping tree,cn=config
    nsDS5ReplicaId: 1
    nsDS5ReplicaType: 3
    nsds50ruv: {replicageneration} 55d5093a000000010000
    nsds50ruv: {replica 1 ldap://m1.example.com:389} 55d57026000000010000 55d57275000000010000
    nsds50ruv: {replica 20 ldap://m2.example.com:389} 55e74b8c000000140000 55e74bf7000000140000
    nsds50ruv: {replica 9 ldap://m2.example.com:389}
    nsds50ruv: {replica 8 ldap://m2.example.com:389} 506f921f000000080000 50774211000500080000
    
    请注意返回的副本 ID: 1、 2098
  2. 通过在 cn=config 后缀下搜索副本配置条目 DN cn=replica,列出所有供应商的当前定义和有效的副本 ID。
    注意
    消费者和只读节点始终将副本 ID 设置为 65535nsDS5ReplicaType: 3 表示供应商。
    # ldapsearch -o ldif-wrap=no -xLLL -H m1.example.com m2.example.com -D "cn=Directory Manager" -W -b cn=config cn=replica nsDS5ReplicaId nsDS5ReplicaType
    dn: cn=replica,cn=dc\3Dexample\2Cdc\3Dcom,cn=mapping tree,cn=config
    nsDS5ReplicaId: 1
    nsDS5ReplicaType: 3
    
    dn: cn=replica,cn=dc\3Dexample\2Cdc\3Dcom,cn=mapping tree,cn=config
    nsDS5ReplicaId: 20
    nsDS5ReplicaType: 3
    
    在搜索第一步中返回的所有 URI 后(在此流程中,m1.example.comm2.example.com),比较返回的供应商列表(具有 nsDS5ReplicaType: 3)与上一步中的 RUV 列表。在上例中,此搜索仅返回 ID 120,但前面的搜索也会在 URI m2.example.com 上返回 98。这意味着,后者的两个被删除,需要清理其 RUV。
  3. 确定哪个 RUV 需要清理后,创建一个新的 cn=cleanallruv,cn=tasks,cn=config 条目,并提供有关复制配置的以下信息:
    • 复制数据库的基本 DN (replica-base-dn)
    • 副本 ID (副本 ID)
    • 是否要从缺少的供应商捕获到最大更改状态号(CSN),还是只删除所有 RUV 条目,并丢失任何更新(replica-force-cleaning);将此属性设置为 no 意味着任务将等待所有配置的副本,以首先从删除的副本中获得所有更改,然后删除 RUV。
    # dsconf -D "cn=Directory Manager" ldap://m2.example.com repl-tasks \
         cleanallruv --suffix="dc=example,dc=com" --replica-id=8
    注意
    cleanallruv 任务被复制。因此,您只需要在一个供应商上运行它。
    对您要清理的每个 RUV 重复相同的操作(此流程中的 ID 9 )。
  4. 清理之前发现的所有副本的 RUV 后,您可以使用第一步中的搜索来验证是否删除了所有额外的 RUV:
    # ldapsearch -o ldif-wrap=no -xLLL -H m1.example.com -D "cn=Directory Manager" -W -b dc=example,dc=com '(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))' nsDS5ReplicaId nsDS5ReplicaType nsds50ruv
    dn: cn=replica,cn=dc\3Dexample\2Cdc\3Dcom,cn=mapping tree,cn=config
    nsDS5ReplicaId: 1
    nsDS5ReplicaType: 3
    nsds50ruv: {replicageneration} 55d5093a000000010000
    nsds50ruv: {replica 1 ldap://m1.example.com:389} 55d57026000000010000 55d57275000000010000
    nsds50ruv: {replica 20 ldap://m2.example.com:389} 55e74b8c000000140000 55e74bf7000000140000
    
    如以上输出中显示的那样,副本 ID 89 不再存在,这表示其 RUV 已被成功清理。