Mycat:Mycat的安装及应用测试
Mycat:基于java语言编写的数据库中间件。可以看作一个数据库代理,核心功能是分库分表。也可以配置读写分离,以及可以做大数据分析处理。
一:安装Mycat
1,安装JDK
// 上传压缩包到 /usr/local // 解压 tar -zxvf OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz // 重命名 mv jdk-11.0.8+10/ java_11 // 删除压缩包 rm -rf OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz // 设置环境变量 // 打开文件编辑 vi /etc/profile // 在unset i 前面加上 java的环境变量配置 下面的JAVA_HOME后面的路径为你的jdk解压的路径 export JAVA_HOME=/usr/local/java_11 export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin // 让环境变量生效 source /etc/profile // 测试 出现下图安装成功 java -version
2,下载Mycat上传解压,下载地址:https://github.com/MyCATApache/Mycat-download
// 上传压缩包到 /usr/local // 解压 tar -zxvf Mycat-server-1.6.7.3-release-20190828135747-linux.tar.gz // 删除压缩包 rm -rf Mycat-server-1.6.7.3-release-20190828135747-linux.tar.gz
3,启动Mycat测试
// 进入Mycat cd mycat // 查看命令 ./bin/mycat // 启动命令 ./bin/mycat start
4、Mycat连接MySQL
// MySQL 5.7 连接命令 mysql -uroot -p123456 -P8066 -h127.0.0.1 // MySQL 8.0 连接命令 mysql -uroot -p123456 -P8066 -h127.0.0.1 --default_auth=mysql_native_password /*这是由于Mysql 8的缺省加密方式已经改为caching_sha2_password,而MyCat对此尚不支持。为此,需加上--default_auth=mysql_native_pasowrd选项*/
二:配置Mycat
Mycat支持两种配置方式,zookeeper和本地xml配置。Mycat默认以本地加载xml方式启动,如果需以zk方式启动,则应把conf目录下面zk.conf文件中loadfromzk参数设置为true。zk配置方式解决了统一配置和管理问题,同时解决了mycat与周边组件的协调问题。如果使用了zk配置方式,则所有的配置参数都在zk-create.yaml文件中,该文件涵盖了conf目录下面的schema,server等文件中所有的配置项。
server.xml 系统配置参数,包括调优,用户权限等。
schema.xml (重要)涵盖了逻辑库,表,分片规则,分片节点及数据源等。
rule.xml 定义了表拆分所涉及到的规则定义。包含多种算法。
三:应用测试
1,先本地创建3张分表
CREATE TABLE `orders_0` ( `id` bigint(20) NOT NULL, `product_id` bigint(10) NOT NULL, `amount` int(4) NOT NULL, `create_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 CREATE TABLE `orders_1` ( `id` bigint(20) NOT NULL, `product_id` bigint(10) NOT NULL, `amount` int(4) NOT NULL, `create_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 CREATE TABLE `orders_2` ( `id` bigint(20) NOT NULL, `product_id` bigint(10) NOT NULL, `amount` int(4) NOT NULL, `create_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
2,添加一个新的database config
'mysql_orders' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => 'orders', 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ],
3,创建orders模型
protected $connection = 'mysql_orders'; protected $fillable=[ 'id', 'product_id', 'amount', 'create_at' ]; public $timestamps = false;
4,创建controller
// 此处根据order_id来进行分表 public function create(){ $order = new Orders([ 'id' => $this->getOrderID(), 'product_id' => 111, 'amount' => 11, 'create_at' =>Carbon::now() ]); $order->setTable($this->getTable()); if ($order->save()) { return "订单生成成功"; }else{ return "订单生成失败"; } } // 根据取模找到对应的表 private function getTable(){ $orer_id = $this->getOrderID(); return 'orders_'.$orer_id % 3; } // 生成一个order_id private function getOrderID(){ //13位日期格式+用户+商家+随机6位数 return Carbon::now()->getPreciseTimestamp(3).str_pad(random_int(0,999999),6,'0',STR_PAD_LEFT); }
5,测试访问create,发现数据分布在order0-3张表里。
6,配置Mycat逻辑表。注意:数据库连接,防火墙等。
// server.xml 这里使用默认逻辑库,暂没做修改。 // rule.xml 配置orders的规则 // 添加规则 <tableRule name="orders-rule">// name rule名称,注意命名 <rule> <columns>id</columns>// 拆分的字段名 <algorithm>mod-long</algorithm> // 拆分的规则 </rule> </tableRule> // 添加或者修改规则 <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">3</property>// 取模的值 </function> // shema.xml 配置逻辑表和使用规则及连接 <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">// name 对应的逻辑库 <table name="t_orders" subTables="orders_$0-2" primaryKey="id" dataNode="dn1" rule="orders-rule" /> // name 逻辑表 subTables 分表 primaryKey 拆分字段 dataNode 使用的数据库 rule 使用的规则 <!--<table name="t" dataNode="dn1" />--> </schema> <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743" /> --> <dataNode name="dn1" dataHost="localhost1" database="orders_test" /> // name 数据库命名,对应上面的dataNode dataHost 数据库连接名 database 具体的库名 <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> //name 数据库连接名字,对应上面的dataHost maxCon,minCon 最大最小连接数 //balance 读写类型配置。 balance=0: 不开启读写分离,所有读操作都发送到当前可用的writeHost上。 balance=1: 全部的readHost与Stand by writeHost都参与select语句的负载均衡,简而言之,当双主双从模式(M1-->S1, M2--->S2,并且M1与M2互为主备)时,在正常情况下,M2,S1和S2都参与select的负载均衡。 balance=2: 所有的读操作都随机在writeHost,readHost上分发。 balance=3: 所有的读请求都随机分配到writeHost对应的readHost上执行,writeHost不负担读压力,注意balance=3只在mycat1.4之后版本中有效。 // writeType 写类型配置。1. writeType=“0”, 所有写操作都发送到可用的writeHost上。 2. writeType=“1”,所有写操作都随机的发送到readHost。 3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。 //dbType 后端连接的数据库类型,目前支持二进制的mysql协议,还有其他使用JDBC连接的数据库。如mongodb,spark等。 //dbDriver 连接后端数据库使用的Driver,目前可选的值有native和JDBC。 //switchType -1:表示不自动切换。 1 :默认值,表示自动切换 2:表示基于MySQL主从同步状态决定是否切换,心跳语句: show slave status. 3:表示基于mysql galary cluster的切换机制,适合mycat1.4之上的版本,心跳语句show status like "%esrep%"; <heartbeat>select user()</heartbeat>//心跳 <!-- can have multi write hosts --> <writeHost host="hostM1" url="192.168.244.100:3306" user="orders_test" password="123456">//写库配置 <!-- can have multi read hosts --> <readHost host="hostS2" url="192.168.244.100:3306" user="orders_test" password="123456" />//读库配置 </writeHost> <!-- <writeHost host="hostS1" url="localhost:3316" user="root" password="123456" /> <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> --> </dataHost>
7,重启Mycat,进入逻辑库测试。
通过explain分析测试,mycat会根据相应的规则去帮助重新构建sql查询。
8,Laravel连接Mycat查询数据。配置database.config
'mycat_orders' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => '192.168.244.120', 'port' => '8066', 'database' => 'TESTDB', 'username' => 'root', 'password' => '123456', 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), PDO::ATTR_EMULATE_PREPARES => true, // 注意这里的配置 ]) : [], ],
9,写一个controller方法测试
//测试查询mycat数据 public function index(){ $result = DB::connection('mycat_orders')->table('t_orders')->where('id',1615791347622551380)->first(); dd($result); }