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步

  1. master将改变(除select之外)全部记录到二进制日志(binary log)中
  2. slave的io线程将master的 binary log 拷贝到它的中继日志(relay log)
  3. slave的sql线程解析中继日志中的事件并在从库中执行,保持和主库一致

复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。

二进制日志格式

  • binlog_format=statement
  • binlog_format=row
  • binlog_format=mixed

其中基于row的复制方式更能保证主从库数据的一致性,但日志量较大,在设置时考虑磁盘的空间问题

主从复制的方式

  • 异步复制
  • 半同步复制

异步复制原理介绍

客户端线程提交一个写操作,写入主库的binlog日志后就立即返回,并不需要等待从库完成同步操作,而主库的dump线程会监测binlog日志的变量然后主动将更新推送给从库。

MySQL 主从复制默认是异步的模式。

主库停服时制作主从

  1. 在主库上创建一个用于复制的账号,并赋予replication slave权限,这里必须 *.* 不能指定库授权,因为 replication slave 是全局的

    mysql> grant replication slave on *.* to 'jason'@'%' identified by '123';
    mysql> flush privileges;
    
  2. 修改主库配置文件,开启主库的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;
    
  3. 修改从库配置文件

    [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'
posted @ 2023-03-11 23:03  暮歌行  阅读(30)  评论(0编辑  收藏  举报