mysql安装及实现读写分离
数据库安装、主从同步
https://blog.csdn.net/Ayhan_huang/article/details/78784486
mysql被收购导致收费,所以使用mariadb代替
1、安装mariadb
# 安装
yum install mariadb-server
#启动
systemctl start mariadb
systemctl enable mariadb
# 首次安装需要进行数据库的配置,命令都和mysql的一样
mysql_secure_installation
配置时出现的各个选项
Enter current password for root (enter for none): # 输入数据库超级管理员root的密码(注意不是系统root的密码),第一次进入还没有设置密码则直接回车
Set root password? [Y/n] # 设置密码,y
New password: # 新密码
Re-enter new password: # 再次输入密码
Remove anonymous users? [Y/n] # 移除匿名用户, y
Disallow root login remotely? [Y/n] # 拒绝root远程登录,n,不管y/n,都会拒绝root远程登录
Remove test database and access to it? [Y/n] # 删除test数据库,y:删除。n:不删除,数据库中会有一个test数据库,一般不需要
Reload privilege tables now? [Y/n] # 重新加载权限表,y。或者重启服务也许
设置MariaDB字符集为utf-8
1、
vim /etc/my.cnf
在[mysqld]下面添加
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
2、
vim /etc/my.cnf.d/client.cnf
在 [client] 标签下添加
default-character-set=utf8
3、
vim /etc/my.cnf.d/mysql-clients.cnf
在 [mysql] 标签下添加
default-character-set=utf8
4、重启服务
systemctl restart mariadb
远程链接mariadb数据库
将与主机名相等的字段改为 "%" ,我的主机名为mini,
update user set host='%' where host='mini';
刷新权限表,或重启mariadb服务,一下二选一即可
数据库中 flush privileges;
数据库外 systemctl restart mariadb
2、主从复制
原理:整体来说,分为3步
- master将改变(除select之外)全部记录到二进制日志(binary log)中
- slave的io线程将master的 binary log 拷贝到它的中继日志(relay log)
- slave的sql线程解析中继日志中的事件并在从库中执行,保持和主库一致
复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。
二进制日志格式
- binlog_format=statement
- binlog_format=row
- binlog_format=mixed
其中基于row的复制方式更能保证主从库数据的一致性,但日志量较大,在设置时考虑磁盘的空间问题
主从复制的方式
- 异步复制
- 半同步复制
异步复制原理介绍
客户端线程提交一个写操作,写入主库的binlog日志后就立即返回,并不需要等待从库完成同步操作,而主库的dump线程会监测binlog日志的变量然后主动将更新推送给从库。
MySQL 主从复制默认是异步的模式。
主库停服时制作主从
-
在主库上创建一个用于复制的账号,并赋予replication slave权限,这里必须
*.*
不能指定库授权,因为 replication slave 是全局的mysql> grant replication slave on *.* to 'jason'@'%' identified by '123'; mysql> flush privileges;
-
修改主库配置文件,开启主库的Binlog,并设置server-id
my.cnf
[mysqld] ... log-bin server_id=1 max_binlog_size=200M expire_logs_days=7 然后重启数据库即生效。 systemctl restart mariadb 创建执行同步的数据库用户 grant replication slave on *.* to 'root'@'101.34.182.36' identified by 'sy@888678'; 生效 flush privileges; 查看状态 show master status;
-
修改从库配置文件
[mysqld] ... server_id=2 read_only=ON systemctl restart mariadb mysql -u root -p change master to master_host='101.35.241.220',master_user='root',master_password='sy@888678'; flush privileges; start slave; show slave status\G;
3、django实现读写分离
配置数据库
django中实现读写分离,在settings
中设置数据库的时候,就需要添加多个数据库信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'db2': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
},
}
创建models并执行数据库迁移
# 数据库迁移
python manage.py makemigrations # 在migrations文件下生成记录
python manage.py migrate #迁移表
python manage.py migrate
# 默认是对defalut数据库进行迁移,并没有给其他数据库进行迁移,可以通过添加 --database db2 的方式指定数据库
python manage.py migrate --database db2
读取分离
手动设置读写分离
在使用数据库时,通过.using(db_name)
来手动指定要使用的数据库
from django.shortcuts import HttpResponse
from . import models
def write(request):
models.Products.objects.using('default').create(prod_name='熊猫公仔', prod_price=12.99)
return HttpResponse('写入成功')
def read(request):
obj = models.Products.objects.filter(id=1).using('db2').first()
return HttpResponse(obj.prod_name)
自动读写分离
通过配置数据库路由,来自动实现,这样就不用每次读写都手动指定数据库了。数据库路由提供4个方法。这里主要使用其中两个:def db_for_read()
决定读操作的数据库,def db_for_write
来决定写操作的数据库
定义Router类
新建db_router.py
脚本
# -*- coding: utf-8 -*-
class MasterSlaveDBRouter(object):
"""数据库主从读写分离路由"""
def db_for_read(self, model, **hints):
"""读数据库"""
return "slave"
def db_for_write(self, model, **hints):
"""写数据库"""
return "default"
def allow_relation(self, obj1, obj2, **hints):
"""是否运行关联操作"""
return True
settings.py中配置数据库路由
# settings.py
...
...
DATABASE_ROUTES = ["MySite.db_router.MasterSlaveDBRouter"]
一主多从方案
# -*- coding: utf-8 -*-
class MasterSlaveDBRouter(object):
"""数据库主从读写分离路由"""
def db_for_read(self, model, **hints):
"""读数据库"""
import random
return random.choice(['db2', 'db3', 'db4'])
def db_for_write(self, model, **hints):
"""写数据库"""
return "default"
def allow_relation(self, obj1, obj2, **hints):
"""是否运行关联操作"""
return True
分库分表
在大型web项目中,常常会创建多个app来处理不同的业务,如果希望实现app之间的数据库分离,比如app01走数据库db1,app02走数据库
class Router:
def db_for_read(self, model, **hints):
if model._meta.app_label == 'app01':
return 'db1'
if model._meta.app_label == 'app02':
return 'db2'
def db_for_write(self, model, **hints):
if model._meta.app_label == 'app01':
return 'db1'
if model._meta.app_label == 'app02':
return 'db2'
本文来自博客园,作者:暮歌行,转载请注明原文链接:https://www.cnblogs.com/xuejian123/p/17204316.html