集群由一组服务器相互独立的服务器,构建的高性能与可靠性的服务器架构
MySQL读写分离
主从复制是读写分离的基础
主从复制原理
- 主服务器将修改的SQL语句写入到二进制(bin)日志中
- 从服务器中的IO线程通过授权账号读取二进制日志,将信息写入到中继日志中(relay)
- 从服务器中的SQL线程读取中继日志中的数据,然后将SQL语句执行,还原主服务器中的数据
实现主从复制
开启主服务器的二进制日志
centos yum 安装MySQL配置文件路径:1
2
3log-bin=mysql-bin
binlog_format=mixed
server-id=101重启主服务器MySQL
service mysqld restart
添加授权账号
1
2
3
4
5[root@localhost etc]# mysql -uroot -p
Enter password:
mysql> GRANT REPLICATION SLAVE ON *.* TO repuser@"192.168.%.%" IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
#''引号内是授权账号的密码在主服务器下刷新用户权限
mysql> FLUSH PRIVILEGES;
查看主服务器状态
1
2
3
4
5
6
7
8
9mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 326 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
File :表示正在使用二进制文件
Position:二进制当前所在的位置修改从服务器mysql配置项
1
2[root@localhost ~]# vim /etc/my.cnf
server-id = 102重启从服务器的mysql服务
[root@localhost ~]# service mysqld restart
配置从服务器通过授权账号读取主服务器信息
1
2mysql> CHANGE MASTER TO MASTER_HOST='192.168.34.101',MASTER_USER='repuser',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=326;
Query OK, 0 rows affected (0.07 sec)在从服务器上开启主从同步数据
1
2mysql> slave start;
Query OK, 0 rows affected (0.00 sec)查看主从复制的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: repuser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 326
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes成功
在主服务器上建表,写入数据,查看重服务的数据表跟数据是否与主服务一样slave_io_running与slave_sql_running要求都为yes则表示成功
可以使用 slave stop关闭主从,使用reset slave 可以清空主从信息
从服务器配置参数
CHANGE MASTER TO
MASTER_HOST=’192.168.81.128’,//指定主服务器的地址
MASTER_USER=’repuser’,//指定授权账号的用户名
MASTER_PASSWORD=’123456’,//指定授权账号的密码
MASTER_LOG_FILE=’mysql-bin.000001’,//指定主服务的正在使用的二进制文件
MASTER_LOG_POS=326;//指定主服务器当前记录到的SQL语句的文字
开启bin日志,相关配置文件
log-bin=mysql-bin
开启二进制日志,并且名称以mysql-bin开头binlog-format=mixed
指定二进制文件记录sql语句的格式。statement:用一条sql语句记录修改。row:表示记录每一条sql语句。mixed:表示混合使用由mysql自己决定server-id = 101
表示主从服务器每台的标识各不一样datadir=/var/lib/mysql
mysql-bin.index //索引文件,列出当前有哪些二进制文件
mysql-bin.000001//记录修改的SQL语句
bin日志,只记录修改表数据的SQL语句:inser
、delete
、update
读写分离原理
判断sql语句,如果是insert、update、delete类型sql语句则直接连接主服务器修改数据;如果是select语句则从slave服务器中选择一台进行查询。
实现读写分离
ThinkPHP实现读写分离
修改配置项
1
2
3
4
5
6
7
8
9
10
11
12'DB_DEPLOY_TYPE' => 1, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'DB_RW_SEPARATE' => true, // 数据库读写是否分离 主从式有效
'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量
'DB_SLAVE_NO' => '', // 指定从服务器序号
/* 数据库设置 */
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => '192.168.34.101,192.168.34.102', // 服务器地址
'DB_NAME' => 'test', // 数据库名
'DB_USER' => 'root,root', // 用户名
'DB_PWD' => '123456,123456', // 密码
'DB_PORT' => '3306,3306', // 端口
'DB_PREFIX' => '', // 数据库表前缀代码书写
1
2
3
4
5
6
7
8
9
10
11public function read(){
$model = M('slave');
$data = $model->select();
dump($data);
}
public function write(){
$model = M('slave');
$data=array('name'=>'dumin','age'=>'18','sex'=>'女');
$res = $model -> add($data);
dump($res);
}
分库分表
垂直分表
- 冷热字段区分
水平分表
- 逻辑分表 MySQL内部完成
- 物理分表 可通过主键取余、MD5加密数据字母与数据分表等
逻辑分表
key:取模算法
hash:哈希算法
range:某一个范围
list:某些值得中间
创建语法
1 | create table 表名( |
添加语法
1 | 求余算法:alter table 表名 add partition partitions 5; |
分表与多方式登录数据表
1 | #创建一个不重复的ID |
laravel 源码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
88public function register(){
if($input = Input::all());
// 定义验证规则
$rules = [
'pwd' => 'required|between:6,20',
'name' => 'alpha_num',
'name' => 'unique:people,tel',
'email' => 'email',
'tel' => 'integer',
];
// 提示信息
$message = [
'name.alpha_num' => '用户名只能是字符和数字',
'name.unique' => '该用户已经存在请重新输入',
'email.email' => '请输入合法邮箱',
'tel.integer' => '请输入合法手机号码',
'pwd.required' => '密码不能为空',
'pwd.between' => '密码必须在6-20位之间',
];
$validator = Validator::make($input,$rules,$message);
if($validator->passes()){//验证规则通过
$pwd = $input['pwd'];
$tel = $input['tel'];
$email = $input['email'];
// 检查用户名是否存在
$name = People::where('name','=',$input['name'])->first();
$tel = People::where('tel','=',$input['tel'])->first();
$email = People::where('email','=',$input['email'])->first();
if($name!=null){
$data = array(
'sign' => 0,
'code' => 'register error',
'msg' => '该用户名已经存在,请返回登录或重新注册!'
);
return json_encode($data);
}
if($tel!=null){
$data = array(
'sign' => 0,
'code' => 'register error',
'msg' => '该手机已经注册,请返回登录或重新注册!'
);
return json_encode($data);
}
if($email!=null){
$data = array(
'sign' => 0,
'code' => 'register error',
'msg' => '该邮箱已经存在,请返回登录或重新注册!'
);
return json_encode($data);
}
$uid = DB::table('people_uid')->insertGetId(array());
$input['uid']=$uid;
$input['pwd'] = Crypt::encrypt($input['pwd']);
DB::table('people')->insert($input);
DB::table('people_index')->insert(array('uid'=>$uid,'name'=>$input['name']));
DB::table('people_index')->insert(array('uid'=>$uid,'name'=>$input['tel']));
$res = DB::table('people_index')->insert(array('uid'=>$uid,'name'=>$input['email']));
if($res){
// 成功
$data = array(
'sign' => 1,
'code' => 'register success',
'msg' => '注册成功!'
);
echo json_encode($data);exit();
}else{
// 入库失败
$data = array(
'sign' => 0,
'code' => 'insert error',
'msg' => '入库失败请联系管理员!'
);
echo json_encode($data);exit();
}
}else{
// 服务器端验证规则
$messages = $validator->messages();
$data = array(
'sign' => 0,
'code' => 'insert error',
'msg' => $messages->first(),
);
echo json_encode($data);exit();
}
}