CouchDB 2中的序列号错误还是有另一种方法来比较序列号?

时间:2017-06-09 00:26:04

标签: couchdb couchdb-2.0

我正在深入研究CouchDB 2,我发现了一些序列号的意外排序。在一个案例中,我发现_changes feed的早期更改具有序列号

99-g1AAAAI-eJyd0EsOgjAQBuAGiI-dN9C9LmrBwqzkJtrSNkgQV6z1JnoTvYneBEvbhA0aMU1mkj6-_NMSITTJfYFm2anOcsFT10mpTzyG-LxpmiL32eqoN8aEAcWE9dz_jPCFrnzrHGQchiFM4kSgaV0JqQ6VFF-AtAV2DggMgCEGxrNhQfatc3bOyDiKUalg2EBVoCu66KapazcUh41e69-GssjNIvcWWRokk2oNofwj0MNazy4QFURhGQ0J9LKI-SHPIBHEgiak51nxBhxnrRk

对于同一个数据库,我的_changes Feed中的最后一个序列号是

228-g1AAAAJFeJyd0EkOgjAUBuAGTJCdN9AjlIKFruQm2jFAEFes9SZ6E72J3gQ7JW7QCGnyXtLhy-vfAgCWVSjAip96XglW-o5afRJQwNbDMDRVSOuj3ogQJRgiOnL_O8I2urKdd4B1KCRpkRcCxH0npKo7KX4ApQH2HogsAElOKOPTBjkY5-yd2DqKYqnItA91C13BRTdNXY0VWouRrV7JDOvmrLuxlLW4VAlJ5Qzr4aznJ2wskIIy-y9sh7wcYoMKLJKRXOACjTxr3uHcsBE

在浏览器控制台中,以下内容为false

'228-g1AAAAJFeJyd0EkOgjAUBuAGTJCdN9AjlIKFruQm2jFAEFes9SZ6E72J3gQ7JW7QCGnyXtLhy-vfAgCWVSjAip96XglW-o5afRJQwNbDMDRVSOuj3ogQJRgiOnL_O8I2urKdd4B1KCRpkRcCxH0npKo7KX4ApQH2HogsAElOKOPTBjkY5-yd2DqKYqnItA91C13BRTdNXY0VWouRrV7JDOvmrLuxlLW4VAlJ5Qzr4aznJ2wskIIy-y9sh7wcYoMKLJKRXOACjTxr3uHcsBE' > '99-g1AAAAI-eJyd0EsOgjAQBuAGiI-dN9C9LmrBwqzkJtrSNkgQV6z1JnoTvYneBEvbhA0aMU1mkj6-_NMSITTJfYFm2anOcsFT10mpTzyG-LxpmiL32eqoN8aEAcWE9dz_jPCFrnzrHGQchiFM4kSgaV0JqQ6VFF-AtAV2DggMgCEGxrNhQfatc3bOyDiKUalg2EBVoCu66KapazcUh41e69-GssjNIvcWWRokk2oNofwj0MNazy4QFURhGQ0J9LKI-SHPIBHEgiak51nxBhxnrRk'

这是一个错误还是我需要使用其他方法来比较序列号?

在查看我的_changes Feed中的其他序列号时,看起来它们通常按照我的预期排序,但在这种情况下,看起来当第一个数字时,例如99,从2位跳到3位,排序中断。如果你把它归结为一个简单的字符串比较示例,你可以看到'228'> '99'=>假

1 个答案:

答案 0 :(得分:3)

以下答案包含来自@rnewson的电子邮件主题的摘录。我希望能帮助其他人理解CouchDB 2中的序列号。谢谢,罗伯特!

背景:

  

在2.0中没有简单的方法来比较它们,也没有对它们的要求   要井然有序。简而言之,它们不是为了检查而设计的   在couchdb之外比较;不透明地对待它们。

     

前面的数字是各个更新序列的总和   在第二部分编码,只存在于旧版本的旧版本   couchdb复制器进入检查站。

     

序列字符串的后半部分是{node,   range,seq}元组(其中seq是你知道的整数值   2.0之前的版本)。当一个序列字符串被传回时,作为   因为=参数,couchdb解码此字符串并传递   适当的整数seq值到单个分片。

     

总而言之,前面的数字应该会增加。满满的   字符串本身不具有可比性,因为没有定义的顺序   到编码列表(因此可以生成两个字符串   编码不同但解码到相同的元组列表,只是在一个   不同的顺序)。

     

另一个方面是改变饲料并非完全   订购。对于给定的分片, 完全有序(分片为。)   与具有整数序列的pre 2.0数据库相同),couchdb   不会改变那个输出(虽然复制的正确性会   保留,如果它确实)。集群数据库由几个组成   但是碎片('q'值,默认为4 iirc)。聚集的   更改Feed将这些单独的更改组合成一个,   但没有努力对此施加总命令。我们不这样做   因为它既昂贵又不必要。

解决方案,如果您需要侦听_changes Feed然后重新启动 从你以后离开的地方开始:

  

正确使用更改Feed的算法是:

     
      
  1. read / dbname / _changes
  2.   
  3. 理所当然地处理每一行
  4.   
  5. 定期(每X秒或每X行)存储您处理的最后一行的“seq”值
  6.         

    如果你遇到崩溃,或者你没有使用continuous = true,你可以这样做   同样的程序,但在步骤1中进行了修改;

         

    修订1.读/ dbname / _changes?since = X

         

    其中X是您在步骤3中保存的值。如果您不使用   连续模式然后你可以只记录“last_seq”值   消耗不连续响应的结束。你冒的风险   但是,要重新处理更多的物品。

         

    通过这个方案(复制者和所有索引者都遵循),你   不关心结果是否有问题,你不需要比较   任何两个seq值。

         

    需要确保您可以正确处理相同的更改   多次。举个例子,考虑复制器,何时   它从更改提要中看到一行,它会询问目标数据库是否存在   包含该行的_id和_rev值。如果确实如此,那就是   复制器移动到下一行。如果没有,它会尝试写   该行中的文档到目标数据库。如果是   崩溃,因此使用之前的seq值调用_changes   处理该行时,它会询问目标数据库是否有   再次_id / _rev,只有这次目标会说是。