各位好:
我按如下附圖的配置 sharding-by-stringhash (io.mycat.route.function.PartitionByString) 分片策略,我按照思路取字串前4位的數字,如上圖 1536 和 3621 除了 partitionLength 256 取模,即 1536%256 和 3621%256,余數分別是0 和 37,但為什么會是分配第同一個磁區節點db4(dn4)上呢?
請問這個取模后再分片的邏輯是怎么分配的呢?搞不清哪個到底分到哪個分片上?
待復,感謝!
【附圖如下】:

uj5u.com熱心網友回復:
你一共有 4 個分片,N % 256 結果一共有 256 種可能:1. 結果為 0 - 63 分配到同一個分片;
2. 結果為 64 - 127 分配到同一個分片;
3. 結果為 128 - 191 分配到同一個分片;
4. 結果為 192 - 255 分配到同一個分片。
uj5u.com熱心網友回復:
---------
您好,感謝您的熱心解答!
你的意思是說256除以分片數,256/4=64,每個分片保留64個范圍數嗎?
我看了一下,照你這么說的,結果也不對哦。如下圖,取列值前四位數字%256,余數是 0和87,為什么都是分到同一個分片了?
uj5u.com熱心網友回復:
---------
您好,感謝您的熱心解答!
你的意思是說256除以分片數,256/4=64,每個分片保留64個范圍數嗎?
我看了一下,照你這么說的,結果也不對哦。如下圖,取列值前四位數字%256,余數是 0和87,為什么都是分到同一個分片了?
【附圖】:
uj5u.com熱心網友回復:
更正一下,一共 4 個分片,每個分片長度 256。partitionCount * partitionLength = 1024,計算 N 二進制 & 1111111111:1. 結果為 0 - 255 分配到同一個分片;
2. 結果為 256- 511 分配到同一個分片;
3. 結果為 512 - 767 分配到同一個分片;
4. 結果為 768 - 1023 分配到同一個分片。
Mycat有個官方網站:http://www.mycat.io/
這是使用指南:http://www.mycat.io/document/mycat-definitive-guide.pdf
uj5u.com熱心網友回復:
-----
感謝董兄熱心解答!官網我看過,好像教程的版本都很舊沒更新了。
按照你說的,好像也不對哦。我計算一下每個節點 模于 256 后,余數都有為0的,都為0,為什么不放到同一節點呢?如下:
root@db1*localhost 12:55:43> select * from bystringhash;
+--------------+
| code |
+--------------+
| 1111afafaa |
| 10240ikalaaa |
| 11115afafaa |
| 1024ikalaaa |
| 10240afasfaa |
+--------------+
5 rows in set (0.00 sec)
root@db1*localhost 12:55:47> select 1024 % 256;
+------------+
| 1024 % 256 |
+------------+
| 0 |
+------------+
1 row in set (0.00 sec)
root@db2*localhost 12:53:49> select * from bystringhash;
+------------+
| code |
+------------+
| 2048Akuccc |
| 65536afafa |
| 5123kkkkk |
+------------+
3 rows in set (0.00 sec)
root@db2*localhost 12:55:26> select 2048 % 256;
+------------+
| 2048 % 256 |
+------------+
| 0 |
+------------+
1 row in set (0.00 sec)
uj5u.com熱心網友回復:
我看了一下原始碼:PartitionByString.java 里是:
@Override
public Integer calculate(String key) {
int start = hashSliceStart >= 0 ? hashSliceStart : key.length() + hashSliceStart;
int end = hashSliceEnd > 0 ? hashSliceEnd : key.length() + hashSliceEnd;
long hash = StringUtil.hash(key, start, end);
return partitionUtil.partition(hash);
}
先呼叫 StringUtil.hash 計算哈希值,然后呼叫 partitionUtil.partition 計算哈希值對應的磁區。
StringUtil.java 里是:
/**
* 字串hash演算法:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] <br>
* 其中s[]為字串的字符陣列,換算成程式的運算式為:<br>
* h = 31*h + s.charAt(i); => h = (h << 5) - h + s.charAt(i); <br>
*
* @param start
* hash for s.substring(start, end)
* @param end
* hash for s.substring(start, end)
*/
public static long hash(String s, int start, int end) {
if (start < 0) {
start = 0;
}
if (end > s.length()) {
end = s.length();
}
long h = 0;
for (int i = start; i < end; ++i) {
h = (h << 5) - h + s.charAt(i);
}
return h;
}
PartitionUtil 里是:
// 磁區長度:資料段分布定義,其中取模的數一定要是2^n, 因為這里使用x % 2^n == x & (2^n - 1)等式,來優化性能。
private static final int PARTITION_LENGTH = 1024;
// %轉換為&操作的換算數值
private static final long AND_VALUE = PARTITION_LENGTH - 1;
public int partition(long hash) {
return segment[(int) (hash & AND_VALUE)];
}
舉例來說,
1024 的哈希:1*31*31*31 + 0*31*31 + 2*31 + 4 = 29857?
然后 29857 % 1024 = 161,屬于 0 - 255,所以在 db1
2048 的哈希:2*31*31*31 + 0*31*31 + 4*31 + 8 = 59714?
然后 59714? % 1024 = 322,屬于 256 - 511,所以在 db2
其他也是一樣,你自己算一下。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/29995.html
標籤:MySQL
上一篇:bcp出錯,怎么也找不出錯誤!
