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

十、总结 #

一致性级别要点:

  1. 可调一致性:每次操作可指定不同级别
  2. 强一致性条件:CL.W + CL.R > RF
  3. QUORUM:生产环境推荐,平衡一致性和可用性
  4. LOCAL_QUORUM:多数据中心首选
  5. 性能权衡:一致性越高,性能越低
  6. 场景选择:根据业务需求选择合适级别

下一步,让我们学习键空间操作!

最后更新:2026-03-27