文章目录
Citus 兼容性评估
结论
1. 对于postgis的支持:
结论:
- 对于ST_AsGeoBuf)这个可以支持表中任意字段的聚集函数支持不好,存在一些bug,需要在sql中通过limit 0 或者子查询等方式绕过限制,进行一些改造适配。其他的postgis函数都支持
- 对于ST_AsGeoBuf(),由于此函数并没有定义combine函数,因此无法被下推到worker执行,这个是函数实现本身的限制,改造可能性较低,因此无法利用到集群优势,同时可能会由于网络传输数据量大时间相比单机更久一点
场景 | 是否支持 | 是否需要改造 |
---|---|---|
对于单表使用ST_AsGeoBuf | 是 | 否 |
对于视图使用ST_AsGeoBuf | 是 | 手动在worker节点创建对应view,或者用子查询limit 0 进行修饰 |
对于视图仅返回常见数据类型和统计字段 | 是 | 否 |
对于视图按照public.ST_Intersects进行过滤 | 是 | 否 |
对于实体表按照public.ST_Intersects进行过滤后按照分组进行二进制编码 | 是 | 否 |
对于视图按照public.ST_Intersects进行过滤后按照分组进行二进制编码 | 是 | 手动在worker节点创建对应view,或者用子查询limit 0 进行修饰 |
子查询,不使用聚合函数 | 是 | 否 |
子查询,对于返回的数据使用聚合函数ST_AsGeoBuf | 是 | 采用临时表的方式实现,性能可能较差,或者用limit 0 进行修饰 |
2. sql功能支持
对于分布式表,INSERT, INSERT … ON CONFLICT, UPDATE, and DELETE都支持
集群环境下不支持的sql功能
查询:
- SELECT … FOR UPDATE work in single-shard queries only
- TABLESAMPLE work in single-shard queries only
- Correlated subqueries are supported only when the correlation is on the Distribution Column.
相关子查询定义参考:https://blog.csdn.net/shiyong1949/article/details/80923083
- Outer joins between distributed tables are only supported on the Distribution Column(不支持2个非亲和分片表的outer join,仅task-tracker执行器支持2个非亲和分片表的inner join)
- Outer joins between distributed tables and reference tables or local tables are only supported if the distributed table is on the outer side(对分片表和参考表的outer join,参考表只能出现在left join的右边或right join的左边)
- Recursive CTEs work in single-shard queries only
- Grouping sets work in single-shard queries only
- 子查询不能参与join,不能出现order by,limit和offset
- 本地表不能和分片表(参考表)混用。
这些限制其实都可以使用某些方法绕过,比如通过pull-push中转解决join问题,或者通过临时表解决其他问题。不过临时表的问题在于会将一个SQL拆成多个SQL。
更新:
在更新上也存在一些限制,它不支持跨分片的更新SQL和事务,‘insert into … select … from …’的支持存在部分限制,插入源表和目的表必须是具有亲和性的分片表,不允许出现Stable and volatile函数,不支持LIMIT,OFFSET,窗口函数,Grouping sets。
当然这些限制也存在对应的回避方法,首先是使用copy代替insert,其次是用SELECT master_modify_multiple_shards(‘…’)实现跨分片更新。
DDL:
上图展示的是对DDL的支持情况,这里面大部分都是支持的,对于不支持的可以通过创建对等的唯一索引代替变更主键,或者使用run_command_on_placements
函数,直接在所有分片位置上执行DDL的方式来进行回避。
3. 事务支持
citus支持分布式事务
执行步骤:
如上图所示,由Coordinator节点负责协调分布式事务的执行,各Worker节点作为参与者参与分布式事务的执行:
-
步骤1和2:Coordinator在本地,以及两个worker节点分别启动一个事务,并把worker节点的事务和Coordiantor上的全局事务进行关联;然后把相关SQL语句推送到对应worker执行;
-
步骤3和4:客户端发起commit后,由Coordinator发起2PC提交协议:
-
PREPARE TRANSACTION
:通知所有参与Worker节点做好事务提交准备,各Worker节点持久化相关数据,反馈可以提交或者需要回滚;COMMIT PREPARED
:当Coordinator节点收到所有Worker节点都投票可以提交事务后,发起提交事务命令,Worker节点收到消息后完成本地事务提交;如果前一阶段有一个Worker节点反馈需要归滚事务,则Coordiantor在本阶段会发送ROLLBACK
命令;
一致性模型:最终一致性
虽然Citus采用2PC协议,保证了在同一个分布式事务中操作的多条记录的原子性更新。但从客户端读取的视角来看,可能会读到中间态的数据(Base中的软状态),是最终一致性的模型。
原因在于Citus并没有引入集群级的全局授时机制,对于只读事务,无法获取集群级的全局一致性快照,而是由各Worker节点自己进行可见性判断,当一个分布式事务正在提交时,在不同的Worker节点提交存在时间差,在这个时间间隙内发起的查询事务,就会在已经提交的Worker节点看到已提交数据,在尚未完成提交的Worker节点看不到同一个事务写入的数据,等所有Worker节点都完成提交后,再次查询又能看到最新一致的数据,因此严格说Citus提供的是最终一致性模型。
隔离级别:读已提交
4. citus性能
当运行INSERT时,Citus首先根据分发列中的值找到正确的分片位置。然后,Citus连接到存储分片放置的工作节点,并对每个分片执行INSERT。从用户的角度来看,由于到工作节点的网络延迟,INSERT需要花费几毫秒的时间来处理。由于Citus协调器节点可以处理并发INSERT,因此可以达到比单机更高的高吞吐量。
Insert Throughput
Update Throughput
同时对于插入的性能提升,citus还支持masterless模式,在这种模式下,每个worker都存储元数据,这样每个worker都可以作为协调者去执行插入操作。
从苏宁发布的数据来及看。用masterless模式插入可以达到每秒30W条。