分布式和集群
分布式一定是集群,但是集群不一定是分布式(可能是复制的)
集群是多个实例一起工作,分布式将一个系统拆分之后那就是多个实例
分布式应用结构:
Hash算法
适用于在加密,数据存储和查找方面有hash表,效率高,最理想的时间复杂度接近O(1)
例如:
直接寻址法:存储的数据和数组下标绑定到一起 H(key)=a*key + b(a,b是常量)
除留余数法:存储的数据对空间长度求模确定存储位置
普通Hash算法存在问题:扩容缩容都需要影响全局重新计算,因此引入一致性Hash
一致性Hash算法
一致性Hash算法将整个Hash空间组织成一个虚拟的圆环,Hash函数的值空间为0 - 2^32 -1 整形,如图所示
一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
在节点少时容易出现资源倾斜,解决这种问题使用虚拟节点机制,每个节点对应多个hash,通过虚拟节点映射真实节点
集群时钟同步方案
如果所有服务器都能联网,可以分别同步国家时间服务器
使用命令:ntpdate -u ntp.api.bz
如果存在不能联网的的机器,定时同步局域网内能联网的其他服务器时间(如果全部不能联网就指定设置一台同步)
分布式ID生成方案
UUID 重复概率低
独立数据库自增id 性能和可靠性都低
SnowFlake 雪花算法 :二进制 由41位时间戳 + 10位机器码 + 12位序列号组成
Redis incr
分布式调度
1.运行在分布式集群环境下的调度任务(同一个定时任务程序部署多份,只应该有一个定时任务在执行)
2.分布式调度—>定时任务的分布式—>定时任务的拆分(即为把一个大的作业任务拆分为多个小的作业任务,同时执行)
定时任务与消息队列的区别
共同点
- 异步处理
2. 应用解耦
3. 流量削峰
不同点
- 定时任务作业是时间驱动,而MQ是事件驱动
2. 定时任务作业更倾向于批处理,MQ倾向于逐条处理
分布式调度框架Elastic-Job
分布式调度协调 基于 Zookeeper 实现
在分布式环境中,任务能够按指定的调度策略执行,并且能够避免同一任务多实例重复执行
丰富的调度策略 基于成熟的定时任务作业框架Quartz cron表达式执行定时任务
弹性扩容缩容 当集群中增加某一个实例,它应当也能够被选举并执行任务;当集群减少一个实例 时,它所执行的任务能被转移到别的实例来执行。
失效转移 某实例在任务执行失败后,会被转移到其他实例执行
错过执行作业重触发 若因某种原因导致作业错过执行,自动记录错过执行的作业,并在上次作业 完成后自动触发。
支持并行调度 支持任务分片,任务分片是指将一个任务分为多个小任务项在多个实例同时执行。 作业分片一致性 当任务被分片后,保证同一分片在分布式环境中仅一个执行实例。
Leader节点选举机制
每个Elastic-Job的任务执行实例App作为Zookeeper的客户端来操作ZooKeeper的znode
1.多个实例同时创建leader节点
2.leader节点只能创建一个,后创建的会失败,创建成功的实例会被选为leader节点, 执行任务
任务分片:
处理数据量过大时,ElasticJob可以把作业分为多个的task(每一个task就是一个任务分片),每一个task交给具体的一个机器实例去处理(一个机器实例是可以处理多个task的),但是具体每个task 执行什么逻辑由我们自己来指定。
当扩容或者缩容时,Zookeeper或通知Elastic-Job 重新分片
Session共享(一致性)
解决方案:
- Nginx的 IP_Hash 策略 :同一个客户端IP的请求都会被路由到同一个目标服务器
缺陷:服务器重启Session丢失,存在单点负载高的⻛险,单点故障问题
2. Session复制:Tomcat修改配置文件,达到Session之间的复制
缺陷:性能低,延迟
3. Session共享,使用缓存中间件
Spring Session 使用仅需要引入依赖,配置redis,开启注解
原理如下图:
作业:
基于SpringBoot实现一个登陆功能,含有拦截验证,使用Spring session保持session一致性,打成war包,将war包部署到tomcat集群中,要求1个Nginx节点、2个Tomcat节点,使用Nginx轮询访问两个tomcat
主要代码及配置:
登录Controller
拦截器:此处简易实现
配置拦截登录之外的请求
Nginx配置