如何在Cassandra中创建自动增量ID

时间:2010-10-14 17:38:38

标签: cassandra

我们知道在SQL数据库中创建自动增量ID很容易,在Cassandra中有一个很好的解决方案吗? ID应该是键名或列名。

8 个答案:

答案 0 :(得分:33)

在分布式系统中创建数字的全局顺序序列并没有任何意义。使用UUIDs

(因为你必须让所有参与者同意并接受序列的演变 - 在一个天真的实现下)

答案 1 :(得分:33)

使用Cassandra的Lightweight transactions

,以下内容如何

1 - 创建ID表:

CREATE TABLE ids (
  id_name varchar,
  next_id int,
  PRIMARY KEY (id_name)
)

2 - 插入您想要使用

的全局序列的每个id

例如:

INSERT INTO ids (id_name, next_id)
VALUES ('person_id', 1)

3 - 然后,当您插入要使用自动递增密钥的表时,请执行以下操作:

3.1 - 从ids表中获取next_id:

SELECT next_id FROM ids WHERE id_name = 'person_id'

假设结果是next_id = 1

3.2 - 增加next_id,方法如下:

UPDATE ids SET next_id = 2 WHERE id_name = 'person_id' IF next_id = 1

结果应如下所示:

[{[applied]: True}]

如果成功更新,或者

[{[applied]: False, next_id: 2}]

如果其他人已经更新了它。

所以,如果你得到True,请使用id'1' - 它是你的。否则,递增next_id(或只使用返回的next_id)并重复该过程。

答案 2 :(得分:15)

没有好的解决方案。

  1. 创建一个带有数字的列,增加数字并将其与临时ID一起保存到所有副本,读取所有副本并检查临时ID是否为“你的”,如果不再这样做...不是一个很好的解决方案并且不会扩展。
    1. 建立您自己的ID服务,您可以在其中获取下一个ID。此服务只能在单个实例中运行,并且是一个非缩放的可怕因素。
    2. 只要有任何事情超出单个实例,id的排序就会变得复杂,至少如果你想要它的扩展。这包括关系数据库。

答案 3 :(得分:5)

有一个可以使用的计数器数据类型。请考虑以下示例。

CREATE KEYSPACE counterks WITH REPLICATION =
{ 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3 };

为计数器列创建一个表。

CREATE TABLE counterks.page_view_counts
(counter_value counter,
url_name varchar,
page_name varchar,
PRIMARY KEY (url_name, page_name)
);

将数据加载到计数器列中。

UPDATE counterks.page_view_counts
SET counter_value = counter_value + 1
WHERE url_name='www.datastax.com' AND page_name='home';

查看计数器值。

SELECT * FROM counterks.page_view_counts;

输出是:

 url_name         | page_name | counter_value
------------------+-----------+---------------
 www.datastax.com |      home |             1

增加柜台的价值。

 UPDATE counterks.page_view_counts
 SET counter_value = counter_value + 2
 WHERE url_name='www.datastax.com' AND page_name='home';

查看计数器值。

 url_name         | page_name | counter_value
------------------+-----------+---------------
www.datastax.com |      home |             3  

有关详细信息,请参阅此处:http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_counter_t.html

答案 4 :(得分:3)

这个问题很老了,但我想用其他解决方案来完成它。

依赖于节点同步的任何解决方案都是不合理的。通过阻止ID生成或创建重复的ID,可以肯定地打破它。

MySQL方式

您可以使用auto_increment_incrementauto_increment_offset参数重现mysql主 - 主复制的方式。

要重现它,您需要知道节点数或预期节点的最大数量,并且需要在每个节点上创建一个(非cassandra)计数器(每个示例的文件)。

每次要生成新数字时,都会找到当前值,添加增量并保存。如果它还不存在,那就是偏移量。

因此,对于10个节点,第一个节点的增量为10,偏移量为1,第二个节点的偏移量为2,等等。节点1将创建ID 1,11,21。节点2将创建ID 2,21,22。

如果您希望在节点之间(近似地)订购ID,则需要维护共享计数器并确保每个生成的ID都高于共享计数器。这样,除非您的节点/数据中心长时间不同步,否则您不会发现太大的差异。

加前缀

您可以通过在节点号(或名称)前面添加ID(如果它是可接受的解决方案)来做同样的事情。而且您不必知道节点数量。 节点1将创建1_1,1_2,1_3。节点2将创建2_1,2_2,2_3。

答案 5 :(得分:2)

编辑:此解决方案不正确。请参阅第一条评论。

我的解决方案:

1 - 创建ID表:

CREATE TABLE ids (
  id_name varchar,
  next_id counter,
  PRIMARY KEY (id_name)
)

2 - 当您要插入要使用自动递增键的表格时,请执行以下操作:

2.1 - 增量计数器(如果不存在,将创建它),使用最高一致性级别

UPDATE ids
  SET next_id = next_id + 1
  WHERE id_name = $AUTO_INCREMENTED_ID
  USING CONSISTENCY ALL

2.2 - 获取新的id值:

SELECT next_id
  FROM ids
  WHERE id_name = $AUTO_INCREMENTED_ID

2.3 - 使用自动增加的id插入值

INSERT INTO some_table ($AUTO_INCREMENTED_ID, ...)
  VALUES ($RESULT_FROM_PREVIOUS_QUERY, ...)

在我的回答中以'$'开头的单词是不言自明的(我希望)占位符......

当然这不是推荐的方法。只有在必要时才使用它。

答案 6 :(得分:2)

我认为恕我直言,期待Cassandra提供一个自动递增字段是错误的

Cassandra是一个优雅的分散数据库,因此期望它提供一个自动填充字段,使得最初的目的很费力,因为这个值必须保持在一个中心位置

因此,不要制作任何基于DB的解决方案来获得自动递增数

而是在您的应用中的代码或服务中生成ID,这可以保持生成随机唯一ID并使用它来应用于您的数据模型,这样就可以实现目标&卡桑德拉的好处不会被打败

答案 7 :(得分:1)

他们真的是否需要顺序,或者你只需​​要计算比人们容易输入的UUID小得多的数字吗?

如果您确实需要序号,则需要执行以下操作之一。

  • 在cassandra中有一个表,其中key / id是生成器的字段,值是一个数字...在循环中进行条件更新,直到成功递增计数。 (坏主意)

  • 有一个生成器服务,可以为您提供下一个号码。这只能在单个系统上运行并且是单点故障,但根据您的需要,这可能是最好的。

或者......类似于第一个,但是一次获得100个左右的批次,并在你的进程/线程中处理这些...这将争用较少,但不保证顺序,只是唯一性...如果您只想要更短的数字来展示,这可能是您最好的选择。