使用sqlalchemy 使mysq自动读写分离:

代码如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy, SignallingSession, get_state
from sqlalchemy import orm app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@192.168.105.134:3306/test30' # 设置数据库连接地址
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 是否追踪数据库变化(触发某些钩子函数), 开启后效率会变
app.config['SQLALCHEMY_ECHO'] = True # 开启后, 控制台会打印底层执行的SQL语句 app.config['SQLALCHEMY_BINDS'] = { # get_engine的bind参数为该配置的键
'master': 'mysql://root:mysql@192.168.105.134:3306/test30',
'slave': 'mysql://root:mysql@192.168.105.134:8306/test30'
} class RoutingSession(SignallingSession):
def get_bind(self, mapper=None, clause=None):
"""当进行数据操作时, 会调用该方法来获取进行该操作的数据库引擎(连接)""" state = get_state(self.app)
if self._flushing: # 增删改操作, 使用主库
print('使用主库')
return state.db.get_engine(self.app, bind='master')
else: # 读操作, 使用从库
print('使用从库')
return state.db.get_engine(self.app, bind='slave') class RoutingSQLAlchemy(SQLAlchemy):
def create_session(self, options):
return orm.sessionmaker(class_=RoutingSession, db=self, **options) # 初始化组件(建立数据库连接)
db = RoutingSQLAlchemy(app) # ORM 类->表 类属性->字段 对象->记录
class User(db.Model):
__tablename__ = "t_user" # 设置表名, 默认为类名的小写
id = db.Column(db.Integer, primary_key=True) # 主键
name = db.Column(db.String(20), unique=True, nullable=False) # 设置唯一&非空约束
age = db.Column(db.Integer, default=10, index=True) # 设置默认值约束&建立索引 @app.route('/')
def index():
# 增加数据 进行检验是否读写分离
# 1.创建模型对象
user1 = User(name='zs', age=20)
db.session.add(user1)
db.session.commit() print('-' * 30)
# 查询数据
print(User.query.all())
return "index" if __name__ == '__main__':
db.drop_all() # 删除所有继承自db.Model的表
db.create_all() # 创建所有继承自db.Model的表
app.run(debug=True)

手动时mysql读写分离:

1,修改源码:routing_sqlalchemy.py

import random
from flask_sqlalchemy import SQLAlchemy, BaseQuery, Model, SignallingSession, get_state
from sqlalchemy import orm class Config:
SQLALCHEMY_BINDS = {
"bj_m1": 'mysql://root:mysql@192.168.105.134:3306/test30',
"bj_m2": 'mysql://root:mysql@192.168.105.134:3306/test30',
"bj_s1": 'mysql://root:mysql@192.168.105.134:8306/test30',
"bj_s2": 'mysql://root:mysql@192.168.105.134:8306/test30',
}
SQLALCHEMY_CLUSTER = {
"masters": ["bj_m1", "bj_m2"],
"slaves": ['bj_s1', 'bj_s2'],
"default": 'bj_m1'
}
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False class RoutingSession(SignallingSession):
def __init__(self, db, autocommit=False, autoflush=True, **options):
SignallingSession.__init__(self, db, autocommit=autocommit, autoflush=autoflush, **options)
self.default_key = db.default_key
self.master_keys = db.master_keys if len(db.master_keys) else self.default_key
self.slave_keys = db.slave_keys if len(db.slave_keys) else self.default_key
self.bind_key = None def get_bind(self, mapper=None, clause=None):
"""获取会话使用的数据库连接engine"""
state = get_state(self.app) if self.bind_key:
# 指定
print('Using DB bind: _name={}'.format(self.bind_key))
return state.db.get_engine(self.app, bind=self.bind_key)
else:
# 默认数据库
print('Using default DB bind: _name={}'.format(self.default_key))
return state.db.get_engine(self.app, bind=self.default_key) def set_to_write(self):
"""使用写数据库"""
self.bind_key = random.choice(self.master_keys) def set_to_read(self):
"""使用读数据库"""
self.bind_key = random.choice(self.slave_keys) class RoutingSQLAlchemy(SQLAlchemy):
def init_app(self, app):
config_binds = app.config.get("SQLALCHEMY_BINDS")
if not config_binds:
raise RuntimeError('Missing SQLALCHEMY_BINDS config') cluster = app.config.get("SQLALCHEMY_CLUSTER")
if not cluster:
raise RuntimeError('Missing SQLALCHEMY_CLUSTER config') default_key = cluster.get('default')
if not default_key:
raise KeyError("deafult is not in SQLALCHEMY_CLUSTER") # 生成并保存数据库引擎
self.master_keys = cluster.get("masters") or []
self.slave_keys = cluster.get("slaves") or []
self.default_key = default_key super(RoutingSQLAlchemy, self).init_app(app) def create_session(self, options):
return orm.sessionmaker(class_=RoutingSession, db=self, **options)

2, __init__.py下导入routing_sqlalchemy.py 中的类创建 db

from .routing_sqlalchemy import RoutingSQLAlchemy

db = RoutingSQLAlchemy()

3,定义装饰器类,实现读写分离

import functools

from user_select import db

def set_read_db(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
db.session().set_to_read()
return f(*args, **kwargs) return wrapper def set_write_db(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
db.session().set_to_write()
return f(*args, **kwargs) return wrapper

4,使用装饰器方式,调用读写分离,如果用装饰器,都使用主库进行读写

from flask import Flask
from user_select import db
from user_select.routing_sqlalchemy import Config
from user_select.decorator import set_read_db, set_write_db app = Flask(__name__)
app.config.from_object(Config) # 初始化数据库连接对象
db.init_app(app) # 建立映射模型 类->表 类属性->字段 对象->记录
class User(db.Model):
__tablename__ = 't_user' # 设置表名 表名默认为类名小写
id = db.Column(db.Integer, primary_key=True) # 主键 默认主键自增
name = db.Column(db.String(20), unique=True) # 设置唯一
age = db.Column(db.Integer) @app.route('/')
@set_write_db
def index():
"""增加数据"""
user1 = User(name='lisi', age=20)
db.session.add(user1)
db.session.commit() return "index" @app.route('/demo1')
# @set_read_db
def demo1():
users = User.query.all()
print(users)
return 'demo1' if __name__ == '__main__':
# db.drop_all() # 删除所有继承自db.Model的表
# db.create_all() # 创建所有继承自db.Model的表
app.run(debug=True)

mysql 读写分离(手动和自动方法)的更多相关文章

  1. 【转】双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    架构简介 前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构.此架构主要是由kee ...

  2. 双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构. 架构简介 此架构主要是由ke ...

  3. 18、mysql读写分离实现的方法

    18.1.mysql读写分离实现的方法: 1.通过程序实现读写分离: php和java程序实现读写分离(性能,效率最佳,推荐); php和java程序都可以通过设置多个连接文件轻松实现对数据库的读写分 ...

  4. MySQL读写分离技术

    1.简介 当今MySQL使用相当广泛,随着用户的增多以及数据量的增大,高并发随之而来.然而我们有很多办法可以缓解数据库的压力.分布式数据库.负载均衡.读写分离.增加缓存服务器等等.这里我们将采用读写分 ...

  5. [记录]MySQL读写分离(Atlas和MySQL-proxy)

    MySQL读写分离(Atlas和MySQL-proxy) 一.阿里云使用Atlas从外网访问MySQL(RDS) (同样的方式修改配置文件可以实现代理也可以实现读写分离,具体看使用场景) 1.在跳板机 ...

  6. 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变

    [Mysql主从复制]解决的问题数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了.负载均衡:M ...

  7. mysql读写分离实战

    一个完整的MySQL读写分离环境包括以下几个部分: 应用程序client database proxy database集群 在本次实战中,应用程序client基于c3p0连接后端的database ...

  8. Mysql-Proxy实现mysql读写分离、负载均衡 (转)

    在mysql中实现读写分离.负载均衡,用Mysql-Proxy是很容易的事,不过大型处理对于性能方面还有待提高,主要配置步骤如下: 1.1. mysql-proxy安装 MySQL Proxy就是这么 ...

  9. 提高性能,MySQL 读写分离环境搭建

    这是松哥之前一个零散的笔记,整理出来分享给大伙! MySQL 读写分离在互联网项目中应该算是一个非常常见的需求了.受困于 Linux 和 MySQL 版本问题,很多人经常会搭建失败,今天松哥就给大伙举 ...

随机推荐

  1. 3年java开发面试BAT,你必须彻底搞定Maven!

    前言 现在的Java项目中,Maven随处可见. Maven的仓库管理.依赖管理.继承和聚合等特性为项目的构建提供了一整套完善的解决方案,如果你搞不懂Maven,那么一个多模块的项目足以让你头疼,依赖 ...

  2. 使用if判断字符串的长度是否等于10,根据结果进行不同的输出

    string1=' print(len(string1)) # 使用len()计算字符串长度 if not len(string1) ==10: print('字符串的长度不为10') else: p ...

  3. CentOS下多种方法显示文本行号

    一.创建文本文件 ..}| >test.txt cat test.txt 二.多种方法显示行号 方法一:nl命令(注意:空行不显示行号) [root@WT data]# nl test.txt ...

  4. Vue ---- 项目与环境搭建 初始项目结构 Vue生命周期

    目录 1. vue环境搭建 2. Vue项目搭建 pycharm配置并启动vue项目 3 . 认识项目 1. vue项目目录结构 2. 配置文件:vue.config.js 3. main.js 4. ...

  5. linux指令-date

    1.在linux中要显示日期,则可以直接输入指令date 2.如果想以这样2016/12/26的方式输出呢,那就是,Y是年份,m是月份,d是日 date +%Y/%m/%d 3.如果要显示时间,则da ...

  6. VScode安装golang插件详细教程

    可能是由于非科班自学编程,所以在安装插件的时候虽然参考了很多人写的教程,但是总安装不成功,在综合各位大牛的教程之后进行总结,并且亲自实践安装成功,希望能给初学编程的人一些帮助,如果有不对的地方还希望大 ...

  7. Ubuntu16.04+GTX2070+Driver418.43+CUDA10.1+cuDNN7.6

    最近需要用到一台服务器的GPU跑实验,其间 COLMAP 编译过程出错,提示 cuda 版本不支持,cmake虽然通过了,但其实没有找到支持的CUDA架构. cv@cv:~/mvs_project/c ...

  8. adb shell常用命令

    一.文件操作相关命令 1.文件操作命令 子命令 参数 说明 cd 无 进入目录 cat [-beflnstuv] [-B bsize] [file...] 查看文件内容-n:显示行号-b:显示行号,但 ...

  9. (办公)记事本_Linux权限

    参考谷粒学院Linux教程:http://www.gulixueyuan.com/course/300/task/7084/show# linux权限,什么用户可以操作什么. 1.基本权限的作用: 1 ...

  10. Centos 下安装 Nginx(新)

    今天重新实践了下 CentOS 7.6 下安装 Nginx,总结了一条更直接并简单的方式 从官方获取写入 nginx.repo 的方式 从官网查看文档,获取 nginx.repo 的文档内容,将其内容 ...