在开发IT610项目的时候遇到了一个需求,Tag表要根据TagName的首字母进行分表分库(如果首字母不是字母则视其首字母为0),一个首字母占一个分片,26个字母+1个其他类型总共27个分片。
这里我选择使用枚举分片,rule.xml里应当如下配置(tableRule标签的原名是“sharding-by-intfile”,functin标签的原名是“hash-int”)
<tableRule name="tag">
<rule>
<columns>letter</columns>
<algorithm>letter-hash</algorithm>
</rule>
</tableRule>
<function name="letter-hash" class="io.mycat.route.function.PartitionByFileMap">
<!--指定枚举规则文件-->
<property name="mapFile">letter-hash.txt</property>
<!--如果type为0代表对数字进行枚举,如果type大于0代表对字符串进行枚举-->
<property name="type">1</property>
</function>
letter-hash.txt文件内容如图所示,第一个节点从0开始
然后再来看schema.xml,这里因为IT610其他业务的需要dnA里有1~32个节点(库),tag表只分1~27个节点。而dn1节点是为那些不分布式存储的表而准备的。
<schema name="it-610" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
<table name="cms_tag" dataNode="dnA$1-27" rule="tag" />
</schema>
<dataNode name="dn1" dataHost="database1" database="it610-1" />
<dataNode name="dnA$1-32" dataHost="database1" database="it610-$1-32" />
<dataHost name="database1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostS1" url="192.168.92.22:33061"
user="root" password="123456" />
</dataHost>
然后我写了一段测试程序,用于插入20*27行cms_tag表的记录,用于验证分库分表是否成功。
@ResponseBody
@GetMapping("/test")
public String test() {
char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0".toCharArray();
String sql = "INSERT INTO `cms_tag` (`id`,`tag_name`,`ref_counter`,`letter`) VALUES ";
int id = 0;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 27; j++) {
createMapper.sql(sql + "(" + id + ",'" + letters[j] + id + "',0,'" + letters[j] + "')");
id++;
}
}
return "ok";
}
访问地址,由于540条sql比较多,需要几秒的运行时间。
执行成功
先去Mycat里检查总数,总数是正确的
检查分库分表是否成功,6号库对应第6个字母F,总共20条数据
26号库,对应第26个字母,总共20条数据
27号库,对应的是0(其他),总共20条数据
分库分表的配置文件、SQL文件、Java代码都在案例文件里