轻量级事务 #
一、LWT概述 #
1.1 什么是LWT #
轻量级事务(Lightweight Transactions, LWT)基于Paxos协议,提供条件更新能力。
text
LWT特点:
✓ 条件插入/更新
✓ 原子性保证
✓ 线性一致性
✓ 基于Paxos协议
1.2 LWT vs 普通操作 #
| 特性 | LWT | 普通操作 |
|---|---|---|
| 条件检查 | ✓ | ✗ |
| 原子性 | ✓ | 最终一致 |
| 性能 | 低(4次往返) | 高 |
| 适用场景 | 需要条件判断 | 一般操作 |
二、IF NOT EXISTS #
2.1 条件插入 #
sql
-- 仅当记录不存在时插入
INSERT INTO users (user_id, email, name)
VALUES (uuid(), 'unique@example.com', '张三')
IF NOT EXISTS;
-- 返回结果
-- [applied] | user_id | email | name
------------+---------+--------------------+-------
-- True | uuid | unique@example.com | 张三
-- 如果记录已存在
-- [applied] | user_id | email | name
------------+---------+--------------------+-------
-- False | uuid | existing@ex.com | 李四
2.2 应用场景 #
sql
-- 唯一邮箱注册
INSERT INTO users (user_id, email, name)
VALUES (uuid(), ?, ?)
IF NOT EXISTS;
-- 唯一用户名
INSERT INTO user_names (username, user_id)
VALUES (?, ?)
IF NOT EXISTS;
-- 初始化计数器
INSERT INTO counters (counter_id, value)
VALUES (?, 0)
IF NOT EXISTS;
三、IF条件更新 #
3.1 基本条件更新 #
sql
-- 条件更新
UPDATE users
SET email = 'new@example.com'
WHERE user_id = ?
IF email = 'old@example.com';
-- 多条件更新
UPDATE orders
SET status = 'shipped'
WHERE order_id = ?
IF status = 'pending' AND amount > 0;
3.2 条件删除 #
sql
-- 条件删除
DELETE FROM orders
WHERE order_id = ?
IF status = 'cancelled';
-- 条件删除列
DELETE email FROM users
WHERE user_id = ?
IF email = 'old@example.com';
3.3 复杂条件 #
sql
-- 多列条件
UPDATE products
SET stock = stock - 1
WHERE product_id = ?
IF stock > 0;
-- 组合条件
UPDATE accounts
SET balance = balance - ?
WHERE account_id = ?
IF balance >= ? AND status = 'active';
四、BATCH中的LWT #
4.1 条件批量操作 #
sql
-- 条件批量操作
BEGIN BATCH
UPDATE users
SET email = 'new@example.com'
WHERE user_id = ?
IF email = 'old@example.com';
INSERT INTO audit_log (log_id, action, timestamp)
VALUES (uuid(), 'email_change', toTimestamp(now()));
APPLY BATCH;
4.2 多条件批量 #
sql
-- 多条件批量
BEGIN BATCH
UPDATE accounts
SET balance = balance - 100
WHERE account_id = ?
IF balance >= 100;
UPDATE accounts
SET balance = balance + 100
WHERE account_id = ?
IF balance >= 0;
INSERT INTO transactions (tx_id, from_account, to_account, amount)
VALUES (uuid(), ?, ?, 100);
APPLY BATCH;
五、性能影响 #
5.1 性能开销 #
text
LWT性能开销:
网络往返
├── 4次往返(Paxos协议)
├── Prepare → Propose → Commit → Read
└── 延迟显著增加
吞吐量
├── 比普通操作低很多
├── 单节点约1000 TPS
└── 受网络延迟影响
建议
├── 仅在必要时使用
├── 避免频繁使用
└── 考虑替代方案
5.2 性能对比 #
text
性能对比(大致):
普通操作
├── 延迟:1-5ms
├── 吞吐:高
└── 适合:大部分场景
LWT操作
├── 延迟:10-50ms
├── 吞吐:低
└── 适合:需要条件判断的场景
六、最佳实践 #
6.1 使用场景 #
text
LWT适用场景:
适合
├── 唯一性保证
├── 状态转换
├── 乐观锁
└── 条件更新
不适合
├── 高频操作
├── 大批量操作
├── 对性能敏感
└── 可容忍短暂不一致
6.2 替代方案 #
sql
-- 替代方案1:应用层检查
-- 先查询,再插入/更新
SELECT email FROM users WHERE user_id = ?;
-- 应用层判断
INSERT INTO users ...
-- 替代方案2:唯一约束表
-- 使用单独的表存储唯一约束
INSERT INTO unique_emails (email, user_id)
VALUES (?, ?)
IF NOT EXISTS;
-- 替代方案3:时间戳版本
-- 使用时间戳作为版本号
UPDATE users
SET email = ?, version = ?
WHERE user_id = ? AND version = old_version;
6.3 设计建议 #
text
设计建议:
1. 限制使用范围
└── 仅在真正需要时使用
2. 减少条件复杂度
└── 简单条件性能更好
3. 监控性能
└── 关注延迟和吞吐
4. 考虑一致性级别
└── SERIAL/LOCAL_SERIAL
5. 准备回滚方案
└── 处理条件不满足的情况
七、一致性级别 #
7.1 SERIAL一致性 #
sql
-- SERIAL一致性(默认)
INSERT INTO users (user_id, email)
VALUES (?, ?)
IF NOT EXISTS
USING CONSISTENCY SERIAL;
-- LOCAL_SERIAL(多数据中心)
INSERT INTO users (user_id, email)
VALUES (?, ?)
IF NOT EXISTS
USING CONSISTENCY LOCAL_SERIAL;
7.2 一致性级别选择 #
text
一致性级别选择:
SERIAL
├── 全局线性一致
├── 跨数据中心
└── 延迟较高
LOCAL_SERIAL
├── 本地数据中心线性一致
├── 性能较好
└── 推荐多数据中心使用
八、常见问题 #
8.1 条件不满足 #
sql
-- 检查返回结果
UPDATE users
SET email = 'new@example.com'
WHERE user_id = ?
IF email = 'old@example.com';
-- 处理
-- 如果 [applied] = False,条件不满足
-- 需要处理失败情况
8.2 性能问题 #
text
性能问题解决:
1. 减少LWT使用
└── 重新设计数据模型
2. 使用LOCAL_SERIAL
└── 多数据中心场景
3. 批量操作
└── 合并多个LWT
4. 异步处理
└── 非关键路径异步化
九、总结 #
轻量级事务要点:
- 条件操作:IF NOT EXISTS、IF条件
- Paxos协议:4次网络往返
- 性能开销:比普通操作低很多
- 适用场景:唯一性、状态转换、乐观锁
- 一致性级别:SERIAL、LOCAL_SERIAL
- 谨慎使用:仅在必要时使用
恭喜你完成了Cassandra完全指南的学习!
最后更新:2026-03-27