【问题标题】:using read replication in mysql在 mysql 中使用读取复制
【发布时间】:2013-09-06 15:35:06
【问题描述】:

我有一个 mysql 数据库,每天大约有 1.5 亿次插入,保留期约为 60 天。

  1. 每条记录都以 id 为索引。
  2. 每次更新如下:
    1. 查看记录是否存在。如果是,请使用新数据进行更新。
    2. 或者创建数据。
  3. 删除 60 天前创建的记录。

我的主要用例如下:

运行一些批量查询。例如:

Select (*) from table where prop=val1 and prop2=val2 etc

将返回大量记录,例如。 1M

以下方法好吗:

  1. 拥有一个仅在 id 上具有索引的主数据库。保留 60 天。
  2. 已读取副本数据库。该数据库将在许多列上编入索引
  3. 所有批量查询都将针对只读副本数据库运行。

这是一个好的解决方案吗?

编辑: 我打算使用 Amazon RDS DB,并在他们的文档中找到了这一点:

 Q: Can my Read Replicas only accept database read operations?

只读副本旨在为读取流量提供服务。然而,可能有 是高级用户希望完成数据定义的用例 针对只读副本的语言 (DDL) SQL 语句。例子可能 包括将数据库索引添加到用于 业务报告,无需在相应的索引中添加相同的索引 源数据库实例。如果您希望启用读取以外的操作 对于给定的只读副本,您将需要修改活动数据库 只读副本的参数组,设置“read_only” 参数为“0”。

【问题讨论】:

    标签: mysql replication scaling database-replication


    【解决方案1】:

    回答你的问题:

    以下方法好吗:

    1. 拥有一个仅在 id 上具有索引的主数据库。保留 60 天。
    2. 已读取副本数据库。该数据库将在许多列上编入索引
    3. 所有批量查询都将针对只读副本数据库运行。

    这是一个好的解决方案吗?

    更新

    根据我的看法和经验,不会。

    从技术上讲,此解决方案可能有效,但实际上不适合生产使用。 mysql内置的master-slave replication,只有在从库表和主库表布局一致的情况下才有效。

    您将拥有大约 90 亿条记录 (150 x 60)。我的估计是在磁盘上这可能需要 1TB(每条记录相当于一条推文的大小)。 1.5 亿次插入和 1.5 亿次删除(过期记录)肯定会使索引碎片化,inserts 变慢,需要经常重新构建。

    当您需要多个只读副本时,事情会变得越来越复杂,这是生态系统的自然演变。

    如果您每天有 1.5 亿次插入,您应该考虑使用 NOSQL 数据库。 Mongodb 以前也支持Innodb,不知道现在还支持吗。

    如果您希望坚持使用 MySQL 这样的 RDBMS,您应该使用 Database Sharding 这样的策略。在此策略中,您将数据分段,使负载分布在 MySQL 实例集群中。

    与分片相比,可扩展性稍差的是使用MyISAM 等存储引擎。 MyISAM 不完全符合 ACID,但提供了出色的性能。它支持并发插入。

    【讨论】:

      【解决方案2】:

      @eternal-learner 的回答不正确。

      是的,您概述的方法可能是一个很好的方法。您需要采取一些预防措施:

      1. 在进行索引更改之前确保主从复制工作正常

      2. 仅在slave中进行所有索引更改,并确保只进行不能破坏数据模型逻辑的索引更改(即不要引入新的唯一索引/约束)

      3. 确保在故障转移情况下不能将从站提升为主站,否则您最终会得到一个性能较低的主站,其索引与组中的任何其他从站都不同

      另外——请注意如何进行更新或插入。那里很容易出现竞争条件。

      【讨论】:

      • 请记住,该网站每天会收到 1.5 亿次插入,尝试让它作为学术练习一次就可以了。但不是在生产中使用的可行解决方案。当事情中断时,恢复将是复杂且耗时的(重建所有新索引)。而且,Mysql 复制是异步的。在 slave 上有额外的索引,同步势必会滞后。
      • 我同意如果需要同步/实时操作,那么这不是一个很好的解决方案。但是,如果批量查询可以在定义的时间运行(甚至可能在正确的时间暂停复制),并且如果发生罕见故障时只读副本的重建期是可以容忍的,那么我认为它会正常工作。这些是操作上的权衡——在这种情况下它们是否重要在 OP 中并不明显。
      • @Eternal-Learner 在我的情况下,我不需要实时数据。如果从站落后主站 2 小时也没关系。而且我不打算在失败的情况下将我的奴隶提升为主人
      • @user93796 你是最好的法官,因为你有更多关于用例的数据点。信封计算的背面告诉我,您将拥有 90 亿条记录(1.5 亿 x 60 天)。根据每条记录的大小(假设等于一条推文),在磁盘上它可能接近 1 TB。每天 1.5 亿次删除(过期记录)和 1.5 亿次插入!
      • @user93796,有替代解决方案,但要回答您的原始问题 - 是的,您概述的方法可以工作。
      【解决方案3】:

      我还没有尝试过,但我认为复制不支持主从之间的不同表结构。我没有找到任何来自 Mysql 的文档。这个想法是 mysql 会不时地从 master 到 slaver 重放二进制日志,因此所有结构应该相同以避免冲突。

      要处理庞大的数据库问题,另一种选择是mysql partitioning,或者您可以使用脚本将大量数据重新计算为具有良好索引的小数据。

      【讨论】:

        【解决方案4】:

        如果您的主要用途是 SELECT *,在不同的列上没有连接和多个过滤器,请考虑使用 Fastbit。 Fastbit 实现了可以非常有效地评估的 WAH 压缩位图,并将数据存储为列存储。

        https://sdm.lbl.gov/fastbit/

        对于 MySQL,也许考虑支持“聚集”索引的 TokuDB,或者在 InnoDB 中创建覆盖索引。这只有在您有少量属性组合需要过滤时才真正有效。如果没有,请考虑 fastbit。

        如果您总是过滤相同的属性,那么您可以考虑使用 Flexviews: http://flexvie.ws

        您可以为 select * from table where val1=X and val2=Y 创建一个视图

        或者只是推出您自己的版本。加载数据后: 替换为 summary_table_v2v2 select * from table where val1=X and val2=Y and table.last_update > NOW()-INTERVAL 1 DAY;

        假设 last_update 是一个时间戳列,这将使用最后一天所做的任何更改“刷新”表。

        【讨论】:

          【解决方案5】:

          聚集索引

          无论您使用复制数据库但您的设计数据库不是面向更大的表,您的性能都不会发生任何变化。

          我建议你,阅读这些链接后检查你的设计:

          InnoDb Index Types

          在这里您可以找到一些关于仅使用 innodb 表的聚集索引的示例。

          60 million entries, select entries from a certain month. How to optimize database?

          它适用于 60 到 5 亿行。

          搜索引擎

          在另一种选择中,您可以使用像 Sphinx 这样的搜索引擎是开源的,但您的数据库设计应该处于非规范化模式,您可以将多列转换为一列,例如:

          Select (*) from table where prop=val1 and prop2=val2 and prop3=val3 ..
          

          像这样创建一个唯一的列索引:val_tot = concat(val1, val2, val3,..)

          Select (*) from table where prop_key = val_tot;
          

          【讨论】:

            猜你喜欢
            • 2023-03-16
            • 2021-04-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-06
            • 2021-06-18
            • 1970-01-01
            相关资源
            最近更新 更多