分布式系统
使用分布式系统主要是提高系统稳定性、加强处理能力,实现高可用和容错能力。
分布式:将一个业务拆封成多个业务,部署在多个服务器上。
集群:将同一个业务部署在多个服务器上。
1.分布式ID
-
分类
1.依赖DB类型:依赖数据库进行设置,通过设置初始值和步长实现稳定增长。
2.类似snowflake型:是将定义64位划分不同区域,有占位符,时间戳,机器码,自增序列。
-
snowflake
使用推特的分布式ID算法生成,将64位组成,不同位置含义不同。
占位符:第一个位置为0,可以看做为符号位不使用。
时间戳:由2-42位,是41bit由毫秒级别的时间戳生成.
机器码:中间43-52为,只占10bit。
自增序列:最后12位bit自增序列。
- DB类型
1.mysql
主要是将分布式业务中mysql业务表中分布式ID设置为不同初始值,然后设置业务步长,这个步长就是分库或分表的数量。
mysql 中设置字段 auto_increment_increment和 auto_increment_offset包装id自增。
auto_increment_offset:设置自增字段的数量从那数值开始自增,范围1-65535。
auto_increment_increment:设置自增字段每次增长的量是多少,默认1,范围1-65535。
主要这个是强依赖DB数据库,所以对于数据库服务器要保持高可用,当数据库主从切换之后可能产生id重复。
2.redis
对于redis 通过设置incr和byincr原子命令实现分布式ID,由于redis是单线程所以实现的ID是唯一有序ID。
但是单机的redis的自身的瓶颈限制,无法满足高并发的业务需求,在实现的过程中就引入redis集群,在集群中通过步长和初始值的设置来实现分布式ID。
在实现过过程避免自增数据过大使用时间戳组合使用,这样也保证数据的有序性,即redis分布式ID,它性能比较高,有序,对排序业务有利。
2.分布式锁
类型: 1. redis 2.mysql
1.redis
1).set NX+重试 +重试间隔
这个主要是通过 key+value 将key 设置为数据分布式ID 进行查询如果查询到,则认为已经加锁,否则 没有加锁当前线程可以获取锁。
2).redLock
这个是指当前服务a和服务b 在获取锁的时候,在多个节点下,需要在节点中在建立锁的时候必须要 n/2+1的节点,而且在建立锁并且这个获取锁的时间必须小于设置时间,才能认为当前服务a获取锁成功。
3).redssion
线程获取锁,如果获取成功执行代码,保存数据到redis。
线程获取锁,获取失败,则订阅释放解锁消息,重试,重新获取锁,如果获取成功,则实现代码,保存数据到redis。
4).看门狗机制
当前线程获取锁,时间30秒,后台线程会不断的去询问客户端是否还在持有当锁,如果还在持有,则会再次分配给当前线程10秒时间,一直循环执行,知道业务执行完。
2.mysql
一个是乐观锁:它就是假设俩个锁在相互获取锁的时候不会发生冲突,如果冲突则释放重试,直到成功为止,它主要是多版本控制原理进行加锁。
一个是悲观锁:
表级锁:更新数据不是以主键作为条件,进行表级锁。
行级锁:更新数据以主键作为条件,进行的事表级锁。
3.分布式事务
类型:俩段式提交,三段式提交。
分布式事务中通过 协调者 和 参与者 进行控制处理事务。
1.俩段式提交
准备阶段:当客户端将请求发送过来,通过协调者转发到参与者进行执行,当参与者执行完毕,回复是否成功的消息,这里执行业务代码,但是不提交事务。
提交阶段:当准备阶段的参与者都返回成功,这个就会进行事务提交执行。否则返回失败或者任务超时消息就会进行中断事务,资源回滚。
2.三段式提交
canCommit阶段;也是通过协调者将canCimit请求发送到参与者,如果执行完毕消息响应成功,则进入下一个阶段;
preCommit阶段:通过协调者发送preCommit请求到参与者,如果执行完毕消息响应成功,则进入下一个阶段,否则会中断事务,将占有的资源进行回滚。
doCommit阶段:当前俩个阶段都返回成功的消息,进行协调这给参与者发送doCommit消息,执行业务代码成功进行事务提交,否则协调者没有接受参与者的ac响应的,则会进行发送中断事务命令。
4.分布式缓存
1.客户端缓存:页面和浏览器缓存,APP缓存,H5缓存。
2.NGIN缓存:本地缓存。
3.数据库缓存:持久层缓存(mybaits),mysql查询缓存。
4.操作系统缓存:Page cache。
5.分布式任务
1.Quartz是一个开源分布式调度库,JAVA实现。
2.xxl-job是一个支持分布式任务的工具。
6.设计一个秒杀系统
分层控制数据流量的并发,层层拦截,将请求尽量拦截在系统上游,避免将锁落到数据库。
1.页面
在页面上可以通过当前请求发送之后将点击按钮置灰,禁止重复购买,在js层面,可以限制用户在几秒在重复提交请求。
2.站点(nginx)
a.通过nginx进行的漏斗流算法进行限流,面对突发时刻大量请求访问。
b.也可以通过控制ip多次请求。
3.服务层
a.通过将请求放到队列中,进行批次处理,防止大量数据落到数据库请求。
b.对于读请求,可以通过redis单机可以抗的10wQPS,异步线程定时缓存里的数据。
4.数据库层
通过前面的个个层面拦截的请求,基本差不多,到达数据库的请求就是可控的,然后通过自身本身的锁进行控制,防止超买。
7.幂等
1.幂等是指接口的重复调用的情况下,返回结构是一致的,对于查询接口天然的实现幂等。
2.对于添加,更新,删除如何保证幂等性。
a.全局唯一ID:通过这个id可支持添加,查询,更新,删除。
b.更新和删除: 1)唯一索引 2)多版本控制。