1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
mycat全局系列号
 
1.为什么需要全局系列号:
 
1.1产品介绍:
 
在实现分库分表的情况下,数据库自增主键无法保证自增主键的全局唯一。为此,mycat提供了全局sequence,
并且提供了包含本地配置和数据库配置多种实现方式。
 
 
1.2模拟自增主键会出现的问题:
 
脑瓜子有点笨,一直没太搞清楚为什么分表分库情况下,无法保证自增主键的全局唯一?所以,动手测试模拟出自增主键的问题?
 
以下操作是基于正常mycat使用环境下
 
     <table name= "t1"  dataNode= "dn1,dn2"  rule= "sharding-by-intfile"  />
 
我的mycat有一张表t1分库分表,在dn1,dn2两个node都有这个表格,使用分表的规则是sharding-by-intfile
 
规则配置文件如下:
 
     <tableRule name= "sharding-by-intfile" >
         <rule>
             <columns>city< /columns >
             <algorithm> hash -int< /algorithm >
         < /rule >
 
 
     < function  name= "hash-int"
         class= "io.mycat.route.function.PartitionByFileMap" >
         <property name= "mapFile" >partition- hash -int.txt< /property >
         <property name= "type" >1< /property
         <property name= "defaultNode" >0< /property >
     < /function >
 
 
     [root@ha1 conf] # cat partition-hash-int.txt 
     gz=0
     sz=1
 
 
以上的整体含义是:city是gz的数据放到dn1的表格t1,city是sz的数据放到dn2的表格t1。
 
我准备修改这个表格,添加一个主键,并且设定这个主键自增。
 
mysql> desc t1;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
id     | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(15) | NO   |     | NULL    |                |
| bu    | varchar(10) | NO   |     | NULL    |                |
| city  | varchar(5)  | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
4 rows  in  set  (0.01 sec)
 
 
插入4条数据,其中两条city设置成sz,两条city设置成gz
 
 
mysql>  select  * from t1;
Empty  set  (0.03 sec)
 
mysql> insert into t1(name,bu,city) value( 'am1' , 'cs' , 'sz' );
Query OK, 1 row affected (0.08 sec)
 
mysql> insert into t1(name,bu,city) value( 'am2' , 'cs' , 'gz' ),( 'am3' , 'net' , 'sz' );
Query OK, 2 rows affected (0.06 sec)
 
mysql> insert into t1(name,bu,city) value( 'am4' , 'net' , 'gz' );
Query OK, 1 row affected (0.04 sec)
 
检索看看:
 
mysql>  select  * from t1;
+----+------+-----+------+
id  | name | bu  | city |
+----+------+-----+------+
|  4 | am1  | cs  | sz   |
|  5 | am3  | net | sz   |
|  3 | am2  | cs  | gz   |
|  4 | am4  | net | gz   |
+----+------+-----+------+
 
 
哈哈哈,问题出现了。 id 出现一样的,这就是全局系列号的存在的重大意义所在。
 
 
 
2.全局系列号的配置:
 
 
2.1本地文件方式
 
此方式mycat将sequence配置到文件中,使用到sequence中的配置后,mycat会更下classpath中的sequence_conf.properties文件中的
sequence当前的值。
 
这段解释看得不是一般的拗口。不动手根本不知道在说什么。
 
首先是sequence读取的配置文件:
 
[root@ha1 conf] # pwd
/usr/local/mycat/conf
[root@ha1 conf] # ls |grep sequ
sequence_conf.properties
sequence_db_conf.properties
sequence_distributed_conf.properties
sequence_time_conf.properties
[root@ha1 conf]
 
本地配置文件读取的是:sequence_conf.properties
 
看看内容:
 
[root@ha1 conf] # cat sequence_conf.properties 
#default global sequence
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=20000
GLOBAL.CURID=10000
 
# self define sequence
COMPANY.HISIDS=
COMPANY.MINID=1001
COMPANY.MAXID=2000
COMPANY.CURID=1000
 
CUSTOMER.HISIDS=
CUSTOMER.MINID=1001
CUSTOMER.MAXID=2000
CUSTOMER.CURID=1000
 
ORDER.HISIDS=
ORDER.MINID=1001
ORDER.MAXID=2000
ORDER.CURID=1000
 
HOTNEWS.HISIDS=
HOTNEWS.MINID=1001
HOTNEWS.MAXID=2000
HOTNEWS.CURID=1000
 
其中HISIDS表示使用过的历史分段(一般无特殊需要可不配置),MINID表示最小ID值,MAXID表示最大ID值,CURID表示当前ID值。
 
server.xml中配置:
<system><property name= "sequnceHandlerType" >0< /property >< /system >
注:sequnceHandlerType需要配置为0,表示使用本地文件方式。
 
 
 
实际操作:
 
 
[root@ha1 conf] # pwd 
/usr/local/mycat/conf
[root@ha1 conf] # ls |grep server.xml 
server.xml
 
在server.xml <system>段结尾处加入
<property name= "sequnceHandlerType" >0< /property >
 
参考如下:
 
         <!--是否采用zookeeper协调切换  -->
         <property name= "useZKSwitch" > true < /property >
 
         
         <property name= "sequnceHandlerType" >0< /property >
 
     < /system >
 
 
然后重启mycat。
 
 
测试:
 
就拿前面的表格t1来测试。
 
清空t1
 
mysql> truncate table t1;
Query OK, 0 rows affected (0.15 sec)
 
mysql>  select  * from t1;
Empty  set  (0.01 sec)
 
 
插入数据:
 
mysql> insert into t1( id ,name,bu,city)values(next value  for  MYCATSEQ_GLOBAL, 'am1' , 'sys' , 'gz' );
Query OK, 1 row affected (0.05 sec)
 
mysql> insert into t1( id ,name,bu,city)values(next value  for  MYCATSEQ_GLOBAL, 'am2' , 'sys' , 'sz' );
Query OK, 1 row affected (0.05 sec)
 
mysql> insert into t1( id ,name,bu,city)values(next value  for  MYCATSEQ_GLOBAL, 'am3' , 'sys' , 'sz' );
Query OK, 1 row affected (0.03 sec)
 
mysql> insert into t1( id ,name,bu,city)values(next value  for  MYCATSEQ_GLOBAL, 'am4' , 'sys' , 'gz' );
Query OK, 1 row affected (0.05 sec)
 
 
检索看看:
 
mysql>  select  * from t1;
+-------+------+-----+------+
id     | name | bu  | city |
+-------+------+-----+------+
| 10002 | am1  | sys | gz   |
| 10005 | am4  | sys | gz   |
| 10003 | am2  | sys | sz   |
| 10004 | am3  | sys | sz   |
+-------+------+-----+------+
4 rows  in  set  (0.02 sec)
 
 
实现了自增键的全局唯一。
 
缺点:当MyCAT重新发布后,配置文件中的sequence会恢复到初始值。
优点:本地加载,读取速度较快。
 
 
mycat重新发布的意思有点不明白。后面在测试。