反对唯一性的更好选择?

时间:2016-09-21 07:53:45

标签: cassandra data-modeling

我目前有基本用户事件表的以下表格布局:

CREATE TABLE IF NOT EXISTS events.events_by_user(
    user text,
    added_week int,
    added_timestamp timestamp,
    event text,
    uuid uuid,
    PRIMARY KEY((user, added_week), added_timestamp, event, uuid))
WITH CLUSTERING ORDER BY(added_timestamp DESC)

因此,uuid作为主键的最后一列基本上保证了唯一性。同一用户的几个相同事件有可能在相同的毫秒(时间戳)中发生。

另一种方法可能是(如果我没有记错的话),删除uuid列并将其替换为计数器列,如下所示:

CREATE TABLE IF NOT EXISTS events.events_by_user(
    user text,
    added_week int,
    added_timestamp timestamp,
    event text,
    frequency counter,
    PRIMARY KEY((user, added_week), added_timestamp, event))
WITH CLUSTERING ORDER BY(added_timestamp DESC)

我的想法是,我可以通过使用这个计数器节省一些空间,而且我的行也不会扩大太多。我不确定,如果这可能有其他性能影响维持这个反击,或者是否有任何其他原因为什么这可能不是一个好主意?

1 个答案:

答案 0 :(得分:1)

为什么要使用计数器节省空间? C *设计习惯用于使用空间来获得效率。

回到你的问题,计数器对你可以做的事情有很大限制,例如必须在他们自己的表上使用,你可以在那里拥有你想要的主键数量,然后只有计数器列。它们仅支持递增和递减操作,并且由于它们支持这两个操作,因此每个查询都不是幂等的。如果你可以忍受“计数”值的不准确......(即使C * 2.1+稍微减轻了这一点,过度计数也是一个众所周知的问题)

这意味着您无法指定event列,因为它不属于您的主键,因此您的设计无效。

回到您的唯一性要求,您可以使用timeuuid列类型。它们是基于时间的Type 1 UUID,并提供了相当低的冲突概率。来自Cassandra wiki

  

Type 1 UUID包含以下内容:

     
      
  • 一个时间戳,由100纳秒间隔组成   1582年10月15日00:00:00.00(格列高利改革之日)   基督教历法)。

  •   
  • 版本(值应为1)。

  •   
  • 变体(值应为2)。

  •   
  • 序列号,可以是计数器或伪随机数。

  •   
  • 将成为的“节点”   机器MAC地址(应该使UUID唯一   机)。

  •   
     

使用UUID的挑战是使其独一无二   在单个机器和多个线程上运行的多个进程   在一个过程中运行。上面指定的Type 1 UUID可以   都不是。在具有多个内核的快速机器上,很有可能   生成具有相同时间值的UUID。这可以解决   只有当序列号可以跨越线程和进程时才会出现问题   这是非常具有挑战性的。

     

引用的基于时间的UUID通过以下方式补偿这些问题:

     
      
  • 仅使用返回的正常毫秒粒度   System.currentTimeMillis()并将其调整为假装包含100   ns计数。

  •   
  • 将时间增加1(以非线程安全的方式)   每当遇到重复的时间值时。

  •   
  • 使用伪随机   与序列号的UUID类关联的数字。   将时间增加1允许多个线程唯一地创建   在相同的过程中,在相同的毫秒内最多10,000个UUID。运用   序列号的伪随机数在a中提供1   每个UUID类有16,384个机会具有唯一ID。

  •   
     

这些机制提供了生成的合理概率   UUID将是独一无二的。但是,需要注意的问题是:

     
      
  • 计算机每台可生成超过10,000个UUID   微秒。

  •   
  • 在不同线程上创建UUID的应用程序可以   得到重复,因为时间不会在线程安全中增加   方式。

  •   
  • 该类的多个实例在VM中的位置不同   类加载器 - 每个具有自己的类都可以减轻这种情况   序列号。

  •   
  • 无法保证UUID的两个实例   相同或不同的VM将具有不同的序列号 - 只是   他们会有合理的概率。

  •   

在实践中,C *已经做了你想做的事。但是,如果你真的担心你最终会重复,那么你需要自己进行适当的计算,我建议你在应用程序级别实现它。