2

我正在研究如何解决客户需要将特定客户的所有数据(并且只有该客户的数据)存储在地理上不同的数据库服务器上的情况。

例如,所有数据都应存储在主云上的数据库服务器中,但与客户 ID 92 相关的所有数据除外,这些数据应存储在另一个位置的不同云上的服务器中。

我正在处理的一些限制使这有点棘手,但到目前为止,MySQL Cluster似乎是最好的方法。

但是,我不清楚它在执行查询时如何选择数据节点。例如,如果我要提交一个不需要客户 ID 92 的任何数据的查询,它是否仍会 ping 另一个云中的数据节点并引入延迟?

MySQL Cluster 如何在SELECT查询期间确定要搜索的数据节点?有什么方法可以在查询中提示可以忽略某些数据节点?

4

3 回答 3

6

哎呀..这不是 MySQL Cluster 的工作方式。

默认情况下,MySQL Cluster 在 PRIMARY KEY 上对数据进行分区。但是,可以在部分主键上使用用户定义的分区和分区。这对于将相关数据组合在一起并确保数据在一个分区内的局部性非常有用。由于相关数据随后保存在一个分区中,因此可以在不牺牲性能的情况下从 2 个数据节点扩展到 48 个数据节点——它将保持不变。在http://dev.mysql.com/doc/refman/5.5/en/partitioning-key.html查看更多细节

默认情况下,API 将计算 PRIMARY KEY(或主键的已定义部分)上的哈希值(使用 LH3* 算法,该算法使用 md5)以确定发送查询的分区。计算的哈希是 128 位,64 位确定分区,64 位确定分区上哈希索引中的位置。作为用户,您无法准确了解哪个节点拥有数据(或谁将存储数据),但实际上这并不重要。

关于在 2 个云上分布一个 MySQL 集群和对数据进行分区的原始问题。数据节点之间需要可靠的低延迟访问,因此您不希望将节点分散开,除非它们彼此相距不到 50-100 英里。

于 2013-07-01T07:05:42.980 回答
4

首先请注意,Mysql Cluster 不是为 WAN 设计的,通常最好在您的节点之间具有小于 20ms 的传播延迟。

Mysql Cluster 做分片(在数据节点之间平均分配数据)+复制(每个分片数据存储两次)。

如此简单的表格,

| test  | CREATE TABLE `test` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `v1` char(255) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=ndbcluster AUTO_INCREMENT=1871780 DEFAULT CHARSET=latin1

如果您检查 information_schema,您将看到该表的分区

mysql> select partition_name,table_rows from information_schema.PARTITIONS where     table_name='test' and table_schema='test1';
+----------------+------------+
| partition_name | table_rows |
+----------------+------------+
| p0             |     518667 |
| p1             |     518900 |
| p2             |     517385 |
| p3             |     519050 |
+----------------+------------+
4 rows in set (0.02 sec)

分区 p0,p2 代表数据节点 1,p1,p3 代表节点 2。数据基于主键(或人工键,如果现在定义了主键)分布。

Select 根据这个分区选择要读取的节点,所以如果你使用 explain

mysql> explain partitions select id,v1 from test where id=1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: test
   partitions: p3
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 8
          ref: const
         rows: 1
        Extra: NULL
1 row in set (0.00 sec)

mysql> explain partitions select id,v1 from test where id=2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: test
   partitions: p2
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 8
          ref: const
         rows: 1
        Extra: NULL

id=92 的记录将仅从其中一个数据节点(可能是地理分布的节点)中读取,但不幸的是,它不仅适用于 id 92。

最好的方法是为客户 ID 92(在单独的节点上)创建一个单独的表,并重写您的应用程序以从该表/节点读取。要获得对应用程序透明的解决方案,您可以使用Mysql 代理

于 2013-09-11T09:52:45.697 回答
2

Hi I'm afraid the answer is "no". MySQL cluster is sometimes called sharding but it's really not... It's arbitrary distribution of data from every table by the PK with no control and no thinking about which data is accessed together and which nodes are needed for every access and every query or transaction.

Sharding, and a good data distribution policy is one that keeps data that is accessed together, on the same database, so when a transaction needs data, it'll end-up using this 1 DB, processing (join, group) will be pushed to this database (closer to the data, good!) and other databases will be left to deal with other transactions (and there are many.......).

So we get 2 things from storing together-accessed data on one database:

  1. Less latency for queries/transaction needing this data and finding it on 1 node
  2. Queries/transaction are distributed, not multiplied on all databases

So if I understand your question, this is what you want to achieve, MySQL Cluster can't give that, if it's OK for now, it will come back and bite you when data/concurrency/writes grow.....

You probably need a good old sharding, or today there are tools that actually automates sharding process (disclaimer: I work for ScaleBase, one option for that, using just databases required, and yes, also supporting hints (usually not needed) ).

于 2013-06-24T20:23:42.530 回答