分布式架构(分布式ID+分布式事务)

分布式架构

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

=====================

分布式事务产生的场景:

跨JVM进程产生的分布式事务
在这里插入图片描述
单体系统访问多个数据库实例
在这里插入图片描述
多服务访问同一个数据库实例
在这里插入图片描述

CAP理论

在这里插入图片描述

C:一致性,指写操作后的读操作可以读取到最新的数据状态,当数据分布在多个节点上,从任意节点读取到的数据都是最新状态。
写入主数据库后要将数据同步到从数据库
写入主数据库后,在向从数据库同步期间要将从数据库锁定,待同步完成后再释放锁,以免在新数据写入成功后,向从数据库查询到旧的数据

A:可用性,指任何事务操作都可以得到响应结果,且不会出现响应超时或响应错误。
写入主数据库后要将数据同步到从数据库
由于要保证从数据库的可用性,不可将从数据库中的资源进行锁定
即使数据还没有同步过来,从数据库也要返回要查询的数据,哪怕是旧数据,如果连旧数据也没有则可以按照约定返回一个默认的信息,但不能返回错误或响应超时。

P:分区容忍性,网络分区的不同结点出现的网络问题导致节点之间通信失败,此时仍然可以对外提供服务。
尽量使用异步取代同步操作,使用异步方式将数据从主数据库同步到从数据库,这样节点之间能够有效的实现松耦合
添加从数据库节点,其中一个节点挂掉后,其他从节点提供服务。

CAP组合
在这里插入图片描述

Base理论

在这里插入图片描述

========================================

分布式事务解决方案

2PC 两阶段提交
在这里插入图片描述
在这里插入图片描述

XA方案
需要本地数据库支持XA协议
资源锁需要等到两个阶段结束才释放,性能较差
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Seata方案
阿里中间件,分布式事务框架
提供AT模式(2PC)以及TCC模式的分布式事务解决方案
把分布式事务理解为一个包含了若干分支事务的全局事务,全局事务的职责是协调其下管辖的分支事务达成一致
要么一起成功提交,要么一起失败回滚。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
程序实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置文件
application.yml
application-local.yml
file.conf

dtx-seata-demo-bank1
张三账户减少金额,开启全局事务
远程调用bank2向李四转账

//Dao   MyBatis框架进行
@Mapper
@Component
public interface AccountInfoDao{@Update("update account_info set account_blance = account_balance + #{amount} where account_no = #{accountNo}")int updateAccountBalnce(@Param("accountNo") String accountNo,@Param("amount") Double amount);
}
//张三扣减金额
public interface AccountInfoService{public void updateAccountBalance(String accountNo,Double amount);
}
@Service
@Slf4j
public class AccountInfoServiceImpl implements AccountInfoService{@AutowiredAccountInfoDao accountInfoDao;@AutowiredBank2Client bank2Client;@Transactional@BlobalTransactional//开启全局事务@Overridepublic void updateAccountBalance(String accountNo,Double amount{//扣除张三的金额accountInfoDao.updateAccountBalance(accountNo,amount * -1);//调用李四的微服务来转账String transfer = bank2Client.transfer(amount);if("fallback".equals(transfer)){//调用李四微服务异常throw new RuntimeException("调用李四微服务异常");}}
}
//FeignClient
@FeignClient(value="seata-demo-bank2",fallback=Bank2ClientFallack.class)//如果调用失败,降级
public interface Bank2Client{//远程调用李四的微服务@GetMapping("/bank2/transfer")public String transfer(@RequestParam("amount") Double amout);
}
//调用失败降级
@Component
public class Bank2ClientFallback implements Bank2Client{@Overridepublic String transfer(Double amount){return "fallback";}
}
//启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients(basePackages = {"cn.michael.bank1.spring"})//专门扫描客户端的包
public class Bank2Server{public static void main(String[] args){SpringApplication.run(Bank2Server.class,args);}
}

dtx-seata-demo-bank2

//李四账号增加金额
//分支事务,不适用@GlobalTransactional
@Mapper
@Component
public interface AccountInfoDao{@Update("UPDATE account_info SET account_balance = account_balance + #{amount} WHERE account_no")int updateAccountBalance(@Param("accountNo") String accountNo,@Param("amount") Double amount);
}
public interface AccountInfoService{public void updateAccountBalance(String accountNo,Double amount);
}
@Service
@Slf4j
public class AccountInfoServiceImpl implements AccountInfoService{@AutowiredAccountInfoDao accountInfoDao;//不使用@GlobalTransactional@Transactional@Overridepublic void updateAccountBalance(String accountNo,Double amount){accountaInfoDao.updateAccountBalance(accountNo,amount);}
} 

=========================================

分布式ID

在这里插入图片描述
在这里插入图片描述

一、数据库自增

①、创建一个数据库表

stub 字段无意义,只是为了占位,便于插入或者修改数据。并且,给 stub 字段创建了唯一索引,保证其唯一性。

CREATE TABLE `sequence_id` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,`stub` char(10) NOT NULL DEFAULT '',PRIMARY KEY (`id`),UNIQUE KEY `stub` (`stub`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

②、通过replace into 来插入数据

插入数据这里,没有使用 insert into 而是使用 replace into 来插入数据,具体步骤是这样的:

  1. 尝试把数据插入到表中
  2. 如果主键或唯一索引字段出现重复数据错误而插入失败时,先从表中删除含有重复关键字值的冲突行,然后再次尝试把数据插入到表中
BEGIN;
REPLACE INTO sequence_id (stub) VALUES ('stub');
SELECT LAST_INSERT_ID();
COMMIT;

优点:实现起来比较简单、ID 有序递增、存储消耗空间小
缺点:支持的并发量不大、存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度)、ID 没有具体业务含义、安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量,商业机密啊!)、每次获取 ID 都要访问一次数据库(增加了对数据库的压力,获取速度也慢)

二、数据库号段模式

数据库主键自增这种模式,每次获取 ID 都要访问一次数据库,ID 需求比较大的时候性能问题

可以批量获取,然后存在在内存里面,需要用到的时候,直接从内存里面拿就舒服了!这也就是我们说的 基于数据库的号段模式来生成分布式 ID
数据库的号段模式也是目前比较主流的一种分布式 ID 生成方式。像滴滴开源的Tinyid[1] 就是基于这种方式来做的。不过,TinyId 使用了双号段缓存、增加多 db 支持等方式来进一步优化。

①、创建一个数据表

current_max_id 字段和step字段主要用于获取批量 ID,获取的批量 id 为:current_max_id ~ current_max_id+step
version 字段主要用于解决并发问题(乐观锁),biz_type 主要用于表示业务类型。

CREATE TABLE `sequence_id_generator` (`id` int(10) NOT NULL,`current_max_id` bigint(20) NOT NULL COMMENT '当前最大id',`step` int(10) NOT NULL COMMENT '号段的长度',`version` int(20) NOT NULL COMMENT '版本号',`biz_type`    int(20) NOT NULL COMMENT '业务类型',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

②、先插入一行数据

INSERT INTO `sequence_id_generator` (`id`, `current_max_id`, `step`, `version`, `biz_type`)
VALUES(1, 0, 100, 0, 101);

③、通过 SELECT 获取指定业务下的批量唯一 ID

SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where `biz_type` = 101

在这里插入图片描述
④、不够用的话,更新之后重新 SELECT 即可。

UPDATE sequence_id_generator SET current_max_id = 0+100, version=version+1 WHERE version = 0  AND `biz_type` = 101
SELECT `current_max_id`, `step`,`version` FROM `sequence_id_generator` where `biz_type` = 101

在这里插入图片描述
相比于数据库主键自增的方式,数据库的号段模式对于数据库的访问次数更少,数据库压力更小。
另外,为了避免单点问题,你可以从使用主从模式来提高可用性。

优点:ID 有序递增、存储消耗空间小
缺点:存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度)、ID 没有具体业务含义、安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量,商业机密啊!)

三、NoSQL

通过 Redis 的 incr 命令即可实现对 id 原子顺序递增
在这里插入图片描述

为了提高可用性和并发,可以使用 Redis Cluster。Redis Cluster 是 Redis 官方提供的 Redis 集群解决方案(3.0+版本)。

除了 Redis Cluster 之外,也可以使用开源的 Redis 集群方案Codis[2] (大规模集群比如上百个节点的时候比较推荐)。

除了高可用和并发之外, Redis 基于内存,我们需要持久化数据,避免重启机器或者机器故障后数据丢失。Redis 支持两种不同的持久化方式:快照(snapshotting,RDB)、只追加文件(append-only file, AOF)。并且,Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。

优点:性能不错并且生成的 ID 是有序递增的
缺点:和数据库主键自增方案的缺点类似

除了 Redis 之外,MongoDB ObjectId 经常也会被拿来当做分布式 ID 的解决方案。
在这里插入图片描述
MongoDB ObjectId 一共需要 12 个字节存储:

  • 0~3:时间戳
  • 3~6:代表机器 ID
  • 7~8:机器进程 ID
  • 9~11:自增值

优点:性能不错并且生成的 ID 是有序递增的
缺点:需要解决重复 ID 问题(当机器时间不对的情况下,可能导致会产生重复 ID)、有安全性问题(ID 生成有规律性)

四、算法UUID

UUID 是 Universally Unique Identifier(通用唯一标识符) 的缩写。UUID 包含 32 个 16 进制数字(8-4-4-4-12)

JDK 就提供了现成的生成 UUID 的方法,一行代码就行了。

//输出示例:cb4a9ede-fa5e-4585-b9bb-d60bce986eaa
UUID.randomUUID()

不同的版本对应的 UUID 的生成规则是不同的

  • 版本 1 : UUID 是根据时间和节点 ID(通常是 MAC 地址)生成
  • 版本 2 : UUID 是根据标识符(通常是组或用户 ID)、时间和节点 ID 生成
  • 版本 3、版本 5 : 版本 5 - 确定性 UUID 通过散列(hashing)名字空间(namespace)标识符和名称生成
  • 版本 4 : UUID 使用随机性或伪随机性生成
    在这里插入图片描述
    JDK 中通过 UUID 的 randomUUID() 方法生成的 UUID 的版本默认为 4
UUID uuid = UUID.randomUUID();
int version = uuid.version();// 4

UUID 可以保证唯一性,因为其生成规则包括 MAC 地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,计算机基于这些规则生成的 UUID 是肯定不会重复的。

虽然,UUID 可以做到全局唯一性,但是,我们一般很少会使用它。比如使用 UUID 作为 MySQL 数据库主键的时候就非常不合适:

  • 数据库主键要尽量越短越好,而 UUID 的消耗的存储空间比较大(32 个字符串,128 位)
  • UUID 是无顺序的,InnoDB 引擎下,数据库主键的无序性会严重影响数据库性能

优点:生成速度比较快、简单易用
缺点:存储消耗空间大(32 个字符串,128 位)、 不安全(基于 MAC 地址生成 UUID 的算法会造成 MAC 地址泄露)、无序(非自增)、没有具体业务含义、需要解决重复 ID 问题(当机器时间不对的情况下,可能导致会产生重复 ID)

五、算法雪花

Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 由 64 bit 的二进制数字组成,这 64bit 的二进制被分成了几部分,每一部分存储的数据都有特定的含义:
在这里插入图片描述

  • sign(1bit):符号位(标识正负),始终为 0,代表生成的 ID 为正数
  • timestamp (41 bits):一共 41 位,用来表示时间戳,单位是毫秒,可以支撑 2 ^41 毫秒(约 69 年)
  • datacenter id + worker id (10 bits):一般来说,前 5 位表示机房 ID,后 5 位表示机器 ID(实际项目中可以根据实际情况调整)。这样就可以区分不同集群/机房的节点。
  • sequence (12 bits):一共 12 位,用来表示序列号。序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。

在实际项目中,一般也会对 Snowflake 算法进行改造,最常见的就是在 Snowflake 算法生成的 ID 中加入业务类型信息。

优点:生成速度比较快、生成的 ID 有序递增、比较灵活(可以对 Snowflake 算法进行简单的改造比如加入业务 ID)
缺点:需要解决重复 ID 问题(ID 生成依赖时间,在获取时间的时候,可能会出现时间回拨的问题,也就是服务器上的时间突然倒退到之前的时间,进而导致会产生重复 ID)、依赖机器 ID 对分布式环境不友好(当需要自动启停或增减机器时,固定的机器 ID 可能不够灵活)。

有很多基于 Snowflake 算法的开源实现比如美团 的 Leaf、百度的 UidGenerator(后面会提到),并且这些开源实现对原有的 Snowflake 算法进行了优化,性能更优秀,还解决了 Snowflake 算法的时间回拨问题和依赖机器 ID 的问题。

并且,Seata 还提出了“改良版雪花算法”,针对原版雪花算法进行了一定的优化改良,解决了时间回拨问题,大幅提高的 QPS。

分布式ID开源框架(百度、滴滴等)

=========================================

分布式 事务解决方案TCC

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
TCC需要主义三种异常处理:空回滚 幂等 悬挂
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableAspectAutoProxy //
@EnableFeignClients(basePackages = {"cn.....spring"})
@ComponentScan("xxx.bank1/bank2","org.dromarn.hmily")//要扫描的hmily
public class BankTccServer{public static void main(String[] args){StringApplication.run(BankTccServer.class,args);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/701435.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flet 读取本地音频文件的信息,歌名,歌手,歌曲长度,封面

请先安装 pip install flet, tinytag 组件 tinytag 是用来读取音频文件的信息的 测试用最好找一个有封面的音频的文件, 我是windows电脑,打开预览模式,选中文件时候能够右边显示图片, 如下,我电脑上某个音频文件的封面 import flet as ft from tinytag import TinyTag import…

自动驾驶---行业发展及就业环境杂谈

进入21世纪以来,自动驾驶行业有着飞速的发展,自动驾驶技术(L2---L3)也逐渐落地量产到寻常百姓家。虽然最早期量产FSD的特斯拉有着深厚的技术积累,但是进入2010年以后,国内的公司也逐渐发展起来自己的自动驾…

YOLOv5算法进阶改进(18)— 引入动态蛇形卷积DSConv(ICCV2023 | 用于管状结构分割)

前言:Hello大家好,我是小哥谈。动态蛇形卷积(Dynamic Snake Convolution,简称DSConv)是一种用于图像处理和计算机视觉任务的卷积神经网络(CNN)操作。它是在传统的卷积操作基础上引入了动态蛇形路径的概念,以更好地捕捉图像中的细节和边缘信息。传统的卷积操作是在固定的…

读书笔记-增强型分析:AI驱动的数据分析、业务决策与案例实践

目录 前言 运用人工智能技术,可以使人类社会变得更美好。人们总是期待产品更适合、服务更贴心、生活更便利。在实践中,技术给企业赋能,企业通过优质的产品和服务满足社会,提升人类福祉。很多金融企业已经开始尝试向潜在客户推送…

Uniapp小程序开发-底部tabbar的开发思路

文章目录 前言一、uniapp 实现 tabbar二、图标使用网络图片后端返回tabbar信息uniapp方式中的setTabBarItem 总结 前言 记录uniapp 开发小程序的底部tabbar ,这里讨论的不是自定义tabbar的情况。而是使用wx.setTabBarItem(Object object) 这个api的情况。关于custo…

【Linux进程】进程状态---进程僵尸与孤儿

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 1.进程排队2.进程状态…

【Ubuntu】通过网线连接两台电脑以实现局域网连接的方法

有时我们需要将多台计算机连接在一起,以便实现数据共享、资源访问等功能。本文将介绍如何通过网线连接两台运行Ubuntu操作系统的电脑,以便它们能够直接通信,从而实现局域网连接。 1. 准备工作 在开始之前,请准备好: …

[云原生] 二进制安装K8S(上)搭建单机matser、etcd集群和node节点

一、单机matser预部署设计 目前Kubernetes最新版本是v1.25,但大部分公司一般不会使用最新版本。 目前公司使用比较多的:老版本是v1.15,因为v1.16改变了很多API接口版本,国内目前使用比较多的是v1.18、v1.20。 组件部署&#xff…

WordPress前端如何使用跟后台一样的Dashicons图标字体?

很多站长都喜欢在站点菜单或其他地方添加一些图标字体,常用的就是添加Font Awesome 图标和阿里巴巴矢量库图标iconfont。其实我们使用的 WordPress 本身就有一套管理员使用的官方图标字体 Dashicons,登录我们站点后台就能看到这些图标字体。那么有没有可…

力扣思路题:丑数

此题的思路非常奇妙,可以借鉴一下 bool isUgly(int num){if(num0)return false;while(num%20)num/2;while(num%30)num/3;while(num%50)num/5;return num1; }

18个惊艳的可视化大屏(第六辑):地图焦点

本期带来的都是以地图作为视觉焦点的可视化大屏页面。

动态规划课堂1-----斐波那契数列模型

目录 动态规划的概念: 动态规划的解法流程: 题目: 第 N 个泰波那契数 解法(动态规划) 代码: 优化: 题目:最小花费爬楼梯 解法(动态规划) 解法1: 解…

独立站建站全攻略:从0到1打造专属在线商业平台

独立站建站全攻略:从0到1打造专属在线商业平台 随着互联网的普及和发展,越来越多的企业和个人开始认识到拥有一个独立站的重要性。独立站不仅可以提升品牌形象,还能为企业带来更多的流量和潜在客户。本文将为大家详细介绍独立站建站的全过程…

【深度学习笔记】卷积神经网络——汇聚层(池化层)

汇聚层(池化层) 通常当我们处理图像时,我们希望逐渐降低隐藏表示的空间分辨率、聚集信息,这样随着我们在神经网络中层叠的上升,每个神经元对其敏感的感受野(输入)就越大。 而我们的机器学习任…

VsCode的leetcode插件无法登录

前提 想使用VsCode的leetcode插件进行刷题,然后按照网上的教程进行安装下载,但是到了登录这一步,死活也登录不了,然后查看log一直报的错误是invalid password。 解决方法 首先确定在插件中设置的站点是Leetcode中国&#xff0c…

图像处理新框架 | 语义与复原指令双引擎,谷歌研究院提出文本驱动图像处理框架TIP

本文首发: AIWalker 欢迎关注AIWalker,底层视觉与基础AI技术 https://arxiv.org/abs/2312.14091 https://github.com/Picsart-AI-Research/HD-Painter 基于文本到图像扩散模型的空前成功,文本引导图像修复的最新进展已经可以生成非常逼真和视觉上合理的结…

centos7部署单机项目和自启动

centos7部署单机项目和服务器自启动 1.安装jdk和tomact1.1上传jdk、tomcat安装包1.2解压两个工具包1.3.配置并且测试jdk安装1.4.启动tomcat1.5.防火墙设置1.6配置tomcat自启动 2.安装mysql2.1卸载mariadb,否则安装MySql会出现冲突(先查看后删除再查看)2.2在线下载My…

【爬虫逆向实战篇】定位加密参数、断点调试与JS代码分析

文章目录 1. 写在前面2. 确认加密参数3. 加密参数定位4. XHR断点调试 【作者主页】:吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向…

python-分享篇-用python制作九宫格切图器

文章目录 代码效果 代码 import tkinter as tk from PIL import Image,ImageTk import sys import tkinter.filedialog#先将图片填充为正方形 def fill_image(image): width, height image.size #比较图片的宽和高,选取值较大的作为新图的宽 newImage_width wid…

仿12306校招项目-项目业务和架构

目录 业务图 用户管理 业务难点 1. 如何确定用户注册信息的真实性 2. 面对亿级用户量 3. 支持多种登录方式会造成读请求扩散,需要解决用户定位问题 4. 高并发场景下缓存穿透问题需要有效解决,避免数据库压力过大 5. 明文存储用户敏感信息会造成安…