什么是线程安全这篇博客内容很好,直接偷过来:
什么是线程安全?如何保证线程安全?-CSDN博客
如何保证线程安全第一种:加锁。
在 Java 中通过添加synchronized关键字实现,对方法或者代码块进行互斥。
第二种:CAS非阻塞同步。
通过不断自旋进行重试,避免线程进入阻塞状态,挂起和唤醒都需要性能开销。
前面两种方式可以参考上面的博客和我写的锁的内容:Java多线程:(三)多线程锁、JUC锁的实现
第三种:ThreadLocal无同步方案。
线程本地存储:将共享数据的可见范围限制在一个线程中。这样无需同步也能保证线程之间不出现数据争用问题。
这种方式我结合后端开发一起介绍。
SpringBoot + ThreadLocal通常,我们会使用 synchronzed 关键字 或者 lock锁 来控制线程对临界区资源的同步顺序,但这种加锁的方式会让未获取到锁的线程进行阻塞,很显然,这种方式的时间效率不会特别高。
线程安全问题的核心在于多个线程会对同一个临界区的共享资源进行访问,那如果每个线程都拥有自己的“共享资源”,各用各的,互不影响,这样就不会出现线程安全的问题了,对吧?
顾名 ...
后端开发未读
分布式事务:Seata微服务下的事务场景在以下场景中,用户支付成功后,订单服务创建业务,同时使用 restTemplate 或者 feign 对其他服务发起远程调用,完成整个业务流程。
照理来说所有业务要么都成功,要么都失败,在没有加上事务管理时,是否能保证事务一致性?
实际上不会。假设在第三个库存服务中,商品库存不够了,那么后端确实会给前端报错信息(报状态码),但是在前面两个服务不会同时失败。也就是说,订单确实创建了,钱也确实少了,但是给不了货儿,明白了吧?此时事务就不是一致的。
在分布式系统中,一个业务跨越了多个服务或数据源,每个事务都是一个分支事务,而整个事务称为全局事务。保证所有分支事务的最终一致性,这样的事务就是分布式事务。
那么,如何保证分布式事务?先从基本的理论开始~
理论基础CAP定理四张图介绍CAP定理。
Base理论在CAP中,P是一定会发生的。想想看,网络故障,或者仅仅是普通的网络波动等其他原因,都有可能会导致集群中的节点不可用。因此满足P的前提下,能产生的模式也就只有两个了,那就是CP模式和AP模式。
无论是AP模式还是CP模式,他俩都在一开始我们提出分布式事务中遇 ...
Java开发未读
Java高级:动态代理、反射动态代理什么是动态代理为了避免代码侵入式的修改,在程序运行时,目标对象不变,对目标对象生成代理对象,代理对象中的方法是目标对象方法的增强方法,最终达到目标对象增强的效果。
Java中动态代理的实现第一种:基于接口实现动态代理
基于接口的动态代理,用到的类是Proxy的newProxyInstance静态方法创建,要求被代理对象至少实现一个接口,如果没有,则不能创建代理对象。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface MyInterface void doSomething(); public class DynamicProxyDemo ...
如何在SpringCloud中使用Nacos面试官提问,怎么在你的服务中使用Nacos?
下载安装&使用
使用window直接在Nacos官网下载就可以了,或者使用docker拉取nacos的镜像,我使用的是windows安装。
安装Nacos后在bin目录下使用cmd,执行命令startup.cmd -m standalone,以单机的模式启动nacos。打开浏览器中默认的账号和密码都是nacos。
springcloud引入依赖
<!-- springCloud --><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>$spring-cloud.version</version> <t ...
. 消息可靠性. 生产者确认机制
. 消息持久化(默认就是持久化,了解代码)
. 消费者消息确认
.. none模式
.. auto模式
. 消费者重试机制.. 本地重试(默认的RejectAndDontRequeueRecoverer策略)基于..的auto模式,发送失败的消息会重新放入队列queue中,导致mq反复处理失败的消息,带来过多的压力。因此通过本地重试的方式,将失败的队列进行retry处理(spring),而不是反复放入队列。
在消费者的application.yml文件中配置启动失败重试开关、以及重复的次数:
.. 三个失败策略(RepublishMessageRecoverer实例)在springAMQP中的失败策略有三个,..中是默认的处理方式。对于废弃的消息,如果不希望消息的丢失,可以采用RepublishMessageRecoverer策略。流程图:
消费者中绑定error交换机后(重写失败策略实现),由交换机根据rountingkey(例子中keyD;error)转发到error.queue ...
同步通信与异步通信feign 无法解决的问题假设有一个场景:
客户端发起请求购买商品,此时使用feign的时候,调用链应该如下
客户端 -> 支付服务 -> 订单服务 -> 支付服务 -> 仓储服务 -> 后续服务 -> 支付服务 -> 客户端
可以看到,这条链还是非常长的,而且引发了以下问题:
代码耦合度非常高:
假设在需要加入新的业务需求,那么就需要在支付服务(见下图)中改代码,来一个新需求加一个,非常麻烦。
再来就是业务之间是一个调用一个的链式调用,如果中途有个服务挂了,那么整个项目也就一起挂了。
同步调用非耗时间:
每当有客户发送支付服务的请求,就需要等待订单服务反馈回支付服务后才能继续发送仓储服务的请求,如此反复的把所有业务跑完,非常耗时间。假设回到支付服务再反馈到客户所需时间需要毫秒,也就等于秒中只能处理两个客户,效率非常低。这种接口等待引发的问题甚至导致资源利用率下降,每个接口都需要等待其他业务响应结束才能执行。
资源浪费:
同步调用的时候,调用链中的每个服务都在等待响应,不能释放请求的资源,高并发的场景下会极度的浪费资 ...
后端开发未读
Redis:(三)缓存设计缓存雪崩通常我们为了保证缓存中的数据与数据库中的数据一致性,会给 Redis 里的数据设置过期时间,当缓存数据过期后,用户访问的数据如果不在缓存里,业务系统需要重新生成缓存,因此就会访问数据库,并将数据更新到 Redis 里,这样后续请求都可以直接命中缓存。
那么,当大量缓存数据在同一时间过期(失效)时,如果此时有大量的用户请求,都无法在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是缓存雪崩的问题。
对于缓存雪崩问题,我们可以采用两种方案解决。
将缓存失效时间随机打散: 我们可以在原有的失效时间基础上增加一个随机值(比如 到 分钟)这样每个缓存的过期时间都不重复了,也就降低了缓存集体失效的概率。
设置缓存不过期: 我们可以通过后台服务来更新缓存数据,从而避免因为缓存失效造成的缓存雪崩,也可以在一定程度上避免缓存并发问题。
缓存击穿我们的业务通常会有几个数据会被频繁地访问,比如秒杀活动,这类被频地访问的数据被称为热点数据。
如果缓存中的某个热点数据过期了,此时大量的请求 ...
Redis集群搭建一个高可用集群有以下内容:主从复制,哨兵模式,切片集群。
主从复制虽然使用 AOF 和 RDB 可以保证持久化,但是如果单点暴毙了,那么两个持久化文件也就没有意义了。
因此,可以通过集群的方式,避免单点暴毙的问题。通过一主多从的集群方式,保证服务的可使用。
主从复制是 Redis 高可用服务的最基础的保证,实现方案就是将从前的一台 Redis 服务器,同步数据到多台从 Redis 服务器上,即一主多从的模式,且主从服务器之间采用的是「读写分离」的方式。
主服务器可以进行读写操作,当发生写操作时自动将写操作同步给从服务器,而从服务器一般是只读,并接受主服务器同步过来写操作命令,然后执行这条命令。
也就是说,所有的数据修改只在主服务器上进行,然后将最新的数据同步给从服务器,这样就使得主从服务器的数据是一致的。
注意,主从服务器之间的命令复制是异步进行的。所以,无法实现强一致性保证(主从数据时时刻刻保持一致),数据不一致是难以避免的。
全量同步:第一次同步
在第一阶段中,如何判断从节点是不是第一次同步?
执行了 replicaof 命令后,图中的.阶段请求数据同步 ...
RedisRedis简介Redis 官方文档:
Redis 是一个开源(BSD 许可)的内存数据结构存储,用作数据库、缓存、消息代理和流引擎。Redis提供数据结构,例如字符串、散列、列表、集合、带范围查询的排序集合、位图、超日志、地理空间索引和流。Redis 内置了复制、Lua 脚本、LRU驱逐、事务和不同级别的磁盘持久性,并通过以下方式提供高可用性 Redis Sentinel 和 Redis Cluster 的自动分区。
使用 Redis 可以对这些类型运行原子操作,例如附加到字符串;增加哈希值;将元素推入列表;计算集交、并、差;或获取排序集中排名最高的成员。为了达到最佳性能,Redis 使用内存中的数据集。根据您的用例,Redis 可以通过定期将数据集转储到磁盘或将每个命令附加到基于磁盘的日志来持久化您的数据。如果您只需要一个功能丰富的网络内存缓存,您也可以禁用持久性。
Redis支持异步复制,具有快速非阻塞同步和自动重新连接以及网络拆分上的部分重新同步。
Redis还包括:
交易
发布;订阅
Lua脚本
生命周期有限的密钥
LRU驱逐密钥
自动故障转移
Redi ...
为什么要进行分库分表
来解释一下IO瓶颈:
在介绍innodb存储引擎MySQL:(二)存储引擎 | 颓废市民黄先生 (rengoku.top)的时候,曾经说过,内存架构中大部分的组件都分配给了缓存。如果内存不足,缓存就不够,那么就要使用后台线程和磁盘进行io,这样效率就会低
拆分策略
垂直拆分
垂直分表:局限于单个数据库内部,不涉及跨数据库操作。
垂直分库:跨越多个数据库,甚至可能跨越不同的服务器,涉及跨数据库的数据访问和管理。
水平拆分和垂直拆分一样,水平分库会涉及跨数据库,而水平分表不跨数据库。
MyCatmycat详细介绍及实战-CSDN博客
mycat实现分库分表,读写分离。