Cassandra数据结构
1. Cassandra Terminology
- 列(column): 一个对象的名/值对(name/value pair).
- 行(row): 存放列的容器(一组关联的列归为一组),由一个主键引用/标识。
- 每一行的唯一标识称为主键(primary key)行键(row key)
- 分区(partition): 将一组相关的行进行分组,一起存储在相同的节点上。
- 这些相关的行就组成一个分区,
每个分区由一个分区键标识
。 - 这时的主键比较特殊,称为复合键(composite key)或者组合键(compound key).
- 复合键由一个
分区键(partition key)
和一组可选的集群列(clustering column)
组成。- 分区键确定行存储在哪个节点,可以包含多个列。
- 集群列用于控制分区中数据如何排序与存储。
- 静态列(static column): 存储不属于主键但是由一个分区中所有行共享的数据。
- 这些相关的行就组成一个分区,
- 表(table): 按分区组织的行的容器。
- 键空间(keyspace): 按表组织的容器。
- 集群(cluster): 键空间的容器,包括一个节点或者多个节点。
主键”永恒“: 表创建完成后,主键就不能修改,因为主键会控制集群中数据如何分布,数据如何在不同的节点磁盘上存储。
2. Cassandra数据组织结构图示
3. 其他
- 集群(cluster): 多个节点共同协作,最终用户看来,所有节点表现就像一个实例。Cassandra集群有时也叫做环(ring),因为Cassandra将所有的节点组织成一个环,并依次将数据分配到节点上。
- 键空间:类似于关系数据库中的数据库(database),是Cassandra数据模型中标的容器。键空间有一个名字,也有一组属性定义键空间范围的行为,如replica。键空间的容器是集群。
- 表:表也是一个容器,包含一个
有序的行集合
,每一行本身则是一个有序的列集合
。- 行按
分区组织
,根据分区键的列(可能有多个)分配到Cassandra集群中的节点。 - 一个分区中数据的顺序由
集群列
确定。
向表中写入数据时,可以为一列或多列指定值,值的集合称为一行。
主键中包含的列,必须为其中的每一个列都指定值,因为要用它们一起来唯一标识一行数据。 - 行按
- 列: 列是Cassandra数据模型中最基本的数据结构单元,包含一个name/value对。每个列的值根据定义时的数据类型设定对应值。列还包含如下两个属性:
- 时间戳(timestamp): 每次向Cassandra写入数据时,会为插入或者更新的各个列值生成一个时间戳(单位是微秒)。如果多个写操作试图修改同一个值,Cassandra内部使用”最后写获胜(last write wins)“来解决冲突。可以使用
writetime()
函数查看列值的写入时间。cqlsh:my_space> select first_name, last_name, writetime(title) from user; first_name | last_name | writetime(title) ------------+-----------+------------------ Bill | Nguyen | 1722158562120950 (1 rows) cqlsh:my_space>
- 生存时间(TTL): Cassandra提供了一个非常强大的特性,能够让不需要的数据自动过期。可以为列值(
列这一级进行操作
)设置生存时间(TTL, time to live),指示这个值需要保存多久。- TTL默认值为null,标识写入数据不会过期。
- 可以使用TTL()函数查看列值有些时间。
- UPDATE时增加USING TTL选项,可以在UPDATE操作时设置列的TTL。
- INSERT时增加USING TTL选项,整行数据在TTL之后都会过期,数据会被删除。
- INSERT时未设置TTL,UPDATE时不能对整行设置TTL,因为TTL是基于列级别。可能的方式使用upsert(对于已经存在的主键行,使用INSERT语句执行UPDATE操作)。
主键不允许设置TTL,也不能通过writetime()查看写入时间。
upsert操作为行设置TTLcqlsh:my_space> select writetime(first_name) from user; InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot use selection function writetime on PRIMARY KEY part first_name" cqlsh:my_space>
# 插入时未设置row的TTL cqlsh:my_space> insert into user (first_name, last_name, title) values ('Jim', 'Green', 'Mr.'); cqlsh:my_space> cqlsh:my_space> cqlsh:my_space> select * from user; last_name | first_name | title -----------+------------+------- Green | Jim | Mr. Nguyen | Bill | Mr. (2 rows) #查询结果显示TTL为null cqlsh:my_space> select last_name, first_name, ttl(title) from user; last_name | first_name | ttl(title) -----------+------------+------------ Green | Jim | null Nguyen | Bill | null (2 rows) # upsert方式:insert操作使用同样的primary key,实际执行的是update操作,同时为行设置了TTL cqlsh:my_space> insert into user (first_name, last_name, title) values ('Jim', 'Green', 'Mr.') USING TTL 100; cqlsh:my_space> cqlsh:my_space> # 立马查询可以看到TTL行有97秒 cqlsh:my_space> select last_name, first_name, ttl(title) from user; last_name | first_name | ttl(title) -----------+------------+------------ Green | Jim | 97 Nguyen | Bill | null (2 rows) #一段时间后查询,数据已经被删除。 cqlsh:my_space> select last_name, first_name, ttl(title) from user; last_name | first_name | ttl(title) -----------+------------+------------ Nguyen | Bill | null (1 rows) cqlsh:my_space>
- 时间戳(timestamp): 每次向Cassandra写入数据时,会为插入或者更新的各个列值生成一个时间戳(单位是微秒)。如果多个写操作试图修改同一个值,Cassandra内部使用”最后写获胜(last write wins)“来解决冲突。可以使用