使用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. where和having区别

    壹: where后面不能跟聚合函数(sum.avg.count.max.min) having后面可以跟 贰: where和having都能用: select goods_price,goods_na ...

  2. Spring Integration - WS Outbound Gateway

    1.通过MessageSender客户化http连接参数 AbstractHttpWebServiceMessageSender有若干实现子类: - CommonsHttpMessageSender( ...

  3. .NET 中数据访问用的 DBHelper(Sql Server) 类

    public class DBHelper { private static string DBConnectString = "Data Source=.;Initial Catalog= ...

  4. 前端day01

    目录 软件开发架构 web服务的本质 HTTP协议 HTML的注释 HTML的文档结构 标签的分类 标签的分类 列表标签 表格标签 软件开发架构 ​ c/s ​ b/s ​ b/s本质也是c/s ​ ...

  5. 千呼万唤始出来——uFUN开发板2.0开箱评测

    前言 今年3月,我参与了面包板社区组织的第一批uFUN开发板评测活动,并有幸能获得试用机会,那是我第一次了解到uFUN这个项目及背后的故事,4月份,uFUN 2.0版本来了,收到了张工送的一块样板,后 ...

  6. Android 基于ksoap2的webservice请求的学习

    [学习阶段] WebService网络请求? 其实我也是第一次遇到,之所以有这个需要是因为一些与 ERP 相关的业务,需要用到这样的一个请求方式. 开始学习WebService ①当然是百度搜索,这里 ...

  7. C++之下载Visual Studio Installer缓慢问题

    将IPv4中设置DNS首选项为8.8.8.8即可.

  8. .NET Core 发布(dotnet publish)

    目录 一.需求 二.方法 三.参考 一.需求 使用.net core 3.0建的项目,一般情况下,每次想发布都要打开vs,然后点击发布,选择配置: 如果想用cmd命令行发布,应该怎么写呢? 二.方法 ...

  9. 封装和@property

    封装和@property 一.复习 1.接口类和抽象类 python中没有接口类,有抽象类,abc模块中的metaclass=ABCMeta,@abstructmethod,本质是做代码规范用的,希望 ...

  10. Mysql - 读写分离与读负载均衡之Maxscale

    一.概述 常见的高可用方案如MMM和MHA等都将重点放在主库上,一旦主库出现故障,通过这些方案能将主库故障进行转移. 本文将给大家介绍一款由mariadb公司出品的中间件Maxscale,该中间件能实 ...