本機環境是Centos7,使用的MySQL版本是mysql-community 5.7.29-1.el7
安裝MySQL
1、準備了三臺虛擬機:192.168.56.102,192.168.56.103,192.168.56.104
2、MyCat安裝在192.168.56.103上,首先安裝MyCat的機器必須要裝jdk
每臺機器依次運行以下命令,我的機器上安裝的板本是:mysql-community 5.7.29-1.el7,下載量很大等待進度條跑完
yum -y install mysql
yum -y instll mysql-server
yum -y install mysql-devel
MySQL安裝完成之後會默認生成一個隨機密碼,使用命令查看,後面改成自己的密碼就可以了(這裏偷了點懶,直接用了root用戶)
cat /var/log/mysqld.log | grep 'password'
配置字符集及啓動MySQL
修改所有機器上的/etc/my.cnf文件,在最後添加編碼設置
具體配置查看官方文檔:https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
[client]
default-character-set=utf8 #默認是utf8
[connection]
default-character-set=utf8 #默認是utf8
[database]
default-character-set=utf8 #默認是latin1
[results]
default-character-set=utf8 #默認是utf8
將MySQL服務設置爲開機啓動(CentOS 7.x開始,CentOS開始使用systemd服務來代替daemon,原來管理系統啓動和管理系統服務的相關命令全部由systemctl命令來代替),啓動MySQL服務
systemctl enable mysqld
systemctl start mysqld
登錄MySQL查看配置文件是否生效,圖中證明配置文件生效了
使用MySQL語句更新root用的遠程訪問權限,更新爲所有IP均能訪問(存在一定安全隱患);新增用戶mycat,給予權限;
使用mycat用戶登錄數據庫,在每臺機器上創建一個數據庫,名字不一樣(例如:db1、db2、db3)
use mysql;
update user set host='%' where user='root' and host='localhost';
create user 'mycat'@'%' identified by '123456';
grant all privileges on *.* to 'mycat'@'%' identified by '123456';
安裝MyCat
下載MyCat Linux的壓縮包並解壓,這裏我把解壓厚的文件夾重命名爲了MyCat-1.6.7.4
cd /usr/local
wget http://dl.mycat.io/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
tar -xvf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
將MyCat加入Linux的環境變量中(/etc/profile文件)
#編輯文件
vim /etc/profile
#加入以下內容
export MYCAT_HOME=/usr/local/MyCat-1.6.7.4
export PATH=$PATH:$MYCAT_HOME/bin
#保存文件之後執行命令
source /etc/profile
創建用戶組mycat,新建mycat用戶並加入用戶組mycat
group mycat
useradd -g mycat mycat
passwd mycat
配置MySQL及MyCat
首先推薦MyCat官方文檔,這裏面講述得非常詳細,本文配置基本是按照文檔裏面來的(自己也做了一些小修改):MyCat權威指南
配置schema.xml,配置schema以及對應的數據節點的信息,三臺機器上的schema依次是seckill_102,seckill_103,seckill_104,分片策略選擇的是mod_long:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="seckill" checkSQLschema="false" sqlMaxLimit="100">
<table name="manager_user" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="manager_merchant" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="manager_shop" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="manager_product_type" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="manager_product_detail" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="manager_product_info" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="seckill_product" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="seckill_user_result" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
<table name="seckill_order" primaryKey="id" autoIncrement="true" dataNode="seckill_$102-104" rule="mod-long"/>
</schema>
<dataNode name="seckill_102" dataHost="slave_102" database="seckill_102" />
<dataNode name="seckill_103" dataHost="master_103" database="seckill_103" />
<dataNode name="seckill_104" dataHost="slave_104" database="seckill_104" />
<dataHost name="master_103" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- MySQL數據庫連接串 -->
<writeHost host="hostM1" url="192.168.56.103:3306" user="mycat" password="123456"></writeHost>
</dataHost>
<dataHost name="slave_102" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- MySQL數據庫連接串 -->
<writeHost host="hostM2" url="192.168.56.102:3306" user="mycat" password="123456"></writeHost>
</dataHost>
<dataHost name="slave_104" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- MySQL數據庫連接串 -->
<writeHost host="hostM3" url="192.168.56.104:3306" user="mycat" password="123456"></writeHost>
</dataHost>
</mycat:schema>
配置server.xml,圖中紅框是我修改的地方,主鍵自增方案我選擇的是官方文檔9.3節數據庫全局序列號:
<!-- 使用數據庫進行主鍵自增 -->
<property name="sequnceHandlerType">1</property>
<!-- Mycat連接數據庫時使用的隔離級別 1 - 讀未提交 2 - 讀已提交 3 - 可重複讀 4 - 串行化 當MyCat搭配MySQL使用的時候默認隔離級別是"可重複讀"(摘自官方文檔) -->
<property name="txIsolation">3</property>
<user name="mycat">
<property name="password">123456</property>
<property name="schemas">seckill</property>
<privileges check="true">
<!-- 設置了 schema , 但只設置了個別 table 或 未設置 table 的 DML,自動繼承 schema 的 DML 屬性 -->
<schema name="seckill" dml="1111"></schema>
</privileges>
</user>
配置sequence_db_conf.properties,這裏面記錄的是表中需要增加序列號的表名單的記錄;表名一定要大寫,seckill_103是MyCat安裝的機器的dataNode的名稱:
#sequence stored in datanode
MANAGER_USER=seckill_103
MANAGER_MERCHANT=seckill_103
MANAGER_SHOP=seckill_103
MANAGER_PRODUCT_TYPE=seckill_103
MANAGER_PRODUCT_DETAIL=seckill_103
MANAGER_PRODUCT_INFO=seckill_103
SECKILL_PRODUCT=seckill_103
SECKILL_USER_RESULT=seckill_103
SECKILL_ORDER=seckill_103
創建數據表以及數據表function,需在MyCat安裝的機器上的數據庫裏執行,完成之後插入需要自增長id的表的名稱以及規則,這裏我做了一點改動,current_value從INT類型改到了bigint,因爲我數據庫中的主鍵類型爲bigint,數據庫用戶從root改成了mycat:
CREATE TABLE mycat_sequence (
`name` VARCHAR(50) NOT NULL,
`current_value` bigint NOT NULL,
`increment` INT NOT NULL DEFAULT 1,
PRIMARY KEY(name)
) ENGINE=InnoDB default character set utf8;
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_merchant', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_product_detail', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_product_info', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_product_type', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_shop', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('manager_user', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('seckill_order', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('seckill_product', 1, 1);
INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('seckill_user_result', 1, 1);
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE DEFINER=`mycat`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE retval VARCHAR(64);
SET retval="-999999999,null";
SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval FROM MYCAT_SEQUENCE WHERE name = seq_name;
RETURN retval ;
END
;;
DELIMITER ;
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE DEFINER=`mycat`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE MYCAT_SEQUENCE
SET current_value = current_value + increment WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE DEFINER=`mycat`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) RETURNS varchar(64) CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE MYCAT_SEQUENCE
SET current_value = value
WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END
;;
DELIMITER ;
每次改動MyCat配置文件之後記得要重啓MyCat
效果及展示
MyCat暴露出來的端口默認是8066,使用數據庫連接到這個代理端口可以直接進行操作,通過這個連接插入數據實驗主鍵是否能夠自動增長以及數據會不會自動水平分片:
use seckill;
INSERT INTO seckill_product (product_id, seckill_num, seckill_price, seckill_inventory, create_time, start_time, end_time, shop_id, state, product_price, product_title, product_name, approve_time, seckill_version) VALUES (1, 1, 1999.99, 65, '2019-12-01 20:24:57', '2019-12-01 20:24:59', '2020-12-01 20:25:01', 1, 1, 6799.99, '三星s10 plus秒殺', '三星s10 plus 4+128g', '2019-12-01 20:26:18', 0);
INSERT INTO seckill_product (product_id, seckill_num, seckill_price, seckill_inventory, create_time, start_time, end_time, shop_id, state, product_price, product_title, product_name, approve_time, seckill_version) VALUES (1, 1, 1999.99, 65, '2019-12-01 20:24:57', '2019-12-01 20:24:59', '2020-12-01 20:25:01', 1, 1, 6799.99, '三星s10 plus秒殺', '三星s10 plus 4+128g', '2019-12-01 20:26:18', 0);
INSERT INTO seckill_product (product_id, seckill_num, seckill_price, seckill_inventory, create_time, start_time, end_time, shop_id, state, product_price, product_title, product_name, approve_time, seckill_version) VALUES (1, 1, 1999.99, 65, '2019-12-01 20:24:57', '2019-12-01 20:24:59', '2020-12-01 20:25:01', 1, 1, 6799.99, '三星s10 plus秒殺', '三星s10 plus 4+128g', '2019-12-01 20:26:18', 0);
INSERT INTO seckill_product (product_id, seckill_num, seckill_price, seckill_inventory, create_time, start_time, end_time, shop_id, state, product_price, product_title, product_name, approve_time, seckill_version) VALUES (1, 1, 1999.99, 65, '2019-12-01 20:24:57', '2019-12-01 20:24:59', '2020-12-01 20:25:01', 1, 1, 6799.99, '三星s10 plus秒殺', '三星s10 plus 4+128g', '2019-12-01 20:26:18', 0);
select * from seckill_product;
數據插入成功,返回的也是插入的四條數據
接下來看id自增長和數據的水平分片:id實現了自增長,數據也按照mod-long的策略進行了分片