通过分布式数据库聚合作业优化网络带宽

2024-05-12

我有一个分布式/联合数据库,结构如下:

  1. 数据库分布在三个地理位置(“节点”)
  2. 每个节点集群有多个数据库
  3. 关系数据库是 PostgreSQL、MySQL、Oracle 和 MS SQL Server 的混合体;非关系数据库是 MongoDB 或 Cassandra
  4. 每个节点内以及跨节点联合的松散耦合是通过 RabbitMQ 实现的,每个节点都运行一个 RabbitMQ 代理

我正在为跨节点联合的作业(即非节点本地的作业)实现只读节点间聚合作业系统。这些作业仅执行“获取”查询 - 它们不会修改数据库。 (如果作业的结果打算进入一个或多个数据库,那么这是通过一项单独的作业来完成的,该作业不属于我正在尝试优化的节点间作业系统。)我的目标是最小化这些作业所需的网络带宽(首先最小化节点间/WAN带宽,然后最小化节点内/LAN带宽);我假设每个 WAN 链路有一个统一的成本,每个 LAN 链路有另一个统一的成本。这些工作对时间不是特别敏感。我在节点内执行一些 CPU 负载平衡,但不在节​​点之间执行。

相对于集群本地或特定数据库的数据库写入量,聚合作业通过 WAN/LAN 传输的数据量较小,因此跨联合完全分布数据库是不切实际的。

我用于最小化网络带宽的基本算法是:

  1. 给定一个在分布于整个联合的数据集上运行的作业,管理器节点向每个其他节点发送一条包含相关数据库查询的消息。
  2. 每个节点运行其查询集,使用 gzip 压缩它们,缓存它们,并将它们的压缩大小发送到管理器节点。
  3. 管理器移动到包含多个数据的节点(具体地,移动到集群内具有最多数据且具有空闲核的机器);它从其他两个节点和集群内的其他机器请求其余数据,然后运行作业。

如果可能,作业会使用分而治之的方法来最大限度地减少所需的数据共置量。例如,如果作业需要计算整个联盟中所有销售数据的总和,则每个节点在本地计算其销售总和,然后在管理节点上聚合(而不是将所有未处理的销售数据复制到管理节点) 。但是,有时(例如在位于不同节点的两个表之间执行联接时)需要数据共置。

为了优化这一点,我做的第一件事是聚合作业,并以十分钟的周期运行聚合的作业(机器都运行 NTP,所以我可以合理地确定“每十分钟”在每个节点上意味着相同的事情) )。目标是让两个作业能够共享相同的数据,从而降低传输数据的总体成本。

  1. 给定查询同一个表的两个作业,我生成每个作业的结果集,然后取两个结果集的交集。
  2. 如果两个作业都计划在同一节点上运行,则网络传输成本的计算方式为两个结果集之和减去两个结果集的交集。
  3. 这两个结果集存储到 PostgreSQL 临时表(在关系数据的情况下)或存储到选择运行作业的节点处的临时 Cassandra 列族/MongoDB 集合(在 nosql 数据的情况下);然后,针对合并的结果集执行原始查询,并将数据传递给各个作业。 (此步骤仅对组合结果集执行;单个结果集数据只是简单地传递到其作业,而无需首先存储在临时表/列族/集合中。)

这会提高网络带宽,但我想知道是否有一个框架/库/算法可以对此进行改进。我考虑的一个选项是在节点上缓存结果集,并在确定网络带宽时考虑这些缓存的结果集(即,除了当前预先安排的共置作业集之外,尝试跨作业重用结果集,以便例如在一个 10 分钟周期运行的作业可以使用前一个 10 分钟结果集的缓存结果集),但除非作业使用完全相同的结果集(即除非它们使用相同的 where 子句),否则我不知道一般-填补结果集中空白的目的算法(例如,如果结果集使用子句“where N > 3”,而另一个作业需要使用子句“where N > 0”的结果集,那么我可以使用什么算法确定我需要将原始结果集与带有子句“where N > 0 AND N


我已经开始实施我的问题解决方案。

为了简化节点内缓存并简化 CPU 负载平衡,我在每个数据库集群(“Cassandra 节点”)上使用 Cassandra 数据库来运行聚合作业(之前我手动聚合本地数据库结果集) ) - 我使用单个 Cassandra 数据库来存储关系数据、Cassandra 和 MongoDB 数据(缺点是一些关系查询在 Cassandra 上运行速度较慢,但​​这可以通过以下事实来弥补:单个统一聚合数据库更容易执行)维护而不是单独的关系和非关系聚合数据库)。我也不再在十分钟的时期内聚合作业,因为缓存使得这个算法变得不必要。

节点中的每台机器都引用一个名为 Cassandra_Cache_[MachineID] 的 Cassandra 列族,用于存储已发送到 Cassandra 节点的 key_ids 和 column_ids。 Cassandra_Cache 列族由 Table 列、Primary_Key 列、Column_ID 列、Last_Modified_Timestamp 列、Last_Used_Timestamp 列以及由 Table|Primary_Key|Column_ID 组成的复合键组成。 Last_Modified_Timestamp 列表示来自源数据库的数据的last_modified 时间戳,Last_Used_Timestamp 列表示聚合作业上次使用/读取数据的时间戳。当 Cassandra 节点向机器请求数据时,机器会计算结果集,然后获取结果集与其 Cassandra_Cache 中的表|键|列的集合差,这些表|键|列与其 Cassandra_Cache 中的行具有相同的 Last_Modified_Timestamp(如果时间戳不匹配,则缓存的数据已过时并与新的 Last_Modified_Timestamp 一起更新)。然后,本地计算机将设置的差异发送到 Cassandra 节点,并使用设置的差异更新其 Cassandra_Cache,并更新用于组成结果集的每个缓存数据的 Last_Used_Timestamp。 (为每个表|键|列维护单独的时间戳的更简单的替代方法是为每个表|键维护一个时间戳,但这不太精确,并且表|键|列时间戳并不太复杂。) Cassandra_Cache 之间的同步仅要求本地计算机和远程节点发送与每个作业关联的 Last_Used_Timestamp,因为作业中的所有数据都使用相同的 Last_Used_Timestamp。

Cassandra 节点使用从节点内部接收的新数据以及从其他节点接收的数据更新其结果集。 Cassandra 节点还维护一个列族,该列族存储与每台计算机的 Cassandra_Cache 中相同的数据(Last_Modified_Timestamp 除外,仅在本地计算机上需要它来确定数据何时过时),以及指示数据是否来自的源 ID来自节点内或来自另一个节点——该id区分不同节点,但不区分本地节点内的不同机器。 (另一种选择是使用统一的 Cassandra_Cache,而不是在每台机器上使用一个 Cassandra_Cache 并为节点使用另一个 Cassandra_Cache,但我认为增加的复杂性不值得节省空间。)

每个 Cassandra 节点还维护一个 Federated_Cassandra_Cache,它由已从本地节点发送到其他两个节点之一的 {Database, Table, Primary_Key, Column_ID, Last_Used_Timestamp} 元组组成。

当作业通过管道时,每个 Cassandra 节点都会使用本地结果集更新其节点内缓存,并完成可以在本地执行的子作业(例如,在对多个节点之间的数据求和的作业中,每个节点将其节点内数据,以最大限度地减少需要在节点间联合中共同定位的数据量) - 如果子作业仅使用节点内数据,则可以在本地执行。然后,管理器节点确定在哪个节点上执行剩余的工作:每个 Cassandra 节点可以通过获取其结果集与已缓存的结果集子集的集合差值,在本地计算将其结果集发送到另一个节点的成本到其 Federated_Cassandra_Cache,并且管理器节点最小化成本方程 [“从 NodeX 传输结果集的成本”+“从 NodeY 传输结果集的成本”]。例如,Node1 将其结果集传输到 {Node2, Node3} 需要花费 Node1 {3, 5},Node2 将其结果集传输到 {Node1, Node3} 需要花费 {2, 2},Node3 需要花费 {4, 3}将其结果集传输到 {Node1, Node2},因此该作业在 Node1 上运行,成本为“6”。

我对每个 Cassandra 节点使用 LRU 驱逐策略;我最初使用最旧的优先驱逐策略,因为它更容易实现,并且需要更少的写入 Last_Used_Timestamp 列(每次数据更新一次,而不是每次数据读取一次),但 LRU 策略的实现结果并不过分复杂且 Last_Used_Timestamp 写入不会造成瓶颈。当 Cassandra 节点达到 20% 的可用空间时,它会逐出数据,直到达到 30% 的可用空间,因此每次逐出的大小大约为总可用空间的 10%。节点维护两个时间戳:最后驱逐的节点内数据的时间戳,以及最后驱逐的节点间/联邦数据的时间戳;由于节点间通信相对于节点内通信的延迟增加,逐出策略的目标是让 75% 的缓存数据为节点间数据,25% 的缓存数据为节点内数据,可以通过让每次驱逐的 25% 为节点间数据、每次驱逐的 75% 为节点内数据来快速近似。驱逐工作如下:

while(evicted_local_data_size < 7.5% of total space available) {
    evict local data with Last_Modified_Timestamp < 
        (last_evicted_local_timestamp += 1 hour)
    update evicted_local_data_size with evicted data
}

while(evicted_federated_data_size < 2.5% of total space available) {
    evict federated data with Last_Modified_Timestamp < 
        (last_evicted_federated_timestamp += 1 hour)
    update evicted_federated_data_size with evicted data
}

在从节点内的计算机和其他节点收到驱逐确认之前,不会永久删除被驱逐的数据。

然后,Cassandra 节点向其节点内的计算机发送通知,指示新的 last_evicted_local_timestamp 是什么。本地计算机更新其 Cassandra_Cache 以反映新的时间戳,并在完成后向 Cassandra 节点发送通知;当 Cassandra 节点收到来自所有本地计算机的通知时,它会永久删除被逐出的本地数据。 Cassandra 节点还会向远程节点发送带有新的 last_evicted_federated_timestamp 的通知;其他节点更新其 Federated_Cassandra_Caches 以反映新的时间戳,并且 Cassandra 节点在收到来自每个节点的通知时永久删除被驱逐的联邦数据(Cassandra 节点会跟踪数据来自哪个节点,因此在收到驱逐后来自 NodeX 的确认(节点可以在收到来自 NodeY 的驱逐确认之前永久删除被驱逐的 NodeX 数据)。在所有计算机/节点发送通知之前,如果 Cassandra 节点从尚未逐出旧数据的计算机/节点收到结果集,则它会在其查询中使用缓存的逐出数据。例如,Cassandra 节点有一个已驱逐的本地 Table|Primary_Key|Column_ID 数据,同时本地计算机(尚未处理驱逐请求)未在其结果集中包含 Table|Primary_Key|Column_ID 数据,因为它认为Cassandra 节点的缓存中已包含数据; Cassandra 节点从本地计算机接收结果集,并且由于本地计算机尚未确认逐出请求,因此 Cassandra 节点将缓存的逐出数据包含在其自己的结果集中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过分布式数据库聚合作业优化网络带宽 的相关文章

  • 数据加密

    存储大量信用卡信息的数据库是我们刚刚完成的系统中不可避免的一部分 不过 我想要的是卡号的最终安全性 我们可以设置一种加密和解密机制 但我们自己无法解密任何给定的号码 我所追求的是一种即使在数据库级别也能保护这些信息的方法 这样任何人都无法进
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 使用 A 星查找路径的启发式函数

    I am trying to find a optimal solution for the following problem 每个节点内表示的数字表示为 x y 一个节点的相邻节点总是有一个y值为 当前节点 y 值 1 更改的成本为 1
  • Android 中读取未提交的事务

    我正在进行大量数据库操作 这会向我的数据库添加大约 10 000 条记录 由于这可能需要很长时间 因此最好使用事务 db startTransaction do write operations db setTransactionSucce
  • 在 Android 中获取联系方式需要花费大量时间?

    您好 目前正在做一个与联系人相关的项目 我正在从联系人中获取详细信息 电子邮件 电话号码和联系人姓名 效果很好 但问题是获取联系方式需要很长时间 超过 1000 个联系人 包括从社交网站同步的联系人 这样我就放了一个Asynchronous
  • 如何按关系的数量或成员对 Doctrine DQL 查询进行排序?

    我正在尝试创建一个查询 用于从 Doctrine 数据库中检索对象 并按特定一对多关系的成员数量排序 更具体地说 我有两个实体 Person 和 Federation 一个人可以是一个联盟的成员 人具有 联盟 关系 并且一个联盟可以有n人
  • 如何在 Sequelize 现有模型中添加列?

    我使用此命令添加了模型和迁移文件 node modules bin sequelize model generate name User attributes firstName string lastName string email s
  • 优化两个三位数乘积的最大回文数?

    我正在研究一个面试问题 我被问到这个问题 我应该编写一个程序 从两个三位数的乘积中找到最大的回文数 这里是question https projecteuler net problem 4 我想出了这种从底部开始的蛮力方法 public c
  • 布隆过滤器的使用

    我正在努力理解布隆过滤器的用处 我了解了它的底层逻辑 空间压缩 快速查找 误报等 我只是不能将这个概念应用到现实生活中 因为它是有益的 一种常见的应用是在 Web 缓存中使用布隆过滤器 我们使用布隆过滤器来确定给定的 URL 是否在缓存中
  • JPA中如何连接多个数据库?

    我有一个 Spring Boot 应用程序 当前使用 JPA 连接到单个数据库 application properties 文件中的连接详细信息 spring datasource url jdbc oracle thin localho
  • 无法将 CLOB 数据存储到 DB2 中的 CLOB 定义的列中

    我猜这是一个重复的问题 但尚未找到合适的解决方案 基本上 我试图通过以下方式将大一点的 XML 即 32000 个字符 插入到 CLOB 列中 DB2程序 插入失败并出现以下错误 看起来 DB2 正在将输入视为 String 而不是 CLO
  • 如何提高洪水填充例程的性能?

    我正在我的应用程序中实现四路洪水填充 伪代码如下 Flood fill node target color replacement color 1 If the color of node is not equal to target co
  • 我们可以使用sql列出MS Access数据库中的所有表吗?

    我们可以使用 sql 找到 ms access 中的所有表吗 就像我们在 sql server 中所做的那样 select from sys tables 在sqlite中 SELECT FROM sqlite master where t
  • 基于 2 个输入的伪随机数生成器 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要根据 2 个输入值 X 和 Y 生成一个伪随机数 给定相同的 X 和 Y 值 我需要得到相同的结果 结果应介于 0 和 1 之间 含
  • 如何检测图像是否像素化

    之前有人在 SO 上提出过这样的问题 在Python中检测像素化图像 https stackoverflow com questions 12942365 detecting a pixelated image in python还有关于q
  • 如何使用 SharedPreferences 保存多个值?

    我正在开发一个字典应用程序 在我的应用程序中 我假设用户想要保存最喜欢的单词 我决定使用共享首选项保存这些值 我知道 SQLite 和文件更好 但我坚持使用 SharedPreferences 所以继续使用它 下面是我的代码 Overrid
  • 测量数组的“无序”程度

    给定一个值数组 我想找到总 分数 其中每个元素的分数是数组中出现在其之前的具有较小值的元素的数量 e g values 4 1 3 2 5 scores 0 0 1 1 4 total score 6 O n 2 算法很简单 但我怀疑可以通
  • 机器人探索算法

    我正在尝试为机器人设计一种算法 试图找到位于未知位置的旗帜 该旗帜位于一个包含障碍物的世界中 机器人的任务是夺取旗帜并将其带到他的基地 代表他的起始位置 机器人在每一步只能看到有限的邻域 他事先不知道世界是什么样子 但他有无限的内存来存储已
  • 关于逻辑/算法的想法以及如何防止线程写入 Sql Server 中的竞争

    我有以下逻辑 public void InQueueTable DataTable Table int incomingRows Table Rows Count if incomingRows gt RowsThreshold async
  • 我应该检查代码中的数据库约束还是应该捕获数据库抛出的异常

    我有一个将数据保存到名为 作业 的表中的应用程序 Jobs 表有一个名为 Name 的列 该列具有 UNIQUE 约束 名称列不是主键 我想知道在尝试保存 更新新条目之前是否应该自己检查重复条目 或者最好等待数据访问层抛出异常 如果这个应用

随机推荐

  • 如果 DirectoryInfo.GetFiles().Length 超过 Int32.MaxValue 怎么办?

    由另一个question https stackoverflow com questions 3766540 error on maximum number of files 3767265 3767265关于文件夹中的最大文件数 我注意到
  • Python argparse 作为函数

    以这种方式获取命令行参数有什么本质上的错误吗 我的意思是把参数解析放入它自己的函数中 它会被认为是非 Pythonic 或更严重吗 usr bin python import argparse def getArgs argv None p
  • 表达式 >.Compile() 的逆向?

    因为我们可以 Expression
  • 按 Enter 键提交消息?

    我正在开发一个基于本教程使用 Meteor 构建的聊天应用程序 http code tutsplus com tutorials real time messaging for meteor with meteor streams net
  • 在 Hive 中获取数据的交集

    我在配置单元中有以下数据 userid cityid 1 15 2 15 1 7 3 15 2 8 3 9 3 7 我只想保留具有 cityid 15 和 cityid 7 的用户 ID 在我的示例中 它将是用户 ID 1 和 3 我试过
  • 如何在 C# 中使用窗口窗体创建动态下拉列表

    我正在尝试为朋友的手机商店构建一个简单的库存程序 我想使用C 并访问数据库来存储数据 DB 将有 2 个主要列表 devices 品牌 型号 颜色 价格 库存 最小库存 parts 品牌 型号 描述 库存 最小库存 GUI 将使用多个下拉列
  • yaml / yaml 多行转义序列中的 Markdown?

    是否可以在 yaml 中存储未转义的 Markdown 文档 我测试过 key markdown text block that could have any combination of line breaks gt etc etc 这是
  • iOS模拟器找不到SDK,可能需要重新安装SDK

    在这里 我遇到了另一个问题 今天正在开发一个 iOS 应用程序 当我运行 iPhone 5 0 模拟器的应用程序时 仅在该模拟器上遇到了一些奇怪的问题 当我尝试一次又一次地运行该模拟器时 我的 MacBook 屏幕上出现了两个弹出警报窗口
  • 根据屏幕尺寸更改图像 src

    我正在尝试使用媒体查询根据屏幕尺寸更改图像 src 我尝试过背景 url x 但它不起作用 我在某处读到我应该使用 content url x 代替 但是当我这样做时 我得到一个空白页面 谁能告诉我我的代码有什么问题吗 HTML div c
  • 如何查询多对多表(一个表的值成为列标题)

    给定此表结构 我想展平多对多关系 并将一个表的名称字段中的值设置为列标题 并将同一表中的数量设置为列值 目前可行的想法是将值放入字典 哈希表 中并用代码表示这些数据 但我想知道是否有 SQL 方法可以做到这一点 我还使用 Linq to S
  • 代码编译期间遇到警告消息“使用或覆盖已弃用的 API”

    我编译了我的程序并收到以下错误 我该如何解决呢 Note ClientThreadClients java uses or overrides a deprecated API Note Recompile with Xlint depre
  • 动画图像视图

    目前我正在开发一款游戏 这是我的游戏的详细信息 用户应选择正确的图像对象 我希望图像从左到右加速 当他们到达终点时 他们应该再次出现在活动中 这是我正在处理的屏幕截图 我有 5 个图像视图 它们应该会加速 您有此类动画的示例代码吗 非常感谢
  • 将光栅图像转换为矢量图形的建议

    如果一个人想要将大量光栅图像批量转换为矢量图形 是否有任何工具可以很好地做到这一点 例如 考虑任何具有标准形状 椭圆形 矩形 和文本的图表 Inkscape 用途 http www inkscape org doc tracing tuto
  • 如何修复在 Windows 终端中启动“powershell.exe”时出现的错误 0x800700c1?

    最近我在 Windows 终端中遇到以下错误 error 0x800700c1 when launching C Users Dry C Desktop AppData Local Microsoft WindowsApps Microso
  • Delphi中的抽象类

    我正在使用一个具有许多抽象类的组件套件 现在我想应用多态性 但在创建对象时收到错误抽象类 即使我不需要 我是否应该重写所有虚拟方法 有什么解决方法或解决方案吗 为了创建类的实例 您需要重写所有声明为虚拟抽象的方法 即使您不使用它们 如果您确
  • ListView ColumnHeader.Name 为空字符串

    我创建了一个 WinFormsListView作为具有四列的详细视图 我在设计器中为每一列指定了名称 但是在访问每一列时ColumnHeader通过ListView Columns属性 我找到每个ColumnHeader Name是一个空字
  • TextBoxFor @Value(大写)而不是@value

    这只是出于好奇 为什么这段代码有效 Html TextBoxFor x gt x Age new Value 0 这不是 Html TextBoxFor x gt x Age new value 0 请注意其中的大写 V Value I k
  • 如何从左向右滑动文本和图像并具有滑动效果[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • PySpark:如何将带逗号的列指定为小数

    我正在使用 PySpark 并加载csv文件 我有一列包含欧洲格式的数字 这意味着逗号替换点 反之亦然 例如 我有2 416 67代替2 416 67 My data in csv file looks like this ID Reven
  • 通过分布式数据库聚合作业优化网络带宽

    我有一个分布式 联合数据库 结构如下 数据库分布在三个地理位置 节点 每个节点集群有多个数据库 关系数据库是 PostgreSQL MySQL Oracle 和 MS SQL Server 的混合体 非关系数据库是 MongoDB 或 Ca