【发布时间】:2016-05-26 00:40:32
【问题描述】:
在 Cassandra 中更新一行时,我遇到了丢失写入的问题。这是我的架构:
create table balances(
id bigint,
balance decimal,
last_transaction_id bigint,
update_timestamp timestamp,
type varchar,
is_balance_valid boolean,
primary key (wallet_id)
)
集群中的节点总数:本地 DC 中的 3 个 复制因子:2 Cassandra 版本:2.1.8
每次用户进行交易时,我都会通过读取先前设置的值、添加交易金额并发布更新来更新“余额”列的值。我正在使用 Java、Datastax 驱动程序 (2.1.5)。
在大约 50 万笔交易中,有一次特定更新会失败。这通常发生在用户快速连续完成两个事务时,低至几毫秒。以下是日志:
交易#1
2016 年 2 月 10 日 18:15:16,984 -[pool-11-thread-1]- 信息 - ScratchpadMasterStreamProcessor.processMessage(62) - 打印 str id: 1466140282便签本号:9127013322
2016 年 2 月 10 日 18:15:16,986 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(43) - 当前余额:0.0
2016 年 2 月 10 日 18:15:16,986 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(44) - 偏差:200.0
2016 年 2 月 10 日 18:15:16,986 -[pool-11-thread-1]- 调试 - UserBalanceManager.updateWalletBalance(70) - 更新用户..510978682
2016 年 2 月 10 日 18:15:16,987 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(51) - 最终余额:200.0
2016 年 2 月 10 日 18:15:16,987 -[pool-11-thread-1]- 调试 - ScratchpadMasterStreamProcessor.processMessage(79) - 余额更新 钱包510978682成功
交易 #2
2016 年 2 月 10 日 18:18:19,157 -[pool-11-thread-1]- 信息 - ConsumerThread.run(82) - 收到事件
2016 年 2 月 10 日 18:18:19,159 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(43) - 当前余额:200.0
2016 年 2 月 10 日 18:18:19,159 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(44) - 偏差:50.0
2016 年 2 月 10 日 18:18:19,159 -[pool-11-thread-1]- 调试 - UserBalanceManager.updateWalletBalance(70) - 更新用户..510978682
2016 年 2 月 10 日 18:18:19,160 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(51) - 最终余额:250.0
2016 年 2 月 10 日 18:18:19,160 -[pool-11-thread-1]- 调试 - ScratchpadMasterStreamProcessor.processMessage(79) - 余额更新 钱包510978682成功
事务 #3(已丢失)
2016 年 2 月 10 日 18:18:19,160 -[pool-11-thread-1]- 信息 - ScratchpadMasterStreamProcessor.processMessage(62) - 打印 str id: 1466162182便签本编号:9127117934
2016 年 2 月 10 日 18:18:19,161 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(43) - 当前余额:250.0
2016 年 2 月 10 日 18:18:19,161 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(44) - 偏差:-250.0
2016 年 2 月 10 日 18:18:19,161 -[pool-11-thread-1]- 调试 - UserBalanceManager.updateWalletBalance(70) - 更新用户..510978682
2016 年 2 月 10 日 18:18:19,162 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(51) - 最终余额:0.0
2016 年 2 月 10 日 18:18:19,162 -[pool-11-thread-1]- 调试 - ScratchpadMasterStreamProcessor.processMessage(79) - 余额更新 钱包510978682成功
事务 #4 读取过期余额,哎呀
2016 年 2 月 10 日 18:18:23,140 -[pool-11-thread-1]- 信息 - ConsumerThread.run(82) - 收到事件
2016 年 2 月 10 日 18:18:23,140 -[pool-11-thread-1]- 信息 - ScratchpadMasterStreamProcessor.processMessage(62) - 打印 str id: 1466162730便签本编号:9127120830
2016 年 2 月 10 日 18:18:23,141 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(43) - 当前余额:250.0
2016 年 2 月 10 日 18:18:23,141 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(44) - 偏差:200.0
2016 年 2 月 10 日 18:18:23,141 -[pool-11-thread-1]- 调试 - UserBalanceManager.updateWalletBalance(70) - 更新用户..510978682
2016 年 2 月 10 日 18:18:23,142 -[pool-11-thread-1]- 调试 - SclwBalanceUpdater.updateBalance(51) - 最终余额:450.0
2016 年 2 月 10 日 18:18:23,142 -[pool-11-thread-1]- 调试 - ScratchpadMasterStreamProcessor.processMessage(79) - 余额更新 钱包510978682成功
我已将读取和写入的一致性级别设置为 LOCAL_QUORUM,并且三个 cassandra 节点服务器具有相同的时间(使用 NTP)。可能是什么问题?
【问题讨论】:
-
Cassandra 等数据库在扩展、分发到多个数据中心和可用性方面具有显着优势。但这是以降低一致性保证为代价的。这很可能是你正在经历的。如果在所有情况下都需要精确平衡,我不确定 Cassandra 是否是正确的选择。
标签: java cassandra updates datastax consistency