cassandra_Cassandra中单分区操作的重要性

cassandra

DuyHai Doan是DataStax的Apache Cassandra传播者。 他在Cassandra的技术演示/会议之间花费时间,在开源项目上编码以支持社区,并帮助所有使用Cassandra的公司使他们的项目成功。 之前,他是一名自由Java / Cassandra顾问。

在此博客文章中,我们将解释为什么所有Cassandra专家和福音传教士都推广单分区操作的原因。 我们将详细介绍单分区操作在操作一致性系统稳定性方面可以提供的所有好处。

原子性和隔离

保证对分区所有列的更改( INSERT / UPDATE / DELETE )是原子的,例如,将同一行中N列的更新视为一次写入操作。

原子性属性很重要,因为它可以确保客户端应用所有突变或不应用任何突变

多个分区突变目前无法提供原子性(至少直到CASSANDRA-7056RAMP Transaction ”完成)。 多个分区上的原子性将需要设置协调系统(例如全局锁定)或发送额外的元数据(例如在RAMP Transaction中)。

同样,对单个分区的突变被隔离在副本上,例如,直到客户端1完成写入突变,另一个客户端2将无法读取它们。 出于与上述相同的原因,不能单独应用多个分区。

批量

我们的技术传教士过去常常抱怨记录的批次 。 批次使用不当会导致节点故障并损害系统稳定性。

当您向多个分区发送带有突变的已记录批处理时,将发生以下情况:

多分区批处理

多分区批处理

由于具有高分布性, Murmur 3分区程序将在整个群集中均匀分布每个分区。 因此,在删除本地存储的日志批处理之前, 协调器节点将必须等待集群中的N个节点( 为简化起见,N =日志批处理中不同分区键的数量 )来确认突变。 在所有N个节点都发送回ack之前,无法从协调器中删除已记录的批处理。 拥有100个节点的集群,此记录的批次将极大地影响协调器的稳定性。

现在,让我们看看协调器如何处理单个分区记录的批处理

单分区批处理

单分区批处理

突变被发送到所有副本节点,并且协调器在删除记录的批处理之前等待RF确认(RF =复制因子)。 在这种情况下,群集的大小无关紧要,因为批处理涉及的节点数受复制因子的约束。

次要指标

Cassandra中的二级索引是一个有用的功能,但由于两个主要原因,很难正确使用:

  • 次要索引不能随群集大小很好地扩展。实际上,这些索引与基本数据一起分布 ,因此使用这些索引进行查询至少需要命中群集中的N / RF个节点, N是群集中的节点总数/数据中心和RF被复制factor.As一个例子,如果有一个100个节点RF = 3簇,与二级索引查询将很可能击中34个节点 (100/3向上舍入到34)。
  • 基数非常高而基数非常低。想像一下,您有一个带有“ 性别”列的表用户 。 表的主键是user_id 。 您希望能够按性别查找用户,因此很想在此列上创建二级索引。 但是,由于性别的可能值只有2个,因此在每个节点上,所有用户都只能分布在2个宽分区( MALEFEMALE )之间。另一个示例是在用户的电子邮件上创建二级索引,以便能够找到他们通过他们的电子邮件。 问题是,对于1个用户,最多有1个不同的电子邮件(很少有2个用户具有相同的电子邮件地址)。 因此,在发出类似查询时:
    SELECT * FROM users WHERE email='doanduyhai@nowhere.com';

    Cassandra将命中N / RF节点,最多只能检索1行,有时根本没有结果。 因此,仅查找1行所付出的成本实在让人望而却步

二级索引的唯一良好且可扩展的用例是将查询限制在单个分区上。 假设我们具有以下架构来存储传感器数据:

CREATE TABLE sensors(
   sensor_id uuid,
   date timestamp,
   location text,
   value double,
   PRIMARY KEY(sensor_id, date)
);
 
CREATE INDEX location_idx ON sensors(location);
CREATE INDEX value_idx ON sensors(value);

我们为传感器创建了以上2个索引,以按传感器位置和传感器值进行查询。 以下查询将是高性能且可扩展的,因为我们每次都会提供分区键( sensor_id ),因此Cassandra不会命中N / RF节点,而只会搜索单个节点中的数据。

//Give all values of my sensor when it is in Los Angelest
SELECT value FROM sensors WHERE sensor_id='de305d54-75b4-431b-adb2-eb6b9e546014
' AND location='Los Angeles';
 
//Give me the moment and the location of my sensor when it has value 4.5
SELECT date,location FROM sensors WHERE sensor_id='de305d54-75b4-431b-adb2-eb6b9e546014
' AND value=4.5;

轻量级交易

Cassandra 2.0中引入了LightWeight Transactions(LWT) ,以解决一类可能需要外部锁管理器的问题。

在后台,Cassandra正在实现Paxos协议以保证突变的线性化。 它类似于分布式“比较和交换”操作。

借助LWT ,您可以使用INSERT INTO(如果不存在)DELETE(如果存在)来模拟完整性约束。 显然,这两个操作是单个分区。

也可以使用LightWeight Transactions使用语法UPDATE…进行条件更新:SET col 1 = xxx WHERE partition_key = yyy IF col 2 = zzz; ,唯一的约束是要检查的条件列应与要更新的列属于同一行(属于同一分区)。

同样,您可以发出包含一个LWT突变的批处理语句,前提是所有其他突变都使用与使用LWT的相同的分区键。 例

CREATE TABLE stock_order (
   order_id uuid,
   order_state static text, // OPEN or CLOSED
   item_id int,
   item_amount double,
   PRIMARY KEY (order_id, item_id)
);
 
// Batch insert new items into the given order and close it 
BEGIN LOGGED BATCH
   INSERT INTO stock_order(order_id,item_id,item_amount) VALUES('de305d54-75b4-431b-adb2-eb6b9e546014
', 5, 460000.0);
   INSERT INTO stock_order(order_id,item_id,item_amount) VALUES('de305d54-75b4-431b-adb2-eb6b9e546014
', 6, 50000);
   INSERT INTO stock_order(order_id,item_id,item_amount) VALUES('de305d54-75b4-431b-adb2-eb6b9e546014
', 7, 1200000);
  UPDATE stock_order SET order_state='CLOSED' WHERE order_id='de305d54-75b4-431b-adb2-eb6b9e546014
' IF order_state='OPEN';
END BATCH

在上面的示例中,如果给定订单已被某些其他进程关闭,则条件更新( IF order_state ='OPEN' )将失败,因此将不执行任何插入操作。 这是LWT的一大特色。 它为您的操作提供了强大的线性化保证。

如果您要将这些订单更新和变异分布在不同的分区中,那么LWT将不适用,您将回到最终的一致性世界。

用户定义的聚合

最后但并非最不重要的一点是,最近发布的用户定义的聚合(UDA)功能在单个分区上效果最佳。 在不深入研究技术细节的情况下,您应该知道,Cassandra中的聚合函数在最后写赢对帐逻辑之后应用于协调器节点。

因此,在多个分区或整个表上执行聚合将需要协调器在应用UDA之前从不同节点获取所有数据(实际上是使用内部分页 )。 在这种情况下,聚合查询的延迟会绑定到最慢节点的延迟。 此外,多分区聚合需要获取更多数据,因此会大大增加查询持续时间。

出于所有这些原因,当前的建议是仅将UDA保留给单个分区,如果要在其中聚合整个表或几个分区,则依赖Apache Spark

有关UDA的更多详细信息,您可以阅读以下博客文章:

翻译自: https://www.javacodegeeks.com/2016/02/importance-single-partition-operations-cassandra.html

cassandra

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值