分布式

分布式事务方案总结

本地事务不支持跨库操作

方案1

将有关联的表放在一个数据库中
1. 同一个数据库操作 可以使用一个事务
2. eg:用户表& 用户频道表 ,文章基本信息表 & 文章内容表

方案2

Mysql从5.6开始支持分布式事务
核心是二阶段提交协议(简称 2PC协议 / XA协议)
分布式事务会提供一个 事务管理器 来对 各数据库的本地事务进行统一管理, 只有各本地事务都向管理器 预提交 成功后, 事务管理器才会统一执行提交处理, 否则统一进行回滚处理
所有事务都成功后进行统一commit处理,失败则进行回滚
注意: 在Flask框架中,sqlalchemy 也支持分布式事务
我们 只需要在创建 SQLAlchemy对象时, 设置参数 session_options={‘twophase’: True}即可
设置后, 整个session的所有操作会被放入到一个分布式事务中, 并在整个分布式事务范围内保证原子性


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 设置多个数据库地址
app.config['SQLALCHEMY_BINDS'] = {
   'db1': 'mysql://root:mysql@192.168.105.140:3306/db1',
   'db2': 'mysql://root:mysql@192.168.105.140:3306/db2'
   }

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_ECHO'] = True

# 创建组件对象  设置二阶段提交
db = SQLAlchemy(app, session_options={'twophase': True})


# 用户表
class User(db.Model):
    __tablename__ = 't_user'
    __bind_key__ = 'db1'  # 设置数据库db1
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))


# 地址表
class Address(db.Model):
    __tablename__ = 't_adr'
    __bind_key__ = 'db2'  # 设置数据库db2
    id = db.Column(db.Integer, primary_key=True)
    detail = db.Column(db.String(20), unique=True)
    user_id = db.Column(db.Integer)


@app.route('/')
def index():
    """添加数据"""
    user1 = User(name='张三')
    db.session.add(user1)
    db.session.flush()

    adr1 = Address(detail='中关村3号', user_id=user1.id)
    adr2 = Address(detail='华强北5号', user_id=user1.id)
    db.session.add_all([adr1, adr2])
    db.session.flush()

    db.session.commit()  # 由于采用了分布式事务, 整个session的操作会被放入到一个分布式事务中, 并实现事务的原子性
    return "index"


@app.route('/demo1')
def demo1():
    """查询多表数据  需求: 查询姓名为"张三"的所有地址信息"""

    # 先根据姓名查找用户主键
    user1 = User.query.filter_by(name='张三').first()

    # 再根据主键到从表查询关联地址
    adrs = Address.query.filter_by(user_id=user1.id).all()
    for adr in adrs:
        print(adr.detail)

    return 'demo1'


if __name__ == '__main__':
    # 删除所有继承自db.Model的表
    db.drop_all()
    # 创建所有继承自db.Model的表
    db.create_all()

    app.run(debug=True)

注意点:
分布式事务要在所有事务都"提交成功"的情况下才会正式提交, 如果参与的部分节点卡顿, 会影响整个事务的性能

方案3

基于状态/消息的最终一致性方案
1.对于 包含多个子系统的大型项目, 需要保证子系统之间的数据一致性
2.单个子系统往往不会操作所有数据库, 但是 每个子系统可以通过定义字段来记录操作的状态, 每完成一个阶段则更新相应的状态
3.如我们在学习过程中经常使用的下单-付款流程中, 应用A的下单事务完成后更新订单状态为已下单, 应用B付款事务完成后, 再通过 支付回调接口 通知应用A 更新订单状态,应用B还需要提供一个 支付查询接口, 以便在用户查询或者订单超时的情况下, 让应用A可以查询订单的支付情况ebay提出的方案, 理论叫做BASE
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值