Cassandra教程FG004-Cassandra Keyspace与表设计实战
本文档风哥主要介绍Cassandra数据库Keyspace与表设计实战,包括Keyspace概念、表概念、设计原则、Keyspace规划、表规划、副本策略规划、Keyspace创建、表创建、表修改、用户表设计实战、订单表设计实战、日志表设计实战等内容,风哥教程参考Cassandra官方文档Data Modeling内容编写,适合DBA人员和开发人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 Cassandra数据库Keyspace概念
Keyspace是Cassandra数据库中最顶层的命名空间,类似于关系型数据库中的数据库(Database)概念。Keyspace定义了数据的副本策略和副本因子,一个Keyspace可以包含多个表(Table)。更多视频教程www.fgedu.net.cn
1.1.1 Cassandra数据库Keyspace特点
# 1. 命名空间
Keyspace是表的容器,用于组织相关表
# 2. 副本策略
定义数据如何在集群中复制
# 3. 副本因子
定义每条数据保存多少个副本
# 4. 持久化配置
定义是否启用提交日志
# Keyspace与关系型数据库对比
Cassandra Keyspace ≈ MySQL Database
Cassandra Table ≈ MySQL Table
# Keyspace命名规范
– 使用小写字母
– 使用下划线分隔单词
– 名称长度不超过48个字符
– 以字母开头
– 示例: fgedudb, fgedu_user_db, fgedu_order_db
1.1.2 Cassandra数据库Keyspace属性
# 1. replication(副本策略)
定义数据复制方式
– class: 副本策略类
– replication_factor: 副本因子
# 2. durable_writes(持久化写入)
是否启用提交日志
– true: 启用(默认)
– false: 禁用
# 副本策略类型
# SimpleStrategy
适用场景: 单数据中心
配置方式: {‘class’: ‘SimpleStrategy’, ‘replication_factor’: 3}
# NetworkTopologyStrategy
适用场景: 多数据中心
配置方式: {‘class’: ‘NetworkTopologyStrategy’, ‘dc1’: 3, ‘dc2’: 2}
# 副本因子选择建议
开发环境: 1
测试环境: 2
生产环境: 3(推荐)
1.2 Cassandra数据库表概念
Table是Cassandra数据库中存储数据的基本单元,类似于关系型数据库中的表。Cassandra表采用宽列存储模型,每行可以有不同的列集合。
1.2.1 Cassandra数据库表特点
# 1. 宽列存储
每行可以有不同的列集合
列可以动态添加
# 2. 主键设计
主键决定数据分布和排序
主键 = 分区键 + 聚簇键(可选)
# 3. 查询驱动设计
表设计基于查询需求
一个查询一个表的设计理念
# 4. 无连接查询
不支持JOIN操作
需要通过反规范化解决
# 表命名规范
– 使用小写字母
– 使用下划线分隔单词
– 名称长度不超过48个字符
– 以字母开头
– 示例: fgedu_users, fgedu_orders, fgedu_logs
1.2.2 Cassandra数据库主键类型
# 1. 简单主键
PRIMARY KEY (partition_key)
示例: PRIMARY KEY (user_id)
# 2. 复合主键
PRIMARY KEY (partition_key, clustering_key)
示例: PRIMARY KEY (user_id, order_time)
# 3. 复合分区键
PRIMARY KEY ((partition_key1, partition_key2), clustering_key)
示例: PRIMARY KEY ((user_id, order_date), order_time)
# 主键组成
分区键(Partition Key):
– 决定数据存储在哪个节点
– 通过哈希函数计算分区位置
– 相同分区键的数据存储在同一分区
聚簇键(Clustering Key):
– 决定分区内的数据排序
– 支持范围查询
– 可以有多个聚簇键
# 主键设计原则
– 分区键应具有高基数
– 避免热点分区
– 聚簇键支持查询排序需求
1.3 Cassandra数据库设计原则
Cassandra数据库设计原则与关系型数据库有本质区别,需要遵循查询驱动设计理念。
1.3.1 Cassandra数据库设计原则说明
# 1. 查询驱动设计
根据查询需求设计表结构
一个查询一个表
# 2. 反规范化
允许数据冗余
避免连接查询
# 3. 分区键设计
选择高基数列作为分区键
避免数据倾斜和热点
# 4. 聚簇键设计
根据查询排序需求设计
支持范围查询
# 5. 数据类型选择
选择合适的数据类型
考虑存储效率和查询性能
# 6. TTL使用
设置合理的数据过期时间
自动清理过期数据
# 设计流程
1. 分析业务需求
2. 确定查询模式
3. 设计表结构
4. 选择数据类型
5. 确定主键
6. 配置压缩策略
7. 测试验证
Part02-生产环境规划与建议
2.1 Cassandra数据库Keyspace规划
Cassandra数据库Keyspace规划建议:
2.1.1 Cassandra数据库Keyspace规划原则
# 1. 按业务域划分
每个业务域创建独立Keyspace
示例:
– fgedu_user_db: 用户相关表
– fgedu_order_db: 订单相关表
– fgedu_log_db: 日志相关表
# 2. 按环境划分
不同环境使用不同Keyspace
示例:
– fgedu_user_db_dev: 开发环境
– fgedu_user_db_test: 测试环境
– fgedu_user_db_prod: 生产环境
# 3. 按数据敏感度划分
敏感数据独立Keyspace
示例:
– fgedu_user_db: 用户数据
– fgedu_sensitive_db: 敏感数据
# 4. 副本策略选择
单数据中心: SimpleStrategy
多数据中心: NetworkTopologyStrategy
# 5. 副本因子选择
生产环境: 3(推荐)
测试环境: 2
开发环境: 1
2.1.2 Cassandra数据库Keyspace规划示例
# 用户业务Keyspace
CREATE KEYSPACE fgedu_user_db
WITH replication = {
‘class’: ‘NetworkTopologyStrategy’,
‘dc1’: 3,
‘dc2’: 2
}
AND durable_writes = true;
# 订单业务Keyspace
CREATE KEYSPACE fgedu_order_db
WITH replication = {
‘class’: ‘NetworkTopologyStrategy’,
‘dc1’: 3,
‘dc2’: 2
}
AND durable_writes = true;
# 日志业务Keyspace
CREATE KEYSPACE fgedu_log_db
WITH replication = {
‘class’: ‘NetworkTopologyStrategy’,
‘dc1’: 3
}
AND durable_writes = true;
# 缓存业务Keyspace(可禁用提交日志)
CREATE KEYSPACE fgedu_cache_db
WITH replication = {
‘class’: ‘SimpleStrategy’,
‘replication_factor’: 3
}
AND durable_writes = false;
2.2 Cassandra数据库表规划
Cassandra数据库表规划建议:
2.2.1 Cassandra数据库表规划原则
# 1. 查询驱动
根据查询需求设计表
避免复杂查询
# 2. 主键设计
分区键: 高基数,均匀分布
聚簇键: 支持排序和范围查询
# 3. 数据类型
选择合适的数据类型
考虑存储和查询效率
# 4. 压缩策略
根据数据特点选择压缩策略
– SizeTieredCompactionStrategy: 默认,适合写入密集
– LeveledCompactionStrategy: 适合读密集
– DateTieredCompactionStrategy: 适合时序数据
# 5. 压缩配置
启用数据压缩节省存储空间
推荐LZ4或ZSTD
# 6. GC Grace配置
设置合理的gc_grace_seconds
默认864000秒(10天)
# 表设计检查项
[ ] 主键是否合理
[ ] 分区键是否均匀分布
[ ] 是否存在热点分区
[ ] 数据类型是否合适
[ ] 压缩策略是否合理
[ ] 是否需要TTL
2.2.2 Cassandra数据库表命名规范
# 命名规则
1. 使用小写字母
2. 使用下划线分隔单词
3. 名称长度不超过48个字符
4. 以字母开头
5. 避免使用CQL保留字
# 命名示例
用户表: fgedu_users
订单表: fgedu_orders
订单明细表: fgedu_order_items
日志表: fgedu_logs
会话表: fgedu_sessions
# 按功能命名
用户按ID查询表: fgedu_users_by_id
用户按邮箱查询表: fgedu_users_by_email
订单按用户查询表: fgedu_orders_by_user
# 反规范化命名
用户订单汇总表: fgedu_user_order_summary
商品销量统计表: fgedu_product_sales_stats
2.3 Cassandra数据库副本策略规划
Cassandra数据库副本策略规划建议:
2.3.1 Cassandra数据库副本策略选择
# SimpleStrategy
适用场景:
– 单数据中心
– 开发测试环境
– 简单部署场景
特点:
– 按顺时针方向放置副本
– 不考虑机架拓扑
– 配置简单
配置示例:
CREATE KEYSPACE fgedudb
WITH replication = {
‘class’: ‘SimpleStrategy’,
‘replication_factor’: 3
};
# NetworkTopologyStrategy
适用场景:
– 多数据中心
– 生产环境
– 需要机架感知的场景
特点:
– 按数据中心配置副本数
– 考虑机架拓扑
– 支持跨数据中心容灾
配置示例:
CREATE KEYSPACE fgedudb
WITH replication = {
‘class’: ‘NetworkTopologyStrategy’,
‘dc1’: 3,
‘dc2’: 2
};
# 副本因子选择建议
RF=1: 数据丢失风险高,不建议生产使用
RF=2: 可容忍1个节点故障
RF=3: 可容忍1个节点故障(推荐生产使用)
RF=5: 可容忍2个节点故障,高可用场景
Part03-生产环境项目实施方案
3.1 Cassandra数据库Keyspace创建
Cassandra数据库Keyspace创建实战:
3.1.1 Cassandra数据库创建Keyspace
# cqlsh 192.168.1.101 9042 -u fgedu -p Fgedu@2024
Connected to fgedu_cluster at 192.168.1.101:9042
[cqlsh 6.8.0 | Cassandra 4.1.0 | CQL spec 3.4.5 | Native protocol v5]
Use HELP for help.
# 创建Keyspace(SimpleStrategy)
cqlsh> CREATE KEYSPACE fgedudb
… WITH replication = {
… ‘class’: ‘SimpleStrategy’,
… ‘replication_factor’: 3
… }
… AND durable_writes = true;
# 创建Keyspace(NetworkTopologyStrategy)
cqlsh> CREATE KEYSPACE fgedu_order_db
… WITH replication = {
… ‘class’: ‘NetworkTopologyStrategy’,
… ‘dc1’: 3,
… ‘dc2’: 2
… }
… AND durable_writes = true;
# 查看Keyspace
cqlsh> DESCRIBE KEYSPACES;
fgedudb fgedu_order_db system system_auth system_distributed system_schema system_traces
# 查看Keyspace详情
cqlsh> DESCRIBE KEYSPACE fgedudb;
CREATE KEYSPACE fgedudb WITH replication = {‘class’: ‘SimpleStrategy’, ‘replication_factor’: ‘3’} AND durable_writes = true;
# 切换到Keyspace
cqlsh> USE fgedudb;
cqlsh:fgedudb>
3.1.2 Cassandra数据库修改Keyspace
cqlsh:fgedudb> ALTER KEYSPACE fgedudb
… WITH replication = {
… ‘class’: ‘NetworkTopologyStrategy’,
… ‘dc1’: 3
… };
# 修改Keyspace持久化配置
cqlsh:fgedudb> ALTER KEYSPACE fgedudb
… WITH durable_writes = false;
# 注意事项
# 修改副本策略后需要运行repair
# nodetool repair fgedudb
# 查看修改结果
cqlsh:fgedudb> DESCRIBE KEYSPACE fgedudb;
CREATE KEYSPACE fgedudb WITH replication = {‘class’: ‘NetworkTopologyStrategy’, ‘dc1’: ‘3’} AND durable_writes = false;
# 删除Keyspace
cqlsh> DROP KEYSPACE fgedu_test_db;
3.2 Cassandra数据库表创建
Cassandra数据库表创建实战:
3.2.1 Cassandra数据库创建简单表
cqlsh> USE fgedudb;
cqlsh:fgedudb>
# 创建简单表
cqlsh:fgedudb> CREATE TABLE fgedu_users (
… user_id uuid PRIMARY KEY,
… user_name text,
… email text,
… age int,
… created_at timestamp
… );
# 插入测试数据
cqlsh:fgedudb> INSERT INTO fgedu_users (user_id, user_name, email, age, created_at)
… VALUES (uuid(), ‘zhangsan’, ‘zhangsan@fgedu.net.cn’, 25, toTimestamp(now()));
cqlsh:fgedudb> INSERT INTO fgedu_users (user_id, user_name, email, age, created_at)
… VALUES (uuid(), ‘lisi’, ‘lisi@fgedu.net.cn’, 30, toTimestamp(now()));
# 查询数据
cqlsh:fgedudb> SELECT * FROM fgedu_users;
user_id | age | created_at | email | user_name
————————————–+—–+———————————-+———————-+———–
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 25 | 2024-01-15 10:30:00.123000+0000 | zhangsan@fgedu.net.cn | zhangsan
9f6g7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c | 30 | 2024-01-15 10:30:01.234000+0000 | lisi@fgedu.net.cn | lisi
(2 rows)
# 查看表结构
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;
CREATE TABLE fgedudb.fgedu_users (
user_id uuid PRIMARY KEY,
age int,
created_at timestamp,
email text,
user_name text
) WITH bloom_filter_fp_chance = 0.01
AND caching = {‘keys’: ‘ALL’, ‘rows_per_partition’: ‘NONE’}
AND comment = ”
AND compaction = {‘class’: ‘org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy’, ‘max_threshold’: ’32’, ‘min_threshold’: ‘4’}
AND compression = {‘chunk_length_in_kb’: ’16’, ‘class’: ‘org.apache.cassandra.io.compress.LZ4Compressor’}
AND crc_check_chance = 1.0
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND speculative_retry = ’99PERCENTILE’;
3.2.2 Cassandra数据库创建复合主键表
cqlsh:fgedudb> CREATE TABLE fgedu_orders (
… user_id uuid,
… order_id uuid,
… order_time timestamp,
… product_name text,
… quantity int,
… price decimal,
… total_amount decimal,
… status text,
… PRIMARY KEY (user_id, order_time)
… ) WITH CLUSTERING ORDER BY (order_time DESC);
# 说明
# 分区键: user_id
# 聚簇键: order_time
# 聚簇排序: 按order_time降序
# 插入测试数据
cqlsh:fgedudb> INSERT INTO fgedu_orders (user_id, order_id, order_time, product_name, quantity, price, total_amount, status)
… VALUES (
… 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b,
… uuid(),
… ‘2024-01-15 10:00:00’,
… ‘iPhone 15’,
… 1,
… 7999.00,
… 7999.00,
… ‘PAID’
… );
cqlsh:fgedudb> INSERT INTO fgedu_orders (user_id, order_id, order_time, product_name, quantity, price, total_amount, status)
… VALUES (
… 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b,
… uuid(),
… ‘2024-01-15 11:00:00’,
… ‘MacBook Pro’,
… 1,
… 14999.00,
… 14999.00,
… ‘PAID’
… );
# 查询用户订单(按时间降序)
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE user_id = 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b;
user_id | order_time | order_id | price | product_name | quantity | status | total_amount
————————————–+———————————-+————————————–+———+————–+———-+——–+————–
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 2024-01-15 11:00:00.000000+0000 | 0g7h8c9d-0e1f-2a3b-4c5d-6e7f8a9b0c1d | 14999.0 | MacBook Pro | 1 | PAID | 14999.0
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 2024-01-15 10:00:00.000000+0000 | 9f6g7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c | 7999.0 | iPhone 15 | 1 | PAID | 7999.0
(2 rows)
# 范围查询
cqlsh:fgedudb> SELECT * FROM fgedu_orders
… WHERE user_id = 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b
… AND order_time >= ‘2024-01-15 10:30:00’;
user_id | order_time | order_id | price | product_name | quantity | status | total_amount
————————————–+———————————-+————————————–+———+————–+———-+——–+————–
8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b | 2024-01-15 11:00:00.000000+0000 | 0g7h8c9d-0e1f-2a3b-4c5d-6e7f8a9b0c1d | 14999.0 | MacBook Pro | 1 | PAID | 14999.0
(1 row)
3.2.3 Cassandra数据库创建复合分区键表
cqlsh:fgedudb> CREATE TABLE fgedu_logs (
… log_date date,
… log_level text,
… log_time timestamp,
… service_name text,
… message text,
… PRIMARY KEY ((log_date, log_level), log_time)
… ) WITH CLUSTERING ORDER BY (log_time DESC);
# 说明
# 分区键: (log_date, log_level) 复合分区键
# 聚簇键: log_time
# 聚簇排序: 按log_time降序
# 插入测试数据
cqlsh:fgedudb> INSERT INTO fgedu_logs (log_date, log_level, log_time, service_name, message)
… VALUES (‘2024-01-15’, ‘ERROR’, toTimestamp(now()), ‘user-service’, ‘User login failed’);
cqlsh:fgedudb> INSERT INTO fgedu_logs (log_date, log_level, log_time, service_name, message)
… VALUES (‘2024-01-15’, ‘INFO’, toTimestamp(now()), ‘order-service’, ‘Order created successfully’);
cqlsh:fgedudb> INSERT INTO fgedu_logs (log_date, log_level, log_time, service_name, message)
… VALUES (‘2024-01-15’, ‘WARN’, toTimestamp(now()), ‘payment-service’, ‘Payment timeout’);
# 查询特定日期和级别的日志
cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE log_date = ‘2024-01-15’ AND log_level = ‘ERROR’;
log_date | log_level | log_time | message | service_name
————+———–+———————————–+——————–+————–
2024-01-15 | ERROR | 2024-01-15 10:30:00.123000+0000 | User login failed | user-service
(1 row)
3.3 Cassandra数据库表修改
Cassandra数据库表修改实战:
3.3.1 Cassandra数据库添加列
cqlsh:fgedudb> ALTER TABLE fgedu_users ADD phone text;
cqlsh:fgedudb> ALTER TABLE fgedu_users ADD address frozen
# 创建UDT类型
cqlsh:fgedudb> CREATE TYPE address_type (
… province text,
… city text,
… street text,
… zip_code text
… );
# 查看修改后的表结构
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;
CREATE TABLE fgedudb.fgedu_users (
user_id uuid PRIMARY KEY,
address frozen
age int,
created_at timestamp,
email text,
phone text,
user_name text
) …
3.3.2 Cassandra数据库删除列
cqlsh:fgedudb> ALTER TABLE fgedu_users DROP phone;
# 注意事项
# 删除列是不可逆操作
# 删除后数据无法恢复
# 建议先备份数据
# 查看修改后的表结构
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;
3.3.3 Cassandra数据库修改表属性
cqlsh:fgedudb> ALTER TABLE fgedu_users
… WITH compression = {‘class’: ‘LZ4Compressor’, ‘chunk_length_in_kb’: 64};
# 修改压缩策略
cqlsh:fgedudb> ALTER TABLE fgedu_orders
… WITH compaction = {‘class’: ‘LeveledCompactionStrategy’, ‘sstable_size_in_mb’: 160};
# 修改GC Grace时间
cqlsh:fgedudb> ALTER TABLE fgedu_logs
… WITH gc_grace_seconds = 86400;
# 修改默认TTL
cqlsh:fgedudb> ALTER TABLE fgedu_logs
… WITH default_time_to_live = 604800;
# 修改缓存配置
cqlsh:fgedudb> ALTER TABLE fgedu_users
… WITH caching = {‘keys’: ‘ALL’, ‘rows_per_partition’: ‘100’};
# 查看修改后的表属性
cqlsh:fgedudb> DESCRIBE TABLE fgedu_users;
3.3.4 Cassandra数据库删除表
cqlsh:fgedudb> TRUNCATE TABLE fgedu_test;
# 删除表
cqlsh:fgedudb> DROP TABLE fgedu_test;
# 注意事项
# 删除表是不可逆操作
# 删除后数据无法恢复
# 建议先备份数据
Part04-生产案例与实战讲解
4.1 Cassandra数据库用户表设计实战
Cassandra数据库用户表设计实战案例:
4.1.1 Cassandra数据库用户表设计需求
# 查询需求
1. 根据用户ID查询用户信息
2. 根据邮箱查询用户信息
3. 根据用户名查询用户信息
4. 查询最近注册的用户
# 设计方案
# 采用反规范化设计,创建多个表支持不同查询
# 表1: 用户主表(按ID查询)
CREATE TABLE fgedu_users_by_id (
user_id uuid PRIMARY KEY,
user_name text,
email text,
phone text,
password_hash text,
status text,
created_at timestamp,
updated_at timestamp
);
# 表2: 用户邮箱索引表(按邮箱查询)
CREATE TABLE fgedu_users_by_email (
email text PRIMARY KEY,
user_id uuid
);
# 表3: 用户名索引表(按用户名查询)
CREATE TABLE fgedu_users_by_name (
user_name text PRIMARY KEY,
user_id uuid
);
# 表4: 用户注册时间表(查询最近注册用户)
CREATE TABLE fgedu_users_by_created (
created_date date,
created_at timestamp,
user_id uuid,
user_name text,
email text,
PRIMARY KEY (created_date, created_at)
) WITH CLUSTERING ORDER BY (created_at DESC);
4.1.2 Cassandra数据库用户表操作实战
# 使用BATCH保证原子性
cqlsh:fgedudb> BEGIN BATCH
… INSERT INTO fgedu_users_by_id (user_id, user_name, email, phone, password_hash, status, created_at, updated_at)
… VALUES (uuid(), ‘wangwu’, ‘wangwu@fgedu.net.cn’, ‘13800138000’, ‘hash123’, ‘ACTIVE’, toTimestamp(now()), toTimestamp(now()));
… INSERT INTO fgedu_users_by_email (email, user_id)
… VALUES (‘wangwu@fgedu.net.cn’, uuid());
… INSERT INTO fgedu_users_by_name (user_name, user_id)
… VALUES (‘wangwu’, uuid());
… APPLY BATCH;
# 查询用户(按ID)
cqlsh:fgedudb> SELECT * FROM fgedu_users_by_id
… WHERE user_id = 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b;
# 查询用户(按邮箱)
cqlsh:fgedudb> SELECT * FROM fgedu_users_by_email
… WHERE email = ‘wangwu@fgedu.net.cn’;
# 查询用户(按用户名)
cqlsh:fgedudb> SELECT * FROM fgedu_users_by_name
… WHERE user_name = ‘wangwu’;
# 查询最近注册的用户
cqlsh:fgedudb> SELECT * FROM fgedu_users_by_created
… WHERE created_date = ‘2024-01-15’
… LIMIT 10;
4.2 Cassandra数据库订单表设计实战
Cassandra数据库订单表设计实战案例:
4.2.1 Cassandra数据库订单表设计需求
# 查询需求
1. 根据订单ID查询订单详情
2. 根据用户ID查询订单列表
3. 根据商品ID查询订单列表
4. 查询每日订单统计
# 设计方案
# 表1: 订单主表(按订单ID查询)
CREATE TABLE fgedu_orders_by_id (
order_id uuid PRIMARY KEY,
user_id uuid,
order_time timestamp,
status text,
total_amount decimal,
shipping_address frozen
items list
);
# 表2: 用户订单表(按用户ID查询)
CREATE TABLE fgedu_orders_by_user (
user_id uuid,
order_time timestamp,
order_id uuid,
status text,
total_amount decimal,
PRIMARY KEY (user_id, order_time)
) WITH CLUSTERING ORDER BY (order_time DESC);
# 表3: 商品订单表(按商品ID查询)
CREATE TABLE fgedu_orders_by_product (
product_id uuid,
order_time timestamp,
order_id uuid,
user_id uuid,
quantity int,
price decimal,
PRIMARY KEY (product_id, order_time)
) WITH CLUSTERING ORDER BY (order_time DESC);
# 表4: 每日订单统计表
CREATE TABLE fgedu_daily_order_stats (
stat_date date PRIMARY KEY,
total_orders counter,
total_amount counter,
total_users counter
);
# 创建UDT类型
CREATE TYPE order_item_type (
product_id uuid,
product_name text,
quantity int,
price decimal
);
4.2.2 Cassandra数据库订单表操作实战
cqlsh:fgedudb> BEGIN BATCH
… INSERT INTO fgedu_orders_by_id (order_id, user_id, order_time, status, total_amount)
… VALUES (uuid(), uuid(), toTimestamp(now()), ‘CREATED’, 22998.00);
… INSERT INTO fgedu_orders_by_user (user_id, order_time, order_id, status, total_amount)
… VALUES (uuid(), toTimestamp(now()), uuid(), ‘CREATED’, 22998.00);
… APPLY BATCH;
# 更新计数器
cqlsh:fgedudb> UPDATE fgedu_daily_order_stats
… SET total_orders = total_orders + 1,
… total_amount = total_amount + 22998,
… total_users = total_users + 1
… WHERE stat_date = ‘2024-01-15’;
# 查询订单(按订单ID)
cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_id
… WHERE order_id = 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b;
# 查询用户订单
cqlsh:fgedudb> SELECT * FROM fgedu_orders_by_user
… WHERE user_id = 8e5f6a7b-8c9d-0e1f-2a3b-4c5d6e7f8a9b
… LIMIT 10;
# 查询每日订单统计
cqlsh:fgedudb> SELECT * FROM fgedu_daily_order_stats
… WHERE stat_date = ‘2024-01-15’;
stat_date | total_amount | total_orders | total_users
————+————–+————–+————-
2024-01-15 | 22998 | 1 | 1
(1 row)
4.3 Cassandra数据库日志表设计实战
Cassandra数据库日志表设计实战案例:
4.3.1 Cassandra数据库日志表设计需求
# 查询需求
1. 按日期和级别查询日志
2. 按服务名称查询日志
3. 按时间范围查询日志
4. 自动清理过期日志
# 设计方案
# 表1: 日志主表(按日期和级别查询)
CREATE TABLE fgedu_logs (
log_date date,
log_level text,
log_time timestamp,
service_name text,
trace_id text,
message text,
extra_data map
PRIMARY KEY ((log_date, log_level), log_time)
) WITH CLUSTERING ORDER BY (log_time DESC)
AND default_time_to_live = 604800
AND gc_grace_seconds = 86400;
# 表2: 服务日志表(按服务名称查询)
CREATE TABLE fgedu_logs_by_service (
service_name text,
log_date date,
log_time timestamp,
log_level text,
message text,
PRIMARY KEY ((service_name, log_date), log_time)
) WITH CLUSTERING ORDER BY (log_time DESC)
AND default_time_to_live = 604800;
# 表3: 追踪日志表(按追踪ID查询)
CREATE TABLE fgedu_logs_by_trace (
trace_id text,
log_time timestamp,
service_name text,
log_level text,
message text,
PRIMARY KEY (trace_id, log_time)
) WITH CLUSTERING ORDER BY (log_time ASC)
AND default_time_to_live = 86400;
4.3.2 Cassandra数据库日志表操作实战
cqlsh:fgedudb> INSERT INTO fgedu_logs (log_date, log_level, log_time, service_name, trace_id, message, extra_data)
… VALUES (
… ‘2024-01-15’,
… ‘ERROR’,
… toTimestamp(now()),
… ‘user-service’,
… ‘trace-12345’,
… ‘User authentication failed’,
… {‘user_id’: ‘user-001’, ‘ip’: ‘192.168.1.100’}
… );
# 查询日志(按日期和级别)
cqlsh:fgedudb> SELECT * FROM fgedu_logs
… WHERE log_date = ‘2024-01-15’ AND log_level = ‘ERROR’
… LIMIT 100;
log_date | log_level | log_time | extra_data | message | service_name | trace_id
————+———–+———————————–+———————————————+——————————–+————–+———–
2024-01-15 | ERROR | 2024-01-15 10:30:00.123000+0000 | {‘ip’: ‘192.168.1.100’, ‘user_id’: ‘user-001’} | User authentication failed | user-service | trace-12345
(1 row)
# 查询日志(按服务名称)
cqlsh:fgedudb> SELECT * FROM fgedu_logs_by_service
… WHERE service_name = ‘user-service’ AND log_date = ‘2024-01-15’
… LIMIT 100;
# 查询日志(按追踪ID)
cqlsh:fgedudb> SELECT * FROM fgedu_logs_by_trace
… WHERE trace_id = ‘trace-12345’;
# 日志自动清理
# 通过default_time_to_live配置自动过期
# fgedu_logs: 7天后自动删除
# fgedu_logs_by_trace: 1天后自动删除
Part05-风哥经验总结与分享
5.1 Cassandra数据库表设计最佳实践
Cassandra数据库表设计最佳实践总结:
- 查询驱动设计:根据查询需求设计表结构,一个查询一个表
- 反规范化:允许数据冗余,避免连接查询
- 分区键设计:选择高基数列,避免热点分区
- 聚簇键设计:根据排序需求设计,支持范围查询
- 数据类型选择:选择合适的数据类型,考虑存储和查询效率
- TTL使用:设置合理的数据过期时间,自动清理过期数据
- 压缩策略:根据数据特点选择合适的压缩策略
- 副本策略:生产环境使用NetworkTopologyStrategy
5.2 Cassandra数据库表设计检查清单
# 1. Keyspace设计
[ ] Keyspace名称符合规范
[ ] 副本策略选择正确
[ ] 副本因子设置合理
[ ] durable_writes配置正确
# 2. 表设计
[ ] 表名称符合规范
[ ] 主键设计合理
[ ] 分区键分布均匀
[ ] 聚簇键支持排序需求
[ ] 数据类型选择合适
# 3. 查询设计
[ ] 查询模式已确定
[ ] 分区键支持查询条件
[ ] 聚簇键支持范围查询
[ ] 避免ALLOW FILTERING
# 4. 性能设计
[ ] 压缩策略选择合理
[ ] 压缩配置合理
[ ] 缓存配置合理
[ ] TTL设置合理
# 5. 数据一致性
[ ] gc_grace_seconds设置合理
[ ] 数据同步策略确定
[ ] 修复计划制定
# 6. 安全设计
[ ] 敏感数据加密
[ ] 访问权限控制
[ ] 审计日志记录
5.3 Cassandra数据库表设计工具推荐
Cassandra数据库表设计工具推荐:
5.3.1 Cassandra数据库设计工具
# 1. DataStax DevCenter
# DataStax官方开发工具
# 支持CQL编辑和执行
# 支持表结构可视化
# 2. DBeaver
# 通用数据库管理工具
# 支持Cassandra连接
# 支持表结构管理
# 3. cqlsh
# Cassandra自带命令行工具
# 支持CQL执行
# 支持表结构查看
# 4. DataStax Studio
# DataStax官方可视化工具
# 支持数据建模
# 支持查询可视化
# 5. Hackolade
# NoSQL数据建模工具
# 支持Cassandra建模
# 支持逆向工程
5.3.2 Cassandra数据库设计验证工具
# 1. nodetool cfstats
# 查看表统计信息
# nodetool cfstats fgedudb.fgedu_users
# 2. nodetool tablehistograms
# 查看表数据分布
# nodetool tablehistograms fgedudb.fgedu_users
# 3. cassandra-stress
# 性能测试工具
# 验证表设计性能
# 4. sstable-tools
# SSTable分析工具
# 分析数据分布
本文档详细介绍了Cassandra数据库Keyspace与表设计实战,包括Keyspace概念、表概念、设计原则、Keyspace规划、表规划、副本策略规划、Keyspace创建、表创建、表修改、用户表设计实战、订单表设计实战、日志表设计实战、表设计最佳实践、表设计检查清单、表设计工具推荐等内容。通过学习本文档,读者可以掌握Cassandra数据库表设计技能,为应用开发打下坚实基础。
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
