Cassandra一致性级别 #
一、一致性概述 #
1.1 CAP理论 #
Cassandra在CAP理论中属于AP系统,优先保证可用性和分区容错性。
text
CAP理论:
Consistency (一致性)
/\
/ \
/ \
/ \
/________\
Availability Partition
(可用性) (分区容错)
Cassandra选择:
├── Availability: 高可用
├── Partition Tolerance: 分区容错
└── Consistency: 可调一致性
1.2 可调一致性 #
Cassandra允许客户端为每次操作指定一致性级别。
text
可调一致性示意:
写入请求
│
├── CONSISTENCY ONE
│ └── 等待1个节点确认
│
├── CONSISTENCY QUORUM
│ └── 等待多数节点确认
│
└── CONSISTENCY ALL
└── 等待所有节点确认
一致性级别越高:
├── 一致性越强
├── 延迟越高
└── 可用性越低
二、一致性级别类型 #
2.1 写一致性级别 #
| 级别 | 描述 | 确认数量 | 适用场景 |
|---|---|---|---|
| ANY | 任意节点(包括Hinted Handoff) | ≥1 | 最高可用性 |
| ONE | 一个副本确认 | 1 | 快速写入 |
| TWO | 两个副本确认 | 2 | 较高可靠性 |
| THREE | 三个副本确认 | 3 | 高可靠性 |
| QUORUM | 多数副本确认 | RF/2+1 | 强一致性 |
| LOCAL_QUORUM | 本地数据中心多数确认 | 本地DC的RF/2+1 | 多数据中心 |
| EACH_QUORUM | 每个数据中心多数确认 | 每DC的RF/2+1 | 跨DC强一致 |
| ALL | 所有副本确认 | RF | 最高一致性 |
2.2 读一致性级别 #
| 级别 | 描述 | 读取节点 | 适用场景 |
|---|---|---|---|
| ONE | 一个副本 | 1 | 快速读取 |
| TWO | 两个副本,比较时间戳 | 2 | 较高一致性 |
| THREE | 三个副本,比较时间戳 | 3 | 高一致性 |
| QUORUM | 多数副本,比较时间戳 | RF/2+1 | 强一致性 |
| LOCAL_QUORUM | 本地数据中心多数 | 本地DC的RF/2+1 | 多数据中心 |
| LOCAL_ONE | 本地数据中心一个副本 | 1 | 本地快速读取 |
| ALL | 所有副本 | RF | 最高一致性 |
2.3 一致性级别计算 #
text
QUORUM计算:
RF (Replication Factor) = 3
QUORUM = floor(RF/2) + 1 = 2
RF = 5
QUORUM = floor(5/2) + 1 = 3
RF = 7
QUORUM = floor(7/2) + 1 = 4
三、强一致性保证 #
3.1 强一致性条件 #
text
强一致性条件:
写一致性(CL.W) + 读一致性(CL.R) > 复制因子(RF)
示例(RF=3):
┌──────────────┬──────────────┬─────────────────────┐
│ 写一致性 │ 读一致性 │ 结果 │
├──────────────┼──────────────┼─────────────────────┤
│ ALL (3) │ ONE (1) │ 强一致 (3+1>3) ✓ │
│ QUORUM (2) │ QUORUM (2) │ 强一致 (2+2>3) ✓ │
│ ONE (1) │ ONE (1) │ 最终一致 (1+1≤3) ✗ │
│ TWO (2) │ TWO (2) │ 强一致 (2+2>3) ✓ │
└──────────────┴──────────────┴─────────────────────┘
3.2 强一致性示例 #
sql
-- 设置一致性级别
CONSISTENCY QUORUM;
-- 写入(QUORUM)
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '张三', 'zhangsan@example.com');
-- 等待2个节点确认(RF=3时)
-- 读取(QUORUM)
SELECT * FROM users WHERE user_id = ?;
-- 从2个节点读取,比较时间戳,返回最新数据
-- 保证:读取一定能看到最新写入
3.3 最终一致性示例 #
sql
-- 设置一致性级别
CONSISTENCY ONE;
-- 写入(ONE)
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '李四', 'lisi@example.com');
-- 等待1个节点确认
-- 读取(ONE)
SELECT * FROM users WHERE user_id = ?;
-- 从1个节点读取
-- 可能:读取到旧数据(如果读到了还没同步的节点)
四、一致性级别选择 #
4.1 选择策略 #
text
一致性级别选择决策树:
数据重要性?
├── 高(金融、订单)
│ └── QUORUM读写
│ └── 强一致性保证
│
├── 中(用户资料)
│ └── QUORUM写 + ONE读
│ └── 写入可靠,读取快速
│
└── 低(日志、统计)
└── ONE读写
└── 高性能,最终一致
4.2 场景推荐 #
| 场景 | 写一致性 | 读一致性 | 原因 |
|---|---|---|---|
| 金融交易 | QUORUM | QUORUM | 强一致性 |
| 用户资料 | QUORUM | ONE | 写入可靠 |
| 购物车 | ONE | ONE | 高性能 |
| 日志记录 | ANY | ONE | 最高可用 |
| 社交动态 | ONE | ONE | 高吞吐 |
| 库存管理 | QUORUM | QUORUM | 数据准确 |
4.3 多数据中心选择 #
sql
-- 多数据中心推荐配置
-- 本地优先(推荐)
CONSISTENCY LOCAL_QUORUM;
-- 优点:低延迟,本地强一致
-- 跨数据中心强一致(不推荐,延迟高)
CONSISTENCY QUORUM;
-- 本地快速读取
CONSISTENCY LOCAL_ONE;
五、一致性级别设置 #
5.1 cqlsh设置 #
sql
-- 查看当前一致性级别
CONSISTENCY;
-- 设置一致性级别
CONSISTENCY QUORUM;
-- 设置为默认
CONSISTENCY LOCAL_QUORUM;
-- 单次查询指定
SELECT * FROM users WHERE user_id = ?
USING CONSISTENCY QUORUM;
5.2 驱动程序设置 #
java
// Java驱动
import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.QueryOptions;
// 全局设置
QueryOptions options = new QueryOptions()
.setConsistencyLevel(ConsistencyLevel.QUORUM)
.setSerialConsistencyLevel(ConsistencyLevel.LOCAL_SERIAL);
// 单次查询设置
Statement statement = QueryBuilder.select()
.all()
.from("users")
.where(QueryBuilder.eq("user_id", userId))
.setConsistencyLevel(ConsistencyLevel.QUORUM);
python
# Python驱动
from cassandra import ConsistencyLevel
from cassandra.query import SimpleStatement
# 全局设置
cluster = Cluster(['localhost'])
session = cluster.connect()
session.default_consistency_level = ConsistencyLevel.QUORUM
# 单次查询设置
query = SimpleStatement(
"SELECT * FROM users WHERE user_id = %s",
consistency_level=ConsistencyLevel.QUORUM
)
go
// Go驱动
import "github.com/gocql/gocql"
// 全局设置
cluster := gocql.NewCluster("localhost")
cluster.Consistency = gocql.Quorum
// 单次查询设置
query := session.Query(
"SELECT * FROM users WHERE user_id = ?",
userId,
).Consistency(gocql.Quorum)
六、一致性权衡 #
6.1 性能影响 #
text
一致性级别 vs 性能:
一致性级别
│
│ ALL
│ │
│ │
│ QUORUM
│ │
│ │
│ TWO
│ │
│ │
│ ONE
│ │
│ │
│ ANY
│
└──────────────────────────► 性能
低 高
性能排序:ANY > ONE > TWO > QUORUM > ALL
6.2 可用性影响 #
text
一致性级别 vs 可用性:
可用性
│
│ ANY
│ │
│ ONE
│ │
│ QUORUM
│ │
│ ALL
│
└──────────────────────────► 一致性级别
高 低
可用性排序:ANY > ONE > QUORUM > ALL
RF=3时的故障容忍:
├── ANY: 可容忍所有节点故障(Hinted Handoff)
├── ONE: 可容忍2个节点故障
├── QUORUM: 可容忍1个节点故障
└── ALL: 无法容忍任何节点故障
6.3 延迟影响 #
text
一致性级别 vs 延迟:
延迟
│
│ ALL
│ │
│ QUORUM
│ │
│ ONE
│ │
│ ANY
│
└──────────────────────────► 一致性级别
高 低
延迟排序:ALL > QUORUM > ONE > ANY
多数据中心延迟:
├── QUORUM: 跨数据中心延迟
├── LOCAL_QUORUM: 本地数据中心延迟
└── LOCAL_ONE: 本地最低延迟
七、特殊场景 #
7.1 轻量级事务 #
sql
-- 轻量级事务使用SERIAL一致性级别
INSERT INTO users (user_id, email)
VALUES (uuid(), 'unique@example.com')
IF NOT EXISTS;
-- 使用条件更新
UPDATE users
SET email = 'new@example.com'
WHERE user_id = ?
IF email = 'old@example.com';
-- SERIAL一致性级别
-- 使用Paxos协议实现,性能较低
7.2 批量操作 #
sql
-- 批量操作的一致性
BEGIN BATCH
INSERT INTO orders (order_id, user_id, amount)
VALUES (uuid(), ?, 100.00);
UPDATE user_stats SET order_count = order_count + 1
WHERE user_id = ?;
APPLY BATCH;
-- 批量操作使用相同的一致性级别
-- 建议同一分区的批量操作
7.3 计数器更新 #
sql
-- 计数器更新建议使用QUORUM
UPDATE user_counters
SET login_count = login_count + 1
WHERE user_id = ?;
-- 计数器需要强一致性
-- 建议使用QUORUM或LOCAL_QUORUM
八、监控与调优 #
8.1 监控指标 #
bash
# 查看读写延迟
nodetool tablestats my_keyspace.my_table
# 查看一致性相关指标
# JMX: org.apache.cassandra.metrics.ClientRequest
8.2 调优建议 #
text
一致性调优建议:
1. 根据业务需求选择
├── 强一致性需求 → QUORUM
└── 高性能需求 → ONE
2. 多数据中心优化
├── 使用LOCAL_QUORUM
└── 避免跨数据中心延迟
3. 监控和调整
├── 监控读写延迟
├── 监控超时率
└── 根据实际情况调整
4. 故障场景考虑
├── 确定可接受的故障容忍度
└── 选择合适的一致性级别
九、最佳实践 #
9.1 推荐配置 #
sql
-- 生产环境推荐
-- 关键数据(强一致性)
写: LOCAL_QUORUM
读: LOCAL_QUORUM
-- 普通数据(平衡性能和一致性)
写: LOCAL_QUORUM
读: LOCAL_ONE
-- 日志数据(高性能)
写: ANY
读: ONE
9.2 常见问题 #
text
问题1:读取到旧数据
原因:写一致性 + 读一致性 ≤ RF
解决:使用QUORUM读写
问题2:写入超时
原因:一致性级别过高
解决:降低一致性级别或增加超时时间
问题3:跨数据中心延迟高
原因:使用QUORUM而非LOCAL_QUORUM
解决:使用LOCAL_QUORUM
问题4:节点故障时写入失败
原因:使用ALL一致性
解决:使用QUORUM或ONE
十、总结 #
一致性级别要点:
- 可调一致性:每次操作可指定不同级别
- 强一致性条件:CL.W + CL.R > RF
- QUORUM:生产环境推荐,平衡一致性和可用性
- LOCAL_QUORUM:多数据中心首选
- 性能权衡:一致性越高,性能越低
- 场景选择:根据业务需求选择合适级别
下一步,让我们学习键空间操作!
最后更新:2026-03-27