我们知道在SQL数据库中创建自动增量ID很容易,在Cassandra中有一个很好的解决方案吗? ID应该是键名或列名。
答案 0 :(得分:33)
在分布式系统中创建数字的全局顺序序列并没有任何意义。使用UUIDs。
(因为你必须让所有参与者同意并接受序列的演变 - 在一个天真的实现下)
答案 1 :(得分:33)
使用Cassandra的Lightweight transactions
,以下内容如何CREATE TABLE ids (
id_name varchar,
next_id int,
PRIMARY KEY (id_name)
)
例如:
INSERT INTO ids (id_name, next_id)
VALUES ('person_id', 1)
SELECT next_id FROM ids WHERE id_name = 'person_id'
假设结果是next_id = 1
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)
没有好的解决方案。
或
只要有任何事情超出单个实例,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,可以肯定地打破它。
您可以使用auto_increment_increment
和auto_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个左右的批次,并在你的进程/线程中处理这些...这将争用较少,但不保证顺序,只是唯一性...如果您只想要更短的数字来展示,这可能是您最好的选择。