rabbitmq幂等性怎么解决,spring如果解决循环依赖,jvm优化,nginx负载设计,redis分布式锁(保证高并发库存不少于0),cloud组件,rabbitmq,分布式事务,spring5.mysql8.0,工作流,数据库引擎,mysql,redis区别,jar包war包区别,boot mvc 区别,g1,cms,hystrix和幂等性,kafka原理,讲讲dubbo原理
幂等性总结
1,什么是幂等性
幂等性的数学表达式:f(f(x))=f(x)。幂等性是系统接口对外的一种承诺,使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同。
2, 电商常见问题:
2.1. 如何防范 POST 重复提交
HTTP POST 操作既不是安全的,也不是幂等的(至少在HTTP规范里没有保证)。
当我们因为反复刷新浏览器导致多次提交表单,多次发出同样的POST请求,导致远端服务器重复创建出了资源。
所以,对于电商应用来说,第一对应的后端 WebService 一定要做到幂等性,第二服务器端收到 POST 请求,在操作成功后必须302跳转到另外一个页面,这样即使用户刷新页面,也不会重复提交表单。
2.2. 集群环境下的定时任务幂等性
分布式环境下,定时任务或异步处理如何保持幂等性?
那么如何设计接口才能做到幂等呢?
方法一、单次支付请求,也就是直接支付了,不需要额外的数据库操作了,这个时候发起异步请求创建一个唯一的ticketId,就是门票,这张门票只能使用一次就作废,具体步骤如下:
异步请求获取门票
调用支付,传入门票
根据门票ID查询此次操作是否存在,如果存在则表示该操作已经执行过,直接返回结果;如果不存在,支付扣款,保存结果
返回结果到客户端
如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的
方法二、分布式环境下各个服务相互调用
这边就要举例我们的系统了,我们支付的时候先要扣款,然后更新订单,这个地方就涉及到了订单服务以及支付服务了。
用户调用支付,扣款成功后,更新对应订单状态,然后再保存流水。
而在这个地方就没必要使用门票ticketId了,因为会比较闲的麻烦
(支付状态:未支付,已支付)
步骤:
1、查询订单支付状态
2、如果已经支付,直接返回结果
3、如果未支付,则支付扣款并且保存流水
4、返回支付结果
如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的
对于做过支付的朋友,幂等,也可以称之为冲正,保证客户端与服务端的交易一致性,避免多次扣款。
消息队列如何实现幂等性
1,如《消息总线消息必达》所述,MQ消息必达,架构上有两个核心设计点:
(1)消息落地
(2)消息超时、重传、确认
消费端-幂等性保障幂等性 : 多次执行, 结果保持一致主流的幂等性操作唯一ID + 指纹码机制, 利用数据库主键去重
好处 : 实现简单坏处 : 高并发下有数据库写入的性能瓶颈解决方案 : 根据ID进行分库分表进行算法路由利用Redis的原子性实现
需要关注的问题:
是否要进行数据落库, 如果落库的话, 数据库和缓存如何做到原子性
如果不落库, 数据都存储到缓存中, 如何设置定时同步的策略
spring如果解决循环依赖
Spring只能解决Setter方法注入的单例bean之间的循环依赖
ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环。Spring在获取ClassA的实例时,不等ClassA完成创建就将其曝光加入正在创建的bean缓存中。在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。
redis分布式锁(保证高并发库存不少于0)
zk的原理 就是创建节点 节点只能被创建一次;Redis.setnx对一个key只能插入一次.优缺点.redis 性能好;zk 实用性好。Redis 需要设置过期时间 服务器挂掉 只能等到时间过了 才能继续zk创建的临时节点,客户端断了节点就消失了。
工作流
分布式事务
spring cloud
链接最后再来总结一下,上述几个Spring Cloud核心组件,在微服务架构中,分别扮演的角色:
Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务
g1 cms
dubbo原理
dubbo是一个分布式服务框架,致力于提供高性能透明化的rpc远程服务调用方案,以及soa服务治理方案。
核心包括三部分:
1,远程通讯:提供对多种基于长连接的NIO框架的抽象封装,包括多种线程模型,序列化,以及‘请求-响应’模式的信息交换。
2,软件负载均衡和容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3,服务自动注册额和发现,不需要写死服务提供者地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加和删除服务提供者。
注册服务配置文件
生产者
<!-- 整合Dubbo -->
<!-- 第一步:Dubbo起名称 计算用此名称来区分 -->
<dubbo:application name="babasport-service-product"/>
<!-- 第二步:中介 注册中心: zookeeper redis ... -->
<!-- <dubbo:registry address="192.168.200.128:2181,192.168.200.129:2181,192.168.200.130:2181" protocol="zookeeper"/> -->
<dubbo:registry address="192.168.200.128:2181" protocol="zookeeper"/>
<!-- 第三步:设置dubbo的端口号 192.168.40.88:20880/接口 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 第四步:设置服务提供方 提供的接口 也可以使用注解的方式 -->
<dubbo:service interface="cn.itcast.core.service.TestTbService" ref="testTbService"/>、
消费者
<!-- 整合Dubbo -->
24 <!-- 第一步:Dubbo起名称 计算用此名称来区分 -->
25 <dubbo:application name="babasport-console"/>
26 <!-- 第二步:中介 注册中心 zookeeper redis ... -->
27 <!--<dubbo:registry address="192.168.200.128:2181,192.168.200.129:2181,192.168.200.130:2181" protocol="zookeeper"/> -->
28 <dubbo:registry address="192.168.200.128:2181" protocol="zookeeper"/>
29 <!-- 第三步:调用服务提供方 提供的接口 -->
30 <dubbo:reference interface="cn.itcast.core.service.TestTbService" id="testTbService"/>
31
NIO
webservice
webservice 与dubbo类似,也是一种远程调用技术,也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。XML:(Extensible Markup Language)扩展型可标记语言。面向短期的临时数据处理、面向万维网络,是Soap的基础。Soap:(Simple Object Access Protocol)简单对象存取协议。是XML Web Service 的通信协议。当用户通过UDDI找到你的WSDL描述文档后,他通过可以SOAP调用你建立的Web服务中的一个或多个操作。SOAP是XML文档形式的调用方法的规范,它可以支持不同的底层接口,像HTTP(S)或者SMTP。WSDL:(Web Services Description Language) WSDL 文件是一个 XML 文档,用于说明一组 SOAP 消息以及如何交换这些消息。大多数情况下由软件自动生成和使用。
jvm优化
在java中通过多线程使得多个任务同时执行处理,所有的线程共享JVM内存区域main memory,每个线程又单独的有自己的工作内存,当线程和内存区域进行交互时,数据从主存拷贝到工作内存,进而交由线程处理。
程序计数器:程序计数器是一块小的内存空间,他的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时就说通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程回复等基础功能都需要依赖这个计数器来完成。
java虚拟机栈:与程序计数器一样,java虚拟机也是线程私有的,