分布式ID/锁/事务


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、分布式ID

1.特性

全局唯一+局部唯一+按情况递增

2.最佳实现方案

缓存+细粒度的锁化+无锁

3.UUID全剧唯一

问:为什么不用uuID?
答:没有递增特性,插入到innoDB,查找时会对数据库造成巨大压力,不能作为物理主键,只能作为逻辑主键,物理主键依然使用自增id

4.redis雪花算法

redis雪花算法生成分布式id性能很好,使用多组master-slave集群
存在问题:master-slave是异步消息,可能会存在数据的丢失
如果业务可以容忍这种情况,那就可以使用,如果不呢容忍可以将redis源码增加同步消息
可以配合zk实现基本满足cap

二、分布式事务

1. 2PC

针对mysql一种数据库
第一阶段:投票阶段(执行本地事务,不提交)
第二阶段:执行/执行阶段(收到消息通知各服务提交/回滚)

缺点:
1、依赖于事务协调者,如果协调者出现故障,那么事务会失效回滚
2、阻塞数据库资源(两阶段执行完毕才会释放资源,中途过程一直是阻塞的)
3、数据不一致 :第二阶段当协调者发送消息“你们可以提交了”,A 服务commit成功了,但B由于未知原因始终没有
   提交

2. 3PC(实际也是2个阶段)

1.can commit:评估能不能做(先不占用数据库资源),即sql检查
2.pre commit:执行数据库操作(不进行事务提交)
3.do commit:前两阶段执行成功后,当没收到协调的指令“你们提交吧”时,各个服务会认为我大概率成功了,也会自动提交事务。

3. TCC

针对于多种数据库,如同时操作mysql与redis
实际也是两个阶段:
1、try:同时操作redis与mysql操作完并直接提交,释放数据库资源
生产方与消费方引入冻结字段
2、
a.comfirm:提交。清空冻结字段
b.cancel:有一放失败后,会回滚操作。第三方会有一个逆操作,如:原来更改某个字段+1成功,回滚时此字段-1

优点:几乎不占用数据库连接,不是通过数据库日志实现,是通过业务实现。2PC/3PC是通过binlog实现
弊端:代码实现比较复杂,回滚操作需要手动代码实现

4. Seata:性能还可以

第一阶段:执行sql并提交,并且需要在数据库新建一张undolog表,记录数据是从a->b的过程
第二阶段:如果执行成功,那么就删除undolog表数据a->b这些记录,如果执行失败,那么根据此数据进行回滚,从b->a

5. 消息队列+本地事务+定时任务

base理论,最终一致性,通过消息队列进行事务补偿。
只能全部成功:执行一部分事务,并给用户返回成功,后面的事务必须执行成功,如果不成功那么消息中间件会多次重复发送此任务。
如果若干次数不成功,就会进入死信队列,并进行单独处理。一个应用或定时任务监控死信队列,通知人工处理

原理如下:
在这里插入图片描述

6.RocketMQ:最终一致性

6.1 原理图

在这里插入图片描述

6.1 流程

1、生产者发送HalfMessage消息给broker,消息中是消费者要消费的内容
2、生产者发送消息成功并且broker响应成功后,生产者执行本地事务
3、执行本地事务(会有3种情况1.成功 2. 失败 3.超时或无响应)
4.1、如果本地事务成功,那么生产者向borker发送commit,broker会将半消息改为可用消息
4.2、如果本地事务失败,那么生产者向broker发送rollback,broker会删掉半消息
4.3、如果因为网络原因生产者迟迟没有给broker发送最终消息,那么broker会执行回调,来检查事务是否完成

7.最大努力通知方案

原理图:
在这里插入图片描述
最大努力通知方案需要具备:
1.重复通知机制(直到success)
2.消息校对机制(服务方调用支付宝接口,查看钱是否已经到账)

三、分布式锁

问:在分布式锁的情况下可以保证多机、多进程、多线程访问资源的一致性,这个时候还需要JVM锁吗?
需要。jvm内部使用了锁,会对控制此进程中一个线程去竞争分布式锁,过滤掉了一部分请求,减轻了分布式锁服务的压力,也减少了更少的IO请求。
【分而治之】的思想

两大类分布式锁:

1.mysql与redis

类似cas自旋式分布式锁,自己询问的锁提供方的方式,自己尝试加锁。在分布式环境下次方式性能低,会有io操作,给锁提供方压力会更大

redis:通过发布订阅+redis的阻塞队列+合理设置询问时间来减少网络当中IO的复杂度。代码复杂度上升
如当前事务执行时间超过了,redis锁的过期时间,此时要一个线程来管理,进行续租,延期redis锁过期时间

redis集群相关:
主从复制集群:解决redis单点故障的问题,数据同步问题,节点间数据是全量的,所有机器都是一样的数据,哨兵机制是分布式情况下的一种监控手段,偏自动化运维
cluster集群:分治,分片的思想解决的是容量,压力,瓶颈问题

redis的红锁redlock算法是由客户端实现,并不是redis服务端实现。客户端A抢到N/2 +1 个redis锁,那么A就获得了锁(过半机制)
红锁存在问题:节点挂了的时候,重启后又可能出现多个线程抢到同一把锁,那么可以对挂掉的redis服务延迟启动。

继续仍有问题存在:高并发情况仍会又问题,如3个master实例,被3个线程同时抢到,1抢到A锁,2抢到B,3线程抢到C号master的锁,这时会导致3个线程都强锁失败
如何解决?
待续

2.zk与etcd

event事件通知我后续锁的变化,轮询向外的过程

分布式中此CAS自旋,与jvm中cas自旋有着本质上的区别。jvm cas自旋基于cpu指令,无需IO操作。
所以第一类锁,更加耗系统性能

ZK:组从复制通过两阶段提交,先写日志,再提交
ZK的leader选举:实际是推让制度,所有从节点通过zxid(事务id)、serverid,谁数据(zxid)最新,那么就推选谁,其次再是serverid最大选举谁。

为什么ZK能支持分布式这么多东西?
分布式协调、分布式锁、分布式ID、分布式配置、分布式注册与发现、分布式HA

答:是因为有session,和watch机制(监控回调,监控zk节点的事件,如删除,修改节点等后随即触发;如分布式锁时,做下一轮抢锁。由客户端编写和执行,解决了cas轮询耗费资源的问题),存储数据是path和node方式(持久节点,临时节点,其中临时节点与sesson绑定,session在临时节点就还在)
session数据会通过leader同步到所有follower节点,leader挂了,选取新的leader并且会持有之前这个session数据,下次访问时依然可以正常访问。
全局分布式ID:由节点自主递增

四、分布式缓存

1.一致性hash算法:

1.1作用:

解决分布式缓存在动态增加/删除节点时各个redis数据迁移的问题,在新增1个节点时,只有一个redis实例的数据迁移到新增redis节点上,数据的迁移更为平滑,不会造成大规模redis节点的数据迁移。

1.2 实现方式:

通过redis集群的ip与编号对2^32次方进行hash
数据通过key也进行2^32次方进行hash

1.3实现原理图

在这里插入图片描述

1.4存在问题:

数据倾斜问题
存储框架:大部分的数据存储在少量服务器节点上。数据分布不均匀
计算框架:大部分的数据是由少量的服务进行计算
如何解决数据倾斜:在映射到hash环时,将每个redis节点虚拟成多个redis节点hash到hash环上,虚拟节点越多,数据存储约均匀。实际数据迁移时实质还是实际节点间的数据迁移

2.缓存穿透:

黑客携带无效id=-1请求服务器,请求没有命中缓存,直接会请求到mysql
个别缓存穿透的请求并不可怕,可怕的是大量的缓存穿透可使数据库宕机

解决方案:
2.1.第一次id=-1的请求 mysql处理后,将key=-1,value=null的数据直接存入redis,下次还是id=-1的请求就直接走缓存了。
存在问题:如果id=uuid那么此方案失效了

2.2 为了解决id=uuid的无效请求,在缓存与mysql之间可以采用过滤器来存储所有数据库中存在的id。如果过滤器中有id=uuid,那么就去数据库中查询,如果没有就直接返回。
存在问题:如果改数据量巨大,则过滤器会浪费大量的存储空间

2.3 布隆算法(布隆过滤器):通过极小的错误率来换取空间的占用:
在这里插入图片描述
布隆过滤器错误率原因:hash碰撞过于高,碰撞越高错误率就越高;
1.可以增加布隆过滤器的位数组长度来降低错误率
2.可以用多个hash函数来同时hash将key映射到bit数组上,有多个位是1,此时另一个key请求时,同时也走这多个hash函数,得到的结果在bit位上找是否都为1,如果都为1,那么即存在,反之不存在。

面试题:2个文件中有100亿个url,最高效率找出这两个文件的交集,分别给出精准算法与模糊算法?
1.精准:将文件读取,url根据hash求余,拆分成多个小文件。拆分后对比1-1,2-2的小文件是否内容一样。
过程需要2次IO
2.模糊:布隆算法,读取A文件url每一行,传给hash函数并记录到数组arr,拿B文件每一行也进行hash后去arr对比看是否有没有
过程需要一次IO,效率也高,也省内存

3.缓存击穿:

3.1概念:

一般是缓存中数据过期,由于并发量大,同时没有读取到缓存数据,直接请求数据库,导致数据库压力瞬间增大。
特点:指某一缓存过期

3.2解决方案:

1.设置热点数据永不过期 异步更新
2.加互斥锁或队列

4.缓存雪崩:

4.1.概念:

缓存中大批数据过期,查询数据量巨大,引起数据库压力过大甚至down机。
特点:指多种缓存数据过期

4.2解决方案:

1.缓存数据过期时间随机设置,防止同一时间大批数据过期
2. 设置热点数据永不过期,异步更新
3.使用jvm锁+分布式锁控制流量(针对热点高并发数据)
4.使用双缓存
主缓存正常:主缓存失效后从数据库中读取
备缓存:长期有效,获取锁失败时读取的缓存,主缓存更新时同步更新备缓存

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值