Zeros Tech Zeros Tech
首页
架构
大数据
数据库
  • 面试

    • Java面试
    • 大数据面试
    • 架构面试
语言
运维
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

迹_Jason

全栈工程师
首页
架构
大数据
数据库
  • 面试

    • Java面试
    • 大数据面试
    • 架构面试
语言
运维
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 面试

    • 架构面试

      • 一致性Hash原理
      • 分布式面试
      • 公共问题
      • 大数据面试

      • Java

    • 技术
    • 面试
    • 架构面试
    迹_Jason
    2021-02-08

    公共问题

    # 公共问题

    # 如何实现负载均衡,有哪些算法可以实现?

    经常会用到以下四种算法:随机(random)、轮询(round-robin)、一致哈希(consistent-hash)和主备(master-slave)。

    # Spring Cloud 与 Dubbo 的对比?

    • 对于国外,Spring Cloud 基本已经统一国外的微服务体系。
    • 对于国内,老的系统使用 Dubbo 较多,新的系统使用 Spring Cloud 较多。

    Spring Cloud 与 Dubbo 两者其实并不冲突,目前,Dubbo 也积极的 Spring Boot 化,Dubbo 可以作为 Spring Cloud 体系的一个补充。

    如果从各自生态圈进行比较的话,

    Nacos 注册中心 + 配置中心,对标 Eureka 。并且,还对标了 Spring Cloud Config 。

    Sentinel 服务保障,对标 Hystrix 。

    Dubbo 服务调用( 包括负载均衡 ),对标 Ribbon + Feign 。

    缺失 网关服务。

    分布式锁三种实现方式:

    1. 基于数据库实现分布式锁;

    2. 基于缓存(Redis等)实现分布式锁;

    3. 基于Zookeeper实现分布式锁

    数据库实现

    1. 悲观锁

    利用select … where … for update 排他锁

    注意: 其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,name字段必须要走索引,否则会锁表。有些情况下,比如表不大,mysql优化器会不走这个索引,导致锁表问题。

    1. 乐观锁

    所谓乐观锁与前边最大区别在于基于CAS思想,是不具有互斥性,不会产生锁等待而消耗资源,操作过程中认为不存在并发冲突,只有update version失败后才能觉察到。我们的抢购、秒杀就是用了这种实现以防止超卖。

    通过增加递增的版本号字段实现乐观锁

    基于缓存(Redis等)实现分布式锁

    (1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。

    (2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。

    (3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

    基于Zookeeper实现分布式锁

    (1)创建一个目录mylock; (2)线程A想获取锁就在mylock目录下创建临时顺序节点; (3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁; (4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点; (5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

    这里推荐一个Apache的开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。

    优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。

    缺点:因为需要频繁的创建和删除节点,性能上不如Redis方式。

    对比

    数据库分布式锁实现

    缺点:

    1.db操作性能较差,并且有锁表的风险

    2.非阻塞操作失败后,需要轮询,占用cpu资源;

    3.长时间不commit或者长时间轮询,可能会占用较多连接资源

    Redis(缓存)分布式锁实现

    缺点:

    1.锁删除失败 过期时间不好控制

    2.非阻塞,操作失败后,需要轮询,占用cpu资源;

    ZK分布式锁实现

    缺点:性能不如redis实现,主要原因是写操作(获取锁释放锁)都需要在Leader上执行,然后同步到follower。

    总之:ZooKeeper有较好的性能和可靠性。

    从理解的难易程度角度(从低到高)数据库 > 缓存 > Zookeeper

    从实现的复杂性角度(从低到高)Zookeeper >= 缓存 > 数据库

    从性能角度(从高到低)缓存 > Zookeeper >= 数据库

    从可靠性角度(从高到低)Zookeeper > 缓存 > 数据库

    # ZK 如何保证数据的一致性呢?

    ZAB协议是为zookeeper专门设计的一种支持奔溃恢复的原子广播协议。虽然它不像Paxos算法那样通用,但是它却比Paxos算法易于理解。在我看来ZAB协议主要的作用在于三个方面 1、选举出leader;2、同步节点之间的状态达到数据一致;3、数据的广播。

    # 选举leader

    每个follower广播自己事务队列中最大事务编号maxId 获取集群中其他follower发出来的maxId,选取出最大的maxId所属的follower,投票给改follower,选它为leader。 统计所有投票,获取投票数超过一半的follower被推选为leader

    # 同步数据

    各个follower向leader发送自己保存的任期E leader,比较所有的任期,选取最大的E,加1后作为当前的任期E=E+1 将任务E广播给所有follower follower将任期改为leader发过来的值,并且返回给leader事务队列L leader从队列集合中选取任期最大的队列,如果有多个队列任期都是最大,则选取事务编号n最大的队列Lmax。将Lmax最为leader队列,并且广播给各个follower。 follower接收队列替换自己的事务队列,并且执行提交队列中的事务。 至此各个节点的数据达成一致,zookeeper恢复正常服务。

    # 广播

    leader节点接收到请求,将事务加入事务队列,并且将事务广播给各个follower。 follower接收事务并加入都事务队列,然后给leader发送准备提交请求。 leader 接收到半数以上的准备提交请求后,提交事务同时向follower 发送提交事务请求 follower提交事务。

    # 二阶段(2PC)事务提交流程?

    • 第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.
    • 第二阶段:事务协调器要求每个数据库提交数据。

    如果有任何一个数据库否决此次提交,那么所有数据库都会被要求回滚它们在此事务中的那部分信息。

    优点: 尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。(其实也不能100%保证强一致)

    缺点: 实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景,如果分布式系统跨接口调用。

    # 补偿事务(TCC)

    • Try 阶段主要是对业务系统做检测及资源预留
    • Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
    • Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

    举个例子,假入 Bob 要向 Smith 转账,思路大概是: 我们有一个本地方法,里面依次调用 1、首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。 2、在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。 3、如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

    优点: 跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些

    缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。

    # MQ 事务消息

    有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交。

    第一阶段Prepared消息,会拿到消息的地址。

    第二阶段执行本地事务。

    第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。

    优点: 实现了最终一致性,不需要依赖本地数据库事务。

    缺点: 实现难度大,主流MQ不支持,RocketMQ事务消息部分代码也未开源。

    # Sagas 事务模型

    该模型其核心思想就是拆分分布式系统中的长事务为多个短事务,或者叫多个本地事务,然后由 Sagas 工作流引擎负责协调,如果整个流程正常结束,那么就算是业务成功完成,如果在这过程中实现失败,那么Sagas工作流引擎就会以相反的顺序调用补偿操作,重新进行业务回滚。

    https://blog.51cto.com/14230003/2460070

    # TCC和2PC比较

    2PC是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。

    XA事务中的两阶段提交内部过程是对开发者屏蔽的,事务管理器在两阶段提交过程中,从prepare到commit/rollback过程中,资源实际上一直都是被加锁的。

    如果有其他人需要更新这两条记录,那么就必须等待锁释放。

    TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

    TCC中的两阶段提交并没有对开发者完全屏蔽,也就是说从代码层面,开发者是可以感受到两阶段提交的存在。

    1、try过程的本地事务,是保证资源预留的业务逻辑的正确性。

    2、confirm/cancel执行的本地事务逻辑确认/取消预留资源,以保证最终一致性,也就是所谓的补偿型事务。

    由于是多个独立的本地事务,因此不会对资源一直加锁。

    https://blog.51cto.com/14230003/2460070

    # 小结

    如无法合并则优先考虑TCC或基于MQ的柔性事务,尽可能规避2PC等对性能影响很大的事务方案。TCC可完全替换2PC,但开发成本偏高,需要调用各方都同步修改以支持Try、Confirm和Cancel操作,某些场景会调用三方服务,其代码不受我们控制,此时可以考虑使用MQ实现异步消息和补偿性事务。

    # 分布式ID有哪些实现方案?

    • UUID
    • 数据库自增ID
    • 数据库多主模式
    • 号段模式
    • Redis
    • 雪花算法(SnowFlake)
    • 滴滴出品(TinyID)
    • 百度 (Uidgenerator)
    • 美团(Leaf):号段模式和snowflake

    # 什么叫 Hash算法?

    一类把任意数据转换为定长(或限制长度)数据的算法统称。

    # Hash 算法应用场景?

    作为一些大文件或者大数据量集合的一个身份凭证,也就是说看到这个hash值就知道说的就是这个大文件。

    例如我们在一些网站下载大文件的时候,网站提供给我们验证文件完整性的 MD5 或者 SHA1 码,就是原文件的哈希值。哈希算法有很多种,MD5 是其中的一种,这就是 MD5。

    # MD5 特点?

    MD5 就是心虚摘要的一种实现,它可以从任意长度的明文字符串生成128位的哈希值。

    • 只是一种hash算法
    • 相比一般的hash算法更加均衡
    • 存在碰撞概率,因而存在重复可能性

    # MD5 相比加密算法的优势是什么?

    • 值是定长的,节省存储空间
    • 不可逆,得出的结果,不可被反向推导
    • 计算容易,不需要太多性能消耗

    # MD5 生成过程?

    摘要哈希生成的正确姿势是什么样呢?分三步:

    1.收集相关业务参数,在这里是金额和目标账户。当然,实际应用中的参数肯定比这多得多,这里只是做了简化。

    2.按照规则,把参数名和参数值拼接成一个字符串,同时把给定的密钥也拼接起来。之所以需要密钥,是因为攻击者也可能获知拼接规则。

    3.利用MD5算法,从原文生成哈希值。MD5生成的哈希值是128位的二进制数,也就是32位的十六进制数。

    # MD5 为什么是不安全的?

    暴力枚举法:简单粗暴地枚举出所有原文,并计算出它们的哈希值,看看哪个哈希值和给定的信息摘要一致。

    字典法:黑客利用一个巨大的字典,存储尽可能多的原文和对应的哈希值。每次用给定的信息摘要查找字典,即可快速找到碰撞的结果。

    彩虹表(rainbow)法:在字典法的基础上改进,以时间换空间。是现在破解哈希常用的办法。

    推荐使用 Bcrypt 加密数据

    编辑 (opens new window)
    分布式面试
    HBase 面试题

    ← 分布式面试 HBase 面试题→

    最近更新
    01
    一致性Hash原理
    02-08
    02
    分布式面试
    02-08
    03
    HBase 面试题
    02-08
    更多文章>
    Theme by Vdoing | Copyright © 2021-2021 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×