cassandra数据备份_Cassandra中的数据建模

cassandra数据备份

在关系数据模型中,我们为域中的每个对象建模关系/表。 对于Cassandra,情况并非如此。本文将详细介绍在Cassandra中进行数据建模时需要考虑的所有方面。 以下是Cassandra数据建模的粗略概述。

资料建模

从上图可以看出, 概念数据建模和应用程序查询是构建模型时要考虑的输入。 对于任何建模(无论是关系数据库还是Cassandra),概念数据建模都是相同的,因为它更多地是关于获取有关实体,关系及其属性(因此称为ER模型)所需的系统功能的知识。

考虑以下有关病理实验室门户的示例。 通过此病理实验室门户,实验室可以向同意进行建议的所有测试的门户进行注册。 此外,它还允许患者(用户)在门户网站上注册,以通过他/她选择的实验室来预定测试约会。 这是概念模型的相关部分,将在Cassandra中进行数据建模:

资料建模

Cassandra中的数据建模是查询驱动的。 因此,下一步是确定需要支持的应用程序级查询。 对于所举的示例,这是我们感兴趣的查询列表:

  • 问题1:通过指定的注册号获取实验室详细信息?
  • 问题2:按预订顺序获取给定实验室要处理的所有待处理订单?
  • 问题3:通过用户的电子邮件ID /电话号码查看用户的详细信息?
  • 问题4:获取指定时间段内用户的所有挂单?

映射规则:列出应用程序查询后,将应用以下规则将概念模型转换为逻辑模型。

  • 规则1:列出我们将在其上执行基于相等性查询的属性。 例如:按注册编号查找实验室。
  • 规则2:列出在上一步中列出的查询中必须使用的基于范围的属性。
  • 规则3:应用程序感兴趣的结果是否有排序? 例如:返回用户按其姓名升/降序排序?

从概念模型和查询中,我们可以看到仅在第一季度使用了实体“实验室”。 由于Q1基于等式,因此只能从映射规则中应用规则1。 因此,“实验室”表可以设计如下:

create table lab_detail(registration_number text, name text, address text, primary key(registration_number));

实体“用户”已在第三季度使用。 该查询指定通过电子邮件ID或电话号码获取用户详细信息。 在关系数据库中,我们可以使用电子邮件ID /电话号码之一作为标识符创建单个用户表。 如果表中的数据很大,则可以在非标识符列上创建索引以加快数据检索速度。 但是在Cassandra中,这是以不同的方式建模的。 我们可以使用2个表来解决此问题:

create table users_by_email(email text primary key, phone_number text, first_name text, last_name text, address text);
create table users_by_phone(phone_number text primary key, email text, first_name text, last_name text, address text);

当我们要基于不属于主键的列查询表时,可以使用二级索引 。 但是在表上创建二级索引时必须小心。 不建议在许多情况下使用它们:

  1. 在高/低基数列上创建索引时,这无济于事。 如果我们根据用户标题(Mr / Mrs / Ms)进行索引,则最终将在索引中形成大量分区。
  2. 同样,如果我们在电子邮件ID上创建索引,因为大多数电子邮件ID是唯一的,在这种情况下,最好创建一个单独的表。
  3. 同样,我们不应该在大量更新的列上创建索引。 如果生成的墓碑比压缩过程可以处理的高得多,这些索引可能会产生错误。

如我们所见,二级索引并不适合我们的用户表,最好创建一个满足应用程序目的的其他表。 请注意, 数据复制在Cassandra数据建模中非常普遍。 但是由于性能原因,我们应该限制要复制多少数据。 现在,创建不同表的问题在于,需要注意可能的数据一致性异常。

  • 如果更新在一个表中成功而在另一个表中失败怎么办?
  • 如何在两个表中保持数据一致,以便在两个表中查询用户数据都能获得相同的结果?

尽管Cassandra不支持参照完整性,但是有一些方法可以解决这些问题- 批次和轻量交易 (LWT) 。 注意,与关系数据库一样,Cassandra中的批处理未用于提高性能。 此处的批处理用于实现操作的原子性,而异步查询用于提高性能。 批处理操作的不正确使用可能会由于协调器节点上的更大压力而导致性能下降。 更多关于此这里 。 当有必要在写入之前执行读取时,LWT可用于实现数据完整性(要写入的数据取决于已读取的数据)。 但是,据说LWT查询比常规查询慢许多倍。 使用LWT时,需要特别小心,因为它们的伸缩性不好。

实现此目的的另一种方法是使用实例化视图 。 它们解决了应用程序维护多个表以同步方式引用相同数据的问题。 为了保持数据与基本表一致,Cassandra代替了应用程序维护这些表,而是负责更新视图。 结果,为了保持这种一致性,写操作将受到很小的性能损失。 但是一旦创建了物化视图,我们就可以像对待其他任何表一样对待它。 既然我们已经了解了视图,那么我们可以重新考虑先前的users_by_phone设计:

create table users_by_email(email text primary key, phone_number text, first_name text, last_name text, address text);
create materialized view users_by_phone as
select * from users_by_email where phone_number is not null and email is not

null and primary key(phone_number, email);

注意,“不为空”约束必须应用于主键中的每一列。 因此,到目前为止,我们已经在应用程序工作流程中解决了Q1和Q3。 现在剩下第二和第四季度了:

  • 问题2:按预订顺序获取给定实验室要处理的所有待处理订单?
  • 问题4:获取指定期间内用户的所有挂单?

在一种情况下,必须由用户获取订单详细信息,而在另一种情况下,必须由实验室获取订单详细信息。 在关系数据库中,我们会将订单,用户和实验室建模为不同的关系。 使用读取数据的JOIN查询可以在这些关系上实现Q2和Q4。 由于无法进行读取级别连接,因此必须在Cassandra中以不同的方式进行建模。 必须完成数据非规范化才能实现此用例。 作为非规范化的一部分,数据将被复制。 但是,如前所述,Cassandra的经验法则之一是不要将数据复制视为一件坏事。 与时间相比,我们基本上会在空间上进行权衡。 由于以下原因, Cassandra宁愿在写时联接而不是在读时联接。

  • 可以通过向群集添加更多节点来扩大数据复制的规模,而联接则无法处理大量数据。
  • 同样,数据复制允许具有恒定的查询时间,而分布式联接对协调器节点施加了巨大压力。 因此,它建议写时连接而不是读时连接。 由于实验室和用户总共是两个不同的实体,因此可以使用两个不同的表对这些查询进行建模。

Cassandra的一般建议是尽可能避免客户端加入。 因此,我们使用逻辑模型中的表(orders_for_user)和视图(orders_for_lab)从概念模型中对“订单”实体进行建模,就像之前所做的那样。 创建支持Q4的表时,必须考虑映射规则#1(基于平等的属性:user_id)和#2(基于范围的属性:booking_time)。 将列order_id和test_id作为主键的一部分添加,以支持该行的唯一性。

create table orders_for_user(user_id text, order_id text, lab_id text, test_id text, booking_time timestamp, amount_paid double, primary key(user_id, booking_time, order_id, test_id));

类似地,可以考虑映射规则#1(基于平等的属性:lab_id)和#3(属性的聚类顺序:booking_time)对视图进行建模

create materialized view orders_for_lab as
select * from orders_for_user where lab_id is not null and order_id is not

null and test_id is not null and user_id is not null primary key(lab_id,
booking_time, test_id, order_id, user_id) with clustering order by(booking_time asc, order_id asc, test_id asc, user_id asc);

最后要考虑的一点是,建模数据时不要让分区大小变得太大。 可以将新字段添加到分区键以解决此不平衡问题。 例如:如果某些实验室获得的订单数量比其他实验室多,那么这会通过将更多的负载分配给集群中的少数几个节点而在分区中造成不平衡。 为了解决这个问题,我们可以添加一个bucket-id列,将每个实验室1000个订单分组到一个分区中。 通过这种方式,负载在群集的所有节点之间平均分配。

翻译自: https://www.javacodegeeks.com/2019/05/data-modeling-cassandra.html

cassandra数据备份

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

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

相关文章

Struts2项目中的JSP如何访问Session对象

Struts2 项目中,Session 对象存放在 ValueStack 的 context 对象中,context 是 Map 对象,那么要从 context 对象中获取到 Session 对象,就要指定 key 值。我们查看 ValueStack 的内容: 从 ValueStack 显示的内容可以知…

pom.xml中pom全称_摆脱pom XML…几乎

pom.xml中pom全称介绍 POM文件是XML格式的文件,声明性地描述了要使用Maven构建的Java项目的构建结构。 维护大型Java项目的POM XML文件通常很麻烦。 XML是冗长的,POM的结构也需要维护冗余信息。 多次对工件进行命名是多余的,在groupId和artif…

IntelliJ IDEA for Mac中Maven菜单用法详解

Reload project 你如果修改了 pom.xml 文件,可以点击这个按钮重载 Maven 项目,重载过程会引入新的依赖,会删除不需要的依赖。 Generate Sources and Update Folders 这个按钮是将 src/main/resources 和 src/test/resources 的资源文件编译…

sql 注射_只能在测试中注射吗?

sql 注射本文是关于测试设计和可测试性的一些想法。 我们与我的儿子讨论了一些问题,他的儿子是Java的初级开发人员,目前在匈牙利的EPAM(我工作的同一家公司,但在另一家公司工作)受雇并学习。 本文中的所有内容都是很好…

IntelliJ IDEA查看方法在哪里被调用(Method Usage Search/Method Call Hierarchy)

文章目录Usage SearchCall Hierarchy区别Usage Search 搜索使用的地方,快捷键如下: 你可以把光标移到方法名称处,然后点击右键,找到 Find Usages 菜单项,意思是“找到使用它的地方”。 例如我要查看哪些地方调用 f…

java编程学习方法_在线学习Java编程的最佳方法

java编程学习方法1.简介 Java是使用最广泛的编程语言之一。 根据Github的最新报告 ,Java被列为仅次于JavaScript的第二大最常用的编程语言。 掌握Java的人有很多话题。 好消息是,您可以在线找到很多内容。 在这篇文章中,我们将对所有这些主题…

hibernate 标识符_Hibernate中的标识符

hibernate 标识符Hibernate中的标识符为实体的主键属性建模。 它有助于我们唯一地标识JPA实体。 每个实体都必须定义一个标识符。 同样,它可以是简单的也可以是复合的。 我们可以通过几种方式定义一个Hibernate标识符。 在本教程中,我们将学习如何做。 …

java中延迟_Java中的延迟分配

java中延迟程序员本质上是懒惰的,而similis simili gaudet就像程序是懒惰的一样。 您听说过延迟加载吗? 还是懒惰的单身人士? (不过,我个人更喜欢单一麦芽版本。)如果使用Scala或Kotlin(这也是一…

camel apache_短款Apache Camel K

camel apache您可能已经看到我们在Camel K周围的Apache Camel社区中所做的工作。 Nicola于半年前在他的博客中介绍了Camel K , 就在几个月前,我们正在讨论一个新项目,该项目可以作为Apache Camel的一部分启动。 一个有可能改变人们处理集成方…

java 栈 队列 接口_Java队列接口

java 栈 队列 接口介绍: 队列是FIFO(先进先出)抽象数据类型(ADT)。 换句话说,按插入顺序将元素删除。 java.util.Queue是Java 中的接口,并且从java.util.Collection扩展。 一些常用的Queue实现…

jakarta ee_Jakarta EE 8状态

jakarta ee遵循Jakarta EE的人们可能知道即将发布的Jakarta EE 8在功能上将与Java EE 8等效。其原因是我们想证明从Oracle的传输已经完成,并且我们能够产生这些流程,规范,测试套件以及通过Eclipse Foundation的兼容实现。 到目前为止&#x…

IntelliJ IDEA如何查看接口的实现类以及如何查看被实现的接口

在接口的左边有个向下的小箭头,点击小箭头就能看到接口的实现类和方法的实现: 在实现类的左边有个向上的小箭头,可以查看被实现的接口和被覆盖重写的方法:

c#自定义控件资源释放问题_定义资源

c#自定义控件资源释放问题在Fielding的论文中 ,资源描述为: “可以命名的任何信息”……“文档或图像,临时服务(例如,“洛杉矶今天的天气”),其他资源的集合,非虚拟对象&#xff08…

MySQL数据库存入日期(java.sql.Date)数据,天数会少一天的问题

网络上给的解决办法: 这是数据库服务器时区的问题,即连接参数 serverTimezone 的问题,默认情况下 serverTimezoneUTC,改成 HongKong 或者 Asia/Shanghai 就可以了。如下所示: jdbc:mysql://localhost:3306/test?useU…

spring的bean范围_Spring Bean范围

spring的bean范围介绍: Spring核心容器实例化bean并管理其生命周期。 在定义bean时,我们可以提供其范围。 除非明确提供,否则单例是Spring容器中Bean的默认范围。 Spring提供了五种类型的bean作用域。 在本教程中,我们将探讨它们…

java.util.Date转换成java.sql.Date

// 获取当前的系统时间,以java.util.Date对象返回 Date dateUtil new Date(); // 获取当前的系统时间,以时间戳返回 long l System.currentTimeMillis();时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现…

省编码市编码区县编码_无浪费编码

省编码市编码区县编码本文介绍了如何通过减少软件堆栈中的浪费来高效解决有意义的事件处理问题。 Java通常被视为无法在低内存环境中有效运行的内存猪。 目的是证明许多人认为不可能的事情,有意义的java程序几乎可以在没有内存的情况下运行。 示例流程 在Java的单…

Java日期时间字符串和毫秒相互转换的方法

参考链接: 1.https://www.jb51.net/article/130195.htm 2.https://blog.csdn.net/yhj19920417/article/details/73799842?locationNum10&fps1

谷歌本地不支持websocket_django开发-websocket的实现

今天介绍下如何在django中使用channels实现websocket。其实还可以使用dwebsocket实现websocket,这里不做介绍。首先介绍一个概念ASGI。ASGI异步网关协议接口,一个介于网络协议服务和Python应用之间的标准接口,能够处理多种通用的协议类型&…

我要正式开始《一个项目征服Java中高级体系》

在互联网上经常看到很多人说35岁危机的问题、大厂裁员、互联网寒冬这些问题。我感觉比较幸运的是,在之前大环境还不是很坏时候就被裁了一次,所以我很早就开始做持续的准备,现在不好说一定能怎么样, 至少自己在持续的探索适合自己的…