【问题标题】:Cassandra UUID vs TimeUUID benefits and disadvantagesCassandra UUID 与 TimeUUID 的优缺点
【发布时间】:2013-07-30 12:29:21
【问题描述】:

鉴于 TimeUUID 允许您轻松地在 CQL 中使用 now(),您是否有任何理由不继续使用 TimeUUID 而不是普通的旧 UUID?

【问题讨论】:

    标签: cassandra uuid cql cql3 timeuuid


    【解决方案1】:

    UUIDTIMEUUID在Cassandra中的存储方式相同,它们只是真正代表了两种不同的排序实现。

    TIMEUUID 列首先按其时间分量排序,然后按其原始字节排序,而 UUID 列首先按其版本排序,然后如果两者都是版本 1,则按其时间分量排序,最后按其原始字节排序字节。奇怪的是,Cassandra 代码中的时间分量排序实现在 UUIDTypeTimeUUIDType 之间重复,但格式不同。

    我认为UUIDTIMEUUID 的问题主要是文档:如果您选择TIMEUUID,您是在说您按时间顺序存储内容,并且这些内容可以同时发生,所以一个简单的时间戳是不够的。使用 UUID 表示您不关心顺序(即使在实践中,如果您将版本 1 UUID 放入其中,列将按时间排序),您只想确保事物具有唯一的 ID。

    即使使用NOW() 生成UUID 值很方便,但阅读您的代码的其他人也很惊讶。

    在总体方案中可能无关紧要,但是对非版本 1 UUID 进行排序比版本 1 快一点,所以如果您有一个 UUID 列并自己生成 UUID,请选择另一个版本.

    【讨论】:

    • 排序非版本 1 UUID 的速度如何?例如,第 4 版 UUID 是完全随机的,我预计它会提供最差的排序性能。我同意这个问题应该无关紧要。如果您使用 UUID,您这样做有几个很好的理由,但性能不在其中。幸运的是,今天的计算机可以处理 UUID 提出的空间和分类需求。
    • UUID 的内容与排序算法的性能无关。非版本 1 在 Cassandra 中排序更快,因为不会将字节解包到时间戳中。这是一个非常非常小的差异,我只是觉得这很有趣。
    • now() 函数是生成timeuuid 的唯一方法吗?是否可以生成自定义的?它仅用于测试我需要自定义的。
    • 好问题皮诺曹。也许不是答案,但我知道有 minTimeuuid() 和 maxTimeuuid()。示例:插入时间 maxTimeuuid('2015-04-03 22:05+0000');
    • @Theo 当您说“您只想确保事物具有唯一 ID”时,您的意思是 timeuuid 可能不是唯一的吗?例如,我可以使用 timeuuid 作为分区键存储用户吗?
    【解决方案2】:

    TimeUUID 根据documentation,一个普通的旧UUID

    UUID 只是一个128-bit value 将其视为一个难以想象的大数字。

    可以通过几种方法中的任何一种来确定特定位。 original method 涉及获取计算机网络硬件的MAC address,结合当前日期和时间,加上任意数字和随机数字。将所有这些压缩在一起以获得几乎唯一的数字。

    后来,出于各种原因(安全、隐私),人们发明了其他方法来在生成 UUID 值时组装这些位。这些其他方法省略了日期时间和/或 MAC 地址作为成分。重点是:并非所有 UUID 值都具有嵌入的日期时间值。

    Cassandra 文档错误地将其 TimeUUID 称为“Type 1 UUID”。正确的术语是版本 1 UUID。这个版本有时被称为“基于时间的版本”。


    一点建议

    Cassandra 似乎识别出这个特定版本的 UUID 是为了提取 128 位的日期和时间部分。从 UUID 中提取日期时间是一个坏主意

    一方面,UUID 从未打算用于此类历史跟踪。实际上,UUID 的规范特别认识到 (a) 计算机时钟可以重置,因此 (b) 稍后生成的 UUID 可能实际上记录了比以前的 UUID 更早的日期时间。不从 UUID 中提取日期时间的另一个原因是,您很可能拥有不是由 time 方法生成的 UUID,因此您将基于实际上不代表日期时间的位构建数据时间值的创造。第三个原因是,当以后重构编程代码时,UUID 的生成时间可能与数据库记录不同,因此使用 UUID 的日期时间会产生误导。

    如果您需要跟踪日期时间历史记录,请明确执行。在您的数据中创建一个日期时间字段。顺便说一句,在 UTC 中跟踪那个日期时间,但这是另一个话题。

    【讨论】:

    • 作为记录,Cassandra doc 明确建议使用 ntp 跨所有节点同步系统时间。 datastax.com/documentation/cassandra/1.2/webhelp/cassandra/…
    • 同意使用 UTC。但要解决您的其他问题:1)时间戳也会受到时钟漂移的影响,因此在时间序列数据方面,它们并不比 TimeUUID 好。 2) 在 CQL3 和使用 TimeUUID 数据类型的 Cassandra 模式的上下文中,可以合理地预期这些列中的所有 UUID 都是时间编码的,类型 1 UUID。 3) 在 CQL3 中,您可以使用 NOW() 或特定日期时间在插入时创建 TimeUUID。因此,处理旧数据仍然可以在 Cassandra 表中生成历史上正确的 TimeUUID。
    • @platforms 将两个不同的目的合并为一个值在原则上是一个坏主意,也是一种不好的做法。在这种情况下,1. 日期时间历史跟踪和 2. 主键标识符。当您想要使用其他系统/源/接收器导出或导入数据的那一天到来时,您会后悔的。作为不必要的混淆的进一步证明,虽然没有得到任何回报,但请重新阅读此页面的问题!
    • 目前为止没有遗憾,对一个生产了一年多的系统,包括数据导出和导入。但我理解您的原则性论点,并同意可能会影响您意见的那种关注点分离的概念。在实践中,为了在 Cassandra 上索引时间序列数据,我发现 TimeUUID 的使用非常有用。但是,原则上,我会选择任何形式的 UUID 作为存储时间值的最佳方式吗?没有。
    • Cassandra 中的 TimeUUID 类型是一种元数据(与任何 Cassandra 类型一样),允许 Cassandra 知道如何解释数据(例如,获取日期并基于日期或现在创建 UUID)。如果您需要直接访问一行并列出按日期排序的行,使用它的好处是可以防止数据重复。它仅作为复合键才有意义。如果您有 2 个字段(日期和唯一 id),您将有一个表,其中日期在前,id 后(在复合键中)进行排序,第二个字段在前,日期在后(用于直接访问)。跨度>
    【解决方案3】:

    总而言之,你需要产生一些来相信它们。 Timeuuids 是版本/级别 1 UUID 似乎只随机化前 8 个字符,如下所示,因此,存在一些冲突的可能性,但仍然是 timeuuid is better than using timestamp 本身。如果 uuid 随机性很重要,使用版本/级别 4 UUID 是一个更好的选择,几乎是improbable collision

    因此,如果您不关心分区之间的唯一性,并且您的分区是具有高写入量的宽行时间序列数据,并且每个事件(时间)需要一些唯一标识符,那么它是一个不错的选择,它还具有聚类、分页等的好处。

    insert into test_tuuid(1, now())
    insert into test_tuuid(1, now())
    insert into test_tuuid(1, now())
    insert into test_tuuid(1, now())
    
    49cbda60-961b-11e8-9854-134d5b3f9cf8
    49d1a6c1-961b-11e8-9854-134d5b3f9cf8
    49d59e61-961b-11e8-9854-134d5b3f9cf8
    49d8d2b1-961b-11e8-9854-134d5b3f9cf8
    

    【讨论】:

    猜你喜欢
    • 2016-03-03
    • 2014-02-27
    • 1970-01-01
    • 2015-04-02
    • 2016-09-26
    • 2012-07-01
    • 2010-09-07
    • 2016-08-06
    • 2017-04-04
    相关资源
    最近更新 更多