使用 cassandra 的 python 驱动程序创建新记录时如何设置服务器端时间戳

Posted

技术标签:

【中文标题】使用 cassandra 的 python 驱动程序创建新记录时如何设置服务器端时间戳【英文标题】:How to set serverside timestamp when create new record using python driver for cassandra 【发布时间】:2017-05-29 04:39:08 【问题描述】:

我有cassandra 模型如下。

from uuid import uuid4
from uuid import uuid1

from cassandra.cqlengine import columns, connection
from cassandra.cqlengine.models import Model
from cassandra.cqlengine.management import sync_table


class BaseModel(Model):
    __abstract__ = True

    id = columns.UUID(primary_key=True, default=uuid4)
    created_timestamp = columns.TimeUUID(primary_key=True,
                                         clustering_order='DESC',
                                         default=uuid1)
    deleted = columns.Boolean(required=True, default=False)

class OtherModel(BaseModel):
    __table_name__ = 'other_table'
    name = columns.Text(required=True, default='')



if __name__ == '__main__':
    connection.setup(hosts=['localhost'],
                     default_keyspace='test')
    sync_table(OtherModel)

    OtherModel.create(id='d43ca2c3-b670-4efc-afd7-b46ada88c3fc', name='test')

当我创建记录时,它设置了我的系统的created_timestamp 或我执行此代码的位置。

我的系统和cassandra 服务器的时间戳不同。

如果我在系统时间为2017-01-13 10:20:30 的情况下执行此操作,那么它将时间戳设置为相同。如果我再次从另一个系统执行相同的操作,其中timestamp2017-01-13 10:20:20,那么它设置相同。

当我像这样运行查询时

select * from test.other_table where id=d43ca2c3-b670-4efc-afd7-b46ada88c3fc limit 1;

它应该返回最后插入的latest(last) 记录,但由于系统时间戳与我插入记录的位置不同,它给出了最先插入的第一条记录。

【问题讨论】:

【参考方案1】:

以上python代码创建的架构是:

CREATE TABLE test.other_table (
    id uuid,
    created_timestamp timeuuid,
    deleted boolean,
    name text,
    PRIMARY KEY (id, created_timestamp)
) WITH CLUSTERING ORDER BY (created_timestamp DESC)

在您的示例中,created_timestamp 是主键的组成部分,因此表中将有两个不同的行 10:20:30 和 10:20:20。将 order 设置为 DESC,您的读取查询将按排序顺序返回值,最大的在前或 2017-01-13 10:20:30。插入行的顺序无关紧要,因为 created_timestamp 是一个聚类列。

如果 created_timestamp 不是主键的一部分,那么 Cassandra 将只返回最新的值。 Cassandra 有一个由协调器生成的内部单元格时间戳,它确定何时插入或更新单元格。 Cassandra 的合并过程在读取请求期间使用它来确定最后插入的值。您不能从客户端代码中设置此项,但您可以使用 CQL writetime() 函数查看 upsert 时间。

例如,

select id, dateOf(created_timestamp), writetime(name) from other_table;

将返回:

 id                                   | system.dateof(created_timestamp) | writetime(name)
--------------------------------------+----------------------------------+------------------
 d43ca2c3-b670-4efc-afd7-b46ada88c3fc |         2017-01-14 23:09:08+0000 | 1484435348108365
 d43ca2c3-b670-4efc-afd7-b46ada88c3fc |         2017-01-14 23:07:30+0000 | 1484435250481046

如果您希望使用协调器的时间戳,则必须使用 CQL 语句而不是对象映射器:

import uuid
from cassandra.cluster import Cluster

cluster = Cluster()
session = cluster.connect("test")

stmt = session.prepare(
"""
    INSERT INTO test.other_table (id,created_timestamp) VALUES (?,now());
"""
)
session.execute(stmt,[uuid.uuid4()])

【讨论】:

感谢您的回答,但我无法更改我的型号,我必须使用与created_timestamp 相同的型号作为clustering_order=DESC 如果您可以选择在创建记录时设置服务器时间,这对我很有帮助。 您可以使用 python 中的 CQL 执行此操作,但不能使用对象映射器。 意思是,在python中,我们不能使用cassandra函数来添加数据? 您可以在 python 中使用 CQL 中的“现在”,请参阅上面的编辑。

以上是关于使用 cassandra 的 python 驱动程序创建新记录时如何设置服务器端时间戳的主要内容,如果未能解决你的问题,请参考以下文章

Cassandra python 驱动程序 - 使用对象映射器冻结

无法使用最新的 datastax python 驱动程序扩展 cassandra

Windows上的Python 3中的Cassandra驱动器安装失败

使用 cassandra 的 python 驱动程序创建新记录时如何设置服务器端时间戳

如何从 python cassandra 驱动程序传递 cassandra 函数?

python cql 驱动程序 - cassandra.ReadTimeout -“操作超时 - 仅收到 1 个响应。”