Apache Cassandra和Apache Ignite:关系并置和分布式SQL

为什么80%的码农都做不了架构师?>>>   hot3.png

在上一篇文章中,回顾和总结了Cassandra中使用的查询驱动数据模型(或者说非常规数据模型)方法论的缺陷。事实证明,如果不对查询有深入的了解,通过该方法论将无法开发高效的应用。实际上,这种场景的应用架构上会变得更加的复杂,难于维护,并且会造成很大的数据冗余。

此外,这个问题通常会被这样的观点掩盖:“如果想要扩展性、速度以及高可用性,那么就得准备存储多份数据,并且牺牲SQL和强一致性。”,这个论调十年前可能是正确的,但是现在完全错误!

没那么夸张,我们选择了另一个ASF成员,Apache Ignite。在本文中,会讲解基于Ignite的应用架构,然后衡量它的维护成本。

我们选择的应用仍然是跟踪所有厂商生产的车辆,然后了解每个单一厂商的产能,如果看过第一篇文章,那么应该知道关系模型如下:

下一步,可以使用Ignite的CREATE TABLE命令创建这三个表,然后运行由SQL驱动的应用了么?不一定,如果不需要对存储于不同表中的数据进行关联操作,那么是可以的。但是根据前文,前提是应用需要支持两种关联的查询:

  1. Q1:获取一个厂商在特定的时间段内生产的车型。
  2. Q2:获取一个厂商特定车型的产量。

在Cassandra的案例中,我们为每个查询创建了一张表规避了关联的问题,那么用Ignite,是不是还要经历同样的过程?完全不用。事实上,Ignite的非并置的关联已经完全可用,如果三个表已经建好了,那么不需要什么额外的工作。但是,这没有比并置的高效和快速。因此,首先要多学习一下关系并置,然后了解这个概念在Ignite中是如何使用的。

基于并置关联的数据模型

关系并置在Ignite(还有其他的分布式数据库,比如Google Spanner以及MemSQL)中是一个强大的概念,它可以在以一个集群节点上存储相关的数据。那么哪些数据是相关的呢?尤其是在关系数据库的背景下,这非常简单,只需要在业务对象之间标示一个父子关系,在CREATE TABLE语句中指定一个关系键就可以了,剩下的就交给Ignite了!

还是拿车辆和厂商的应用举例,使用厂商作为父实体,车辆作为子实体是合理的。比如,按照这样配置好之后,某个厂商生产的所有车辆数据都会存储于同一个节点上,如下图所示:

如图所示,丰田生产的车辆都存储于节点1,而福特生产的车辆都存储于节点2,这就是关系并置,车辆都会存储于对应的厂商所在的节点上。

要做到这样的数据分布,Vendor表的SQL定义如下:

CREATE TABLE Vendor (id INT PRIMARY KEY,name VARCHAR,address VARCHAR
);

厂商数据会在整个集群中随机地分布,Ignite会使用主键列计算厂商数据所在的节点。 下一个是Car表:

CREATE TABLE Car (id INT,vendor_id INT,model VARCHAR,year INT,price float,PRIMARY KEY(id, vendor_id)
) WITH "affinityKey=vendor_id";

车辆表有一个affinityKey参数,配置为vendor_id列,它告诉Ignite,车辆存储于vendor_id对应的集群节点。

Production表上重复同样的过程,它的数据也是存储于vendor_id对应的集群节点上,如下:

CREATE TABLE Production (id INT,car_id INT,vendor_id INT,country VARCHAR,total INT,year INT,PRIMARY KEY(id, car_id, vendor_id)
) WITH "affinityKey=vendor_id";

这样数据模型就建完了,下一步就进入应用的代码,然后开发必要的查询。

带关联的SQL查询

Ignite集群可以使用我们熟悉的SQL进行查询,它支持分布式的SQL关联以及二级索引。 Ignite支持两种类型的关联:并置和非并置。假定要关联的表已经并置,并且本地数据全部可用,那么并置的关联会避免数据(关联所需的)的移动,这是在分布式数据库中效率最高、性能最好的。如果部分表无法实现关系并置,但是还需要进行关联,那么非并置的关联就是一个备份计划。这种类型的关联速度较慢,因为在关联时它需要在集群节点间进行数据的移动。

之前,已经配置好了VendorCarProduction表,下一步就是利用并置关联的优势,为Q1写一个SQL:

SELECT c.model, p.country, p.total, p.year FROM Vendor as v
JOIN Production as p ON v.id = p.vendor_id
JOIN Car as c ON c.id = p.car_id
WHERE v.name = 'Ford Motor' and p.year >= 2017
ORDER BY p.year;

还能更快么?当然能。下面为Vendor.nameProduction.year列定义二级索引:

CREATE INDEX vendor_name_id ON Vendor (name);
CREATE INDEX prod_year_id ON Production (year);

针对Q2的查询也不需要额外的工作:

SELECT p.country, p.total, p.year FROM Vendor as v
JOIN Production as p ON v.id = p.vendor_id
JOIN Car as c ON c.id = p.car_id
WHERE v.name = 'Ford Motor' and c.model = 'Explorer';

现在,如果老板要求增加一个新特性时,很快就能构造出一套新的SQL满足他。 完成!作为比较,如果要支持Q2,可以看看基于Cassandra的架构是怎么搞的。

架构简化:任务完成!

Ignite的基于关系并置的数据模型,针对Cassandra的基于查询驱动的模型有如下的优点:

  • 应用的数据层基于熟悉的关系模型进行建模,易于维护;
  • 数据使用标准的SQL语法进行访问;
  • 关系并置提供了现代分布式数据库的更多好处:
    • 高效和高性能的分布式关联;
    • 并置计算;

使用Ignite替代Cassandra,简化的软件架构并不是唯一的好处,过段时间,还会有关于强一致性和内存极性能方面的想法。

本文译自Denis Magda的博客。

转载于:https://my.oschina.net/liyuj/blog/1615008

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/255579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android高级开发专题晋升班

Android高级开发专题晋升班 适用人群:1-3年以上经验的开发者丨学员平均薪酬20K/月转载于:https://www.cnblogs.com/lythonliu/p/6285531.html

使用opencv简单的播放AVI程序(40行)

学习OPENCV的第一个例子 #include <highgui.h> #include <cassert> #include <iostream> #include <Windows.h> using namespace std; void OnTrackbarSlide(int pos);int g_slider_position 0; CvCapture *g_capture NULL; int main(int argc , cha…

【纠错】——mysql Authentication plugin ‘caching_sha2_password‘ is not supported问题处理

mysql Authentication plugin ‘caching_sha2_password’ is not supported问题处理 使用mysql8.0版本&#xff0c;登录失败&#xff0c;提示 Authentication plugin ‘caching_sha2_password’ is not supported。 原因是在MySQL 8.0以后&#xff0c;默认的密码加密方式是cac…

关于EL表达式取值的问题

EL表达式取值时,如果没有指定作用域,EL表达式会自动按照作用域的大小,从小到大依次去找;比如${s},会自动按照"pageContext,request,session,application"的顺序去找属性名为s的属性.如果找到,则显示.否则,什么都不显示. 当Map中存整数时,如果想采用EL表达式取值,Map的…

统计信息自动收集任务失效原因排查

环境&#xff1a;Oracle 11.2.0.3 RAC问题&#xff1a;统计信息自动收集任务失效原因排查 1.查看自动任务的状态2.进一步查看其它信息3.解决问题1.查看自动任务的状态 查看自动任务的状态&#xff0c;确认是enabled状态&#xff1a; SQL> select client_name,status from db…

Markdown使用

#一级标题 ##二级标题 ###三级标题 斜体 粗体 斜体粗体 代码段> 删除内容效果是&#xff1a; 这是一级标题 这是二级标题 这是三级标题 这是斜体这是粗体这是斜体粗体 代码段 FileInputStream is new FileInputStream("text"); byte[] iput new byte[1024]; is.…

灰度图的width和widthstep的区别

灰度图的width是表示图像的每行像素数&#xff0c;widthstep指表示存储一行像素需要的字节数。 在OpenCV里边&#xff0c;widthStep必须是4的倍数&#xff0c;从而实现字节对齐&#xff0c;有利于提高运算速度。 如果8U单通道图像宽度为3&#xff0c;那么widthStep是4&#xff…

【pyradiomics学习】——安装pyradiomics以及简单示例

目录 数据集下载&#xff1a; 示例代码 参考文献&#xff1a; bug修复 运行结果&#xff1a; 数据集下载&#xff1a; https://www.jianguoyun.com/p/DcEwQq0Q45bOBxj09JYC (访问密码: gd8dmv) 示例代码 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 20…

最新Django2.0.1在线教育零基础到上线教程(九)

演示地址&#xff1a; http://mxonline.mtianyan.cn 教程仓库地址1: https://github.com/mtianyan/DjangoGetStarted 教程仓库地址2: https://github.com/mtianyan/Mxonline2 教程仓库地址3: https://github.com/mtianyan/Mxonline3 9-1 讲师列表页 teacherlist 和 teacher det…

过滤器 拦截器 区别

转 http://www.cnblogs.com/wangyuyu/archive/2013/07/02/3167354.html1、拦截器是基于java的反射机制的&#xff0c;而过滤器是基于函数回调 2、过滤器依赖与servlet容器&#xff0c;而拦截器不依赖与servlet容器 3、拦截器只能对action请求起作用&#xff0c;而过滤器则可以对…

php --魔术常量 /魔术方法

魔术常量&#xff1a;1. __LINE__返回文件中的当前行号。2. __FILE__返回所在文件的完整路径。包含文件名3. __FUNCTION__返回所在函数名称。4. __CLASS__返回所在类的名称。5. __METHOD__返回所在类方法的名称。需要注意__METHOD__返回的是"class::function"的形式&…

【pyradiomics学习】——影像组学特征

目录 1、形状特征&#xff08;14个&#xff09; 2、一阶特征&#xff08;18个&#xff09; 灰度共生矩阵特征&#xff08;24个&#xff09; 灰度区域大小矩阵特征&#xff08;16个&#xff09; 灰度行程矩阵特征&#xff08;16个&#xff09; 邻域灰度差矩阵特…

NLP系列学习:前向算法和后向算法

在上一篇文章里,我们简单的概述了隐马尔科夫模型的简单定义在<CRF-tutorial>这一篇文章里,我们可以看到HMM经过发展之后是CRF产生的条件,因此我们需要学好隐马尔科夫模型.在这一部分,我比较推荐阅读宗成庆老师的<自然语言处理>这本书,这一部分宗老师写的很不错,相关…

Java日期处理 开始时间-结束时间查询

//开始时间 timeBegin " 00:00:00"; //结束时间 timeEnd " 23:59:59"; //时间转换 SimpleDateFormat format new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //Java时间类型转换成Long类型(可封装成工具类) public static Long stringToLong(St…

angular路由操作中'#'字符的解决办法

var appangular.module("myapp",["ngRoute"]);app.controller("ctr",function($scope){});//angular1.6.0以上版本需要配置app.config(["$locationProvider",function($locationProvider){ $locationProvider.hashPrefix(""…

【TypeError: float() argument must be a string or a number, not ‘map’】

初始 相关系数过滤法调用函数 from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr SelectKBest(lambda X,Y:np.array(map(lambda x:pearsonr(x,Y),X.T)).T,k2) .fit_transform(X_test,y_test) TypeError: float() argument must be a strin…

CvScalar

CvScalar定义可存放1—4个数值的数值&#xff0c;其结构如下。 typedef struct CvScalar { doubleval[4]; } CvScalar; CvScalar pt&#xff1b; 如果使用的图像是1通道的&#xff0c;则pt.val[0]中存储数据 如果使用的图像是3通道的&#xff0c;则pt.val[0]&#xff0c;pt…

UVA1493 - Draw a Mess(并查集)

UVA1493 - Draw a Mess(并查集) 题目链接 题目大意:一个N * M 的矩阵&#xff0c;每次你在上面将某个范围上色&#xff0c;不论上面有什么颜色都会被最新的颜色覆盖&#xff0c;颜色是1-9&#xff0c;初始的颜色是0.最后输出这个矩形中。每一个颜色有多少个。某个范围这个分为了…

Hyper-v Server 2012 Release Candidate 部署体验

很多人知道&#xff0c;Microsoft Hyper-V分为两种类型&#xff1a;一种是作为Windows Server的一个组件&#xff0c;另一种是作为虚拟化产品的单独服务器。虽然两者都是技术上的Hyper-V&#xff0c;每个版本的特性和用例各不相同。 Hyper-V Server直接在物理机器硬件上运行&am…

Unity 读取资源(图片)

方法一&#xff1a; 采用Resource.Load方法读取&#xff0c;读取在Unity中Assets下Resources目录下的资源名&#xff08;不采用后缀&#xff09;。 //图片放在Asset/Resources/ Texture2D tex (Texture2D)Resources.Load("图片名称"); 方法二&#xff1a; 采用WWW类…