栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

分布式相关知识点

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分布式相关知识点

分布式锁在项目中有哪些应用场景

1、系统是一个分布式系统,golang的锁已经锁不住了;
2、需要操作共享资源,比如库里唯一的用户数据;
3、同步访问,即多个进程同时操作共享资源;

分布式锁有哪些解决方案

1、Redis分布式锁。使用setnx key value,这种方法如果不在使用完后delete删除锁,则会产生死锁;因此需要同时设置过期时间,作为一个原子性操作;但如果这次操作的耗时超过了过期时间,则其他操作现在能拿到这个数据了,此时需要用watch dog来刷新过期时间。
2、基于Zookeeper,设置临时顺序节点。
3、基于数据库,比如MySQL,使用主键或唯一索引的唯一性。

ZooKeeper和Redis做分布式锁的区别

Redis只保证最终一致性,副本间的数据复制是异步的,所以主从切换会有数据丢失从而丢失锁的情况,但Redis集群响应的时间很低,保证AP,但不可靠,相对不稳定。
ZooKeeper锁原理是使用临时顺序节点,该节点的生命周期在Client与集群的Session结束时结束,有较好的稳定性,每次进行锁操作前要创建若干节点,完成后释放,会浪费时间,保证CP。

MySQL如何做分布式锁

在MySQL中创建一个表,设置一个主键或者唯一索引,这个ID/唯一索引就是一把分布式锁,这个KEY就是要锁的KEY,这样同一个KEY只能在mysql中插入一次了,对锁的竞争就交给了数据库。其他想要进行插入数据的并发请求必须等当前请求执行完毕后删除该KEY才能继续插入。

计数器算法

在指定时间周期内累加访问次数,达到设定的阈值时,触发限流策略。下一个时间周期进行访问时,访问次数清零。但如果在两个周期的交界处,左右两边的请求加起来超过了阈值,即超过了系统的最大承载能力。

滑动时间窗口算法

为解决计算器算法的临界值问题,发明了滑动窗口算法。实际上将计数器算法中的周期划分成多个小的时间窗口,根据时间将窗口向前滑动的同时删除过期的小时间窗口,这样只需要统计滑动窗口之间的总请求数即可。小窗口划分的越多,窗口滑动越平滑,限流的统计越精确。

漏桶限流算法

维持一个漏斗,消息的生产者往里面输入,漏斗以恒定的速度流出给消费者处理,类似于消息中间件,消息处理能力取决于消费者。
漏桶的容量 = 漏桶流出的速度 * 可接受的等待时长。这个容量范围内的请求可以排队等待,超出则抛弃。
当请求速度大于漏桶流出的速度时,触发限流策略。
系统在短时间内有突发的大流量时,漏桶算法处理不了。

令牌桶限流算法

增加一个大小固定的容器,系统以恒定的速度向桶中放令牌,客户端来请求必须先取一个令牌才能访问系统,此时桶中令牌减一。令牌桶满时,生成的令牌被抛弃。令牌被取完,此时后续的请求被限流。
由于桶内有一定数量的令牌,则可以处理短时间大流量的场景。

设计微服务的原则

1、单一职责原则:每个服务能独立工作,只关注自己的业务,做到高内聚。
2、服务自治原则:每个服务能独立开发、测试、构建、部署、运行,与其他服务解耦。
3、轻量级通信原则:让每个服务之间的调用是轻量级的,能够跨平台、跨语言。
4、粒度进化原则:对每个服务不要过度设计,随着业务的发展而发展。
软件是为业务服务的,好的系统部署设计出来的,而是进化出来的。

2PC提交协议

为保证分布式事务的一致性而设计的一种算法或者说协议。分布式系统中,每个节点可以知道自己的操作是否成功,但不知道其他节点的操作是否成功,因此引入一个协调者组件来掌控所有节点的状态,并最终指示这些节点是否要真正提交操作结果。
准备阶段:
协调者向节点发送准备消息,节点接受后要么直接返回失败(权限验证失败),要么在本地执行事务,写本地的redo和undo日志,但不提交,向协调者发送自己的状态。
提交阶段:
如果协调者收到任意失败或超时消息,直接给每个参与者发送回滚消息;否则发送提交消息。
节点按消息执行对应的操作,并在最后阶段释放锁资源。
问题:
1、同步堵塞问题。执行过程中,其他第三方节点来访问这些参与节点的资源都处于堵塞状态。
2、单点故障问题。准备前挂了,还行。准备后挂了,一阶段执行成功的那些节点都堵塞。回滚后、提交后挂了,还行,大概率能执行成功,除非某些参与者因为网络问题收不到命令而堵塞。
提交前挂了,所有的节点都堵塞,回滚前挂了,执行成功的节点都堵塞。
3、数据不一致。第二阶段当协调者发出commit请求后,如果参与者因为网络问题收不到请求,这部分的参与者就无法执行事务提交,整个分布式系统出现数据不一致。
4、二阶段协调者与节点都宕机后选出的新协调者也不知道宕机节点的事务是否已经提交。(处理方法:补偿(服务1:0->1;服务2:a->b,则正确的状态只可能是0a或者1b))

2PC 是一种尽量保证强一致性的分布式事务,因此它是同步阻塞的,而同步阻塞就导致长久的资源锁定问题,总体而言效率低,并且存在单点故障问题,在极端条件下存在数据不一致的风险。

2pc与3pc

3pc 就是通过引入预提交阶段来使得参与者之间的状态得到统一,性能会差一些。在这个阶段不占用资源,只是校验一下sql,如果不能执行,则返回,不像2pc一样上来先把能操作的资源给锁了。

引入参与者超时机制:
参与者超时,则pre阶段执行中断,do阶段进行提交。

超时机制也会带来数据不一致的问题,比如在等待提交命令时候超时了,参与者默认执行的是提交事务操作,但是有可能执行的是回滚操作,这样一来数据就不一致了。

2PC 和 3PC 都不能保证数据100%一致,因此一般都需要有定时扫描补偿机制。

基于业务层面的、事务补偿机制的TCC

TCC 指的是Try - Confirm - Cancel。
Try 指的是预留,即资源的预留和锁定,注意是预留,预执行。
Confirm 指的是确认操作,这一步其实就是真正的执行了。
Cancel 指的是撤销操作,可以理解为把预留阶段的动作撤销了。
因此 TCC 对业务的侵入较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作。

撤销和确认操作的执行可能需要重试(撤销和确认时超时),因此还需要保证操作的幂等。

相对于 2PC、3PC ,TCC 适用的范围更大,但是开发量也更大,为每个操作都要注册对应的确认和撤销操作。不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务。

TCC空回滚

Try请求由于网络延迟或者故障没有执行,如果Cancel进行了对数据的修改,则导致数据不一致。
解决思路:识别出这个空回滚。
在发起全局事务时生成全局事务ID,额外增加一个分支事务记录表,其中有全局事务ID和分支事务ID,Try方法会插入一条记录表示执行了,Cancel接口如果能读到这条数据,则正常回滚;不存在则空回滚。

TCC幂等

因为网络抖动等原因,分布式事务框架可能会重复调用同一个分布式事务中的一个分支事务的二阶段接口。所以分支事务的二阶段接口/confirm/i/Cancel需要能够保证幂等性否则会有数据不一致等严重问题。
解决方法:
在分支事务表中,添加一个事务状态字段,有INIT、/confirm/iED、ROLLBACKED三个状态,Try方法执行成功时,插入一个此幂等记录,初始化为INIT,二阶段的/confirm/i/Cancel执行时会将其状态置为/confirm/iED/ROLLBACKED。重复调用二阶段接口时,参与者先判断状态是否为/confirm/iED/ROLLBACKED,此时代表参与者已经处理过了,不需要再次执行。

TCC悬挂

调用分支事务Try时,发生网络拥堵,TM(事务管理器/协调者)通知RM(资源管理器/参与者)执行回滚,可能Cancel执行完成后,Try才到达参与者真正的执行,此时Try预留的业务资源再也没人能处理了。
解决方法:
为在判断为空回滚的场景下(体现在对应一阶段事务控制记录不存在),插入一条状态为ROLLBACKED的控制记录,当堵塞后的Try到达时首先会尝试插入状态为INIT的事务控制记录。如果插入失败,表示当前分支事务的记录已经存在,Try无需继续执行。

可靠消息服务方案

可靠消息的最终一致性是指:当事务的发起方执行完本地事务后,同时发出一条消息,事务的参与方一定能够接收消息并成功处理自己的事务。
关键点:
1、可靠消息,发起方一定得把消息传递到消费者。(通过RocketMQ在消息丢失时回查事务状态)
2、最终一致性:最终发起方的业务处理和消费方的业务处理都得完成,达成最终一致。

最大努力通知方案

1、有一定的消息重复通知机制。因为接收通知方可能没有接收到通知,需要有对消息的重复通知。
2、消息校对机制。如果尽最大努力也没通知到接收方,或者接收方消费后再次消费,此时可由接收方主动向通知方查询消息来满足需求。

幂等

幂等操作/流程的特点:任意次数的执行得到的结果与执行一次的效果相同。
解决方案:
唯一索引:防止新增脏数据。当前唯一索引存在时,再执行新增操作,只会直接返回结果,不会再次新增数据。
token机制:防止页面重复提交。每次请求来访问服务器都要带一个token,如果请求重复提交,则后面进来的请求拿不到token,则无法访问服务器。
traceid:为每一个操作都添加一个唯一的ID到redis中,来一个请求时如果后端判断到当前traceid已经有了,则拒绝掉该次请求。

对外提供的API如何保证幂等

API需要每次第三方调用访问时携带一个能唯一确定身份的带序列号的字段,将该字段在数据库中做唯一索引。第三方调用访问时,先在数据库中查询,如果已经处理过,则直接返回处理结果;否则先处理,再返回结果。

如何保证数据库缓存数据一致性

给缓存设置过期时间是保证最终一致性的解决方案。因为即使缓存更新失败,那么等到过期了,会从数据库读到新的数据写到缓存中。
不依赖设置缓存过期时间的方法有:
1、先更新数据库,再更新缓存。当线程A更新了数据库,在线程A更新缓存之前,线程B又更新了数据库,同时更新了缓存,等到A更新缓存时就产生了脏数据。因为缓存中的数据不会被频繁读取,如果数据库更新的很频繁,那么缓存的频繁更新就是不必要的,浪费性能,所以选择懒加载的删除缓存方式。
2、先删除缓存,再更新数据库。在删除缓存后,更新数据库完成前,有其他线程来读缓存,则会把数据库中的旧数据读到缓存中,且一直是旧数据。
3、先更新数据库,再删除缓存。这样虽然在更新过程中是读到的旧数据,但总会更新为新数据。
4、延时双删。虽然也不能保证更新过程中数据的一致性,但读到脏数据的概率更低,但因为有延时的存在,写操作频繁的时候,影响性能。
5、将访问操作序列化。先删缓存,然后将更新数据库的操作放到有序队列中,缓存中查不到的数据的读操作也放进有序队列中。这样能保证数据一致性,但会有读请求挤压,导致大量超时、熔断,可以将队列水平拆分,提高并发度。

认证与授权

认证是系统验证客户身份的凭证,确认客户是否存在于系统中。
授权是认证之后,确定客户能访问系统的权限,因为系统的某些资源是某些客户特有的。
两者结合起来保护系统的安全性。

cookie与session有什么区别,如何用session进行身份验证

两者都是服务器会话技术,cookie是浏览器访问服务器后,服务器回传的一段数据,存储在浏览器上;session则是存储在服务器上一个session对象,安全性更高,没有大小、类型限制。
用户访问服务器后,服务器返回客户端具有sessionid的cookie,当用户向后端发起请求时,会把sessionid带上,这样服务器就知道用户的身份状态了。
要注意依赖session的关键业务要确保客户端开启了cookie;注意session的过期时间。

什么是token,什么是jwt,如何基于token进行身份验证

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌。
当第一次用用户名和密码登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需在请求的Header中带上这个Token前来请求数据,服务器即可获取用户信息,无需再次带上用户名和密码。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。
JWT(JSON WEB TOKEN)就是JSON格式的Token。

为什么token能防止CSRF(跨站请求伪造)

Token被用户端放在cookie中(不设置HttpOnly),同源页面每次发请求都在请求头或者参数中加入cookie中读取的Token来完成验证。CSRF只能通过浏览器自己带上cookie,不能操作cookie来获取到Token并加到http请求的参数中。

session的分布式方案

1、采用无状态服务,直接抛弃session
2、将session存入cookie,但是有安全风险,且cookie能携带信息变少。
3、实现IP绑定策略。根据cookie信息将同一个用户的请求每次都分发到同一台服务器上,但这样失去了负载均衡的意义,且一个服务器宕机,会让一大片用户无法处理相应业务。
4、session同步。保证每个服务器上都有全部的session,但数量变多时,session复制占用大量网络资源,且存在数据延时。
5、用redis存储。虽然多了一次对redis的访问,且架构变复杂,但能水平扩展,实现session共享,重启后session不丢失,可跨服务器甚至跨平台session共享。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/270570.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号