分布式事务
分布式事务1. 分布式事务场景 当项目是微服务架构时,一个功能需求可能需要多个微服务共同完成,这个过程就难免会操作不同服务下的不同数据库,那么如何保证数据库的ACID的性质呢? 除了微服务架构,只要是分布式架构就会面临同样的问题,此时无法通过mysql提供的事务功能解决,此时就需要用到分布式事务解决方案。
2. Seata2.1 认识Seata Seata是阿里提供的开源分布式事务框架(https://seata.apache.org/zh-cn/docs/overview/what-is-seata/)。 在Seata的事务管理中,有三个角色:
TC(Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或者回滚;
TM(Transaction Manager) - 事务管理器:定义全局事务的范围,开始全局事务、提交或回滚全局事务;
RM(Resource Manager) - 资源管理器:管理分支事务,于TC交互以注册分支事务和报告分支事务的状态,驱动分支事务提交或者回滚。&em ...
微服务保护
微服务保护一、微服务保护基础1.1 雪崩问题的产生原因 在前面两篇blog中解决了微服务项目中远程调用、网关和配置相关的内容,这已经可以解决微服务项目中大部分的问题了,但是仍存在一些问题,考虑如下场景: 一个微服务项目,服务A需要调用服务B提供的服务,但是服务B可能会抛出异常;或者服务B并发量很高,导致服务B响应服务A的时延很长,甚至超时导致查询失败。此时会导致服务A的响应时间很长,若在高并发的场景下,Tomcat连接占用很多,会拖垮服务中其他接口的响应时间。 若还有其他服务调用服务A,同样会拖垮调用者服务,这样会导致级联失败,产生雪崩问题。
1.2 服务保护方案
请求限流
线程隔离
服务熔断
请求限流 产生雪崩问题的原因,归根结底就是并发太高!因此请求限流,就是限制或控制接口访问的并发流量,避免服务因流量激增而出现故障。
线程隔离 当一个服务接口响应时间长,并且处在高并发状态时,此时会占用大量的Tomcat连接,这样会导致服务内其他接口的请求时延也大大增加。为解决这个问题,可以对服务内的接口设置占用最大线程数,这样该服 ...
微服务-网关和配置
网关一、网关快速入门1.1 认识网关 当项目采用微服务架构时,由于每个服务有自己服务器端口,这样产生了以下两个问题:
后端服务器接口过多,而且后期可能会进行更改或者扩展,因此前端对后端不同服务的请求会很复杂,难以管理;
微服务的多个服务可能会有登录请求校验,获得用户信息等功能,如果在多个模块中添加相应的功能代码,会导致程序冗余。
为解决以上问题,就需要一个同一管理后端微服务接口的中间件,这就是路由网关。网关对外暴露一个端口,随后根据请求的URL将请求路由转发给提供相应服务的后端微服务,同时可以在网关设置登录校验等统一功能。
在SpringCloud有两种网管实现方案,现在一般采用SpringCloudGateway(https://spring.io/projects/spring-cloud-gateway#learn)的解决方案。
1.2 使用步骤
步骤一:创建新模块
步骤二:引入依赖:SpringCloudGateway、nacos发现以及负载均衡依赖123456789101112131415<!--网关--> ...
微服务-远程调用
前置一、微服务与单体架构1.1 单体架构
定义:一个项目所有功能模块都在一个工程中开发,项目的部署和开发比较简单
缺点:
团队协作成本高
系统的发布效率差:一个项目的任意一个模块的bug都会导致整个项目需要重新编译部署
系统可用性差:各模块之间会互相影响,一个热点的功能会耗尽大部分的服务器资源,导致其他功能模块服务低可用
1.2 微服务
定义:将一个项目中的不同模块拆分出来,独立部署为多个服务。
特点:
单一职责:一个微服务负责一部分业务功能,核心模块不依赖其他模块
团队自治:每个微服务有自己的一整套开发、测试、运维等人员
服务自治:每个服务独立打包、部署,访问自己独立的数据库。
1.3 SpringCloud
SpringCloud是一个标准规范,其并不提供具体的服务,而SpringCloudAlibaba是一个满足SpringCloud规范的微服务框架的具体实现,它提供了具体的解决方案。两者关系类似于接口和实现类
使用方法 在父工程里面引入SpringCloud和SpringCloudAlibaba的依赖管理,这样有关这两个依赖的版本就无需配置了
12 ...
docker基础入门
docker基础入门
以下内容基于centOS-7,镜像传送门:https://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
一、docker安装1.1 卸载旧版 尝试卸载旧版,如果存在就卸载,不存在也没有影响,命令如下:
123456789yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine \ docker-selinux
1.2 配置docker的yum库 首先安装yum工具,这里安装了三个包,其中-y代表安装中所有询问都默认为‘yes’
1sudo yum install -y yum-utils device-mapper-persistent-data lv ...
黑马点评项目总结(下)
五、消息队列5.1 异步阻塞队列对秒杀的优化5.1.1 前言 前面实现的优惠券秒杀业务流程,从判断库存是否充足,是否有购买资格知道最后于数据库的交互都是线性执行的,但是和数据库的交互会消耗大量时间,降低了效率。
5.1.2 异步思路 由于与数据库交互浪费时间,因此可以把这部分的代码交给一个新开辟的线程去处理。那么如何取到每一个订单呢? 在下单前的种种判断逻辑处理比较快,交给主线程处理,若用户拥有购买资格且库存充足,那么生成一个订单ID,并将给订单ID添加到一个阻塞队列里;开辟的子线程时刻监听阻塞队列,一旦取到订单ID就会于数据库交互执行相应的业务代码。 下图是主线程执行的业务逻辑,其中不包括与数据库打交道的部分。
与数据库交互的部分:首先开辟一个线程池,线程池的任务就是监听阻塞队列,一旦取到了订单ID就与数据库进行交互。 由于业务中对多个数据库进行了修改,因此需要添加事务,因此如果直接调用方法又会出现事务失效的问题,因此需要通过获得代理对象,间接调用方法。但是获取代理对象是基于当前线程的,因此无法在开辟的子线 ...
黑马点评项目总结(中)
三、优惠券秒杀3.1 全局ID生成器3.1.1 原因 受限于单表的存储能力,分表会导致重复ID,同时要保证ID的安全性,无法使用数据库的自增字段
3.1.2 生成方式 当系统是分布式系统时,也需要满足全局ID唯一,因此采用Redis生成全局唯一ID。为保证安全性,需要将redis自增的数值拼接一些其他内容,具体生成策略如下:
第一位为符号位
接下来的31位用时间戳填满,以秒为单位
最后32位是自增序列号,每秒内可支持2^32^个ID
3.1.3 其他全局唯一ID生成策略
UUID
snowflake算法 (算法在附录中)
数据库自增
3.2 实现秒杀下单3.2.1 业务流程
3.2.2 存在的问题 在当前的实现中,会产生多卖问题,这属于多线程安全问题。为解决此问题,需要给当前业务加锁。
乐观锁 vs 悲观锁
乐观锁:
认为线程安全问题不一定会发生,因此不会加锁,只会在更新数据时检查数据有没有被其他线程修改。
悲观锁:
认为线程安全问题一定会发生,因此在代码执行前先获取锁,保证线程串行执行。
3.2.3 解决方案及代码实现&em ...
黑马点评项目总结(上)
黑马点评项目技术总结一、基于Redis实现发送短信验证码功能1.1 基于session实现发送短信验证码功能流程1.1.1 发送短信验证码 若用户使用手机号 + 短信验证码的方式进行登录,当用户点击获取验证码时,会向后台发送一条请求,下图就是后台对该请求的处理流程:
校验手机号
生成验证码
保存验证码到session(用于后续校验)
发送验证码到用户手机
1.1.2 短信验证码登录、注册 这一步是用户点击登录按钮发送到后端的请求,后端对该请求的处理流程,具体如下:
校验手机号(这一步是防止用户在登陆前修改手机号)
根据第一步保存到session的验证码与前端发送的验证码比对
判断用户是否已注册
将用户保存到session中,为后续其他网页的校验做准备
1.1.3 校验登陆状态 为了实现对用户的每一个页面访问进行校验的功能,此时需要用到拦截器,在拦截器中对http请求携带的cookie以及保存在session中的信息进行比较。拦截器的实现以及拦截器和过滤器的区别将在后文进行说明。 若存在用户,则将脱敏后的用户信息保存到ThreadLocal中,由于每一个sessi ...