2.6.3
1、redis分布式锁的使用场景
简介:分布式锁是BATJ最常⻅的Redis⾯试题,对分布式锁的掌握,多场景下不同版本分布锁的掌握显得尤为关键。
1.1、分布式锁是什么
- 分布式锁是控制分布式系统或不同系统之间共同访问共享资源的⼀种锁实现
- 如果不同的系统或同⼀个系统的不同主机之间共享了某个资源时,往往通过互斥来防止彼此干扰
1.2、分布锁设计目的
可以保证在分布式部署的应用集群中,同一个方法在同一操作只能被一台机器上的一个线程执行。
1.3、设计要求
- 这把锁要是一把可重入锁(避免死锁)
- 这把锁有高可用的获取锁和释放锁功能
- 这把锁获取锁和释放锁的性能要好
1.4、分布锁实现方案分析
- 获取锁的时候,使用setnx(SETNX key val:当且仅当 key 不存在时,set 一个 key 为 val 的字符串,返回 1;
- 若 key 存在,则什么都不做,返回 【0】加锁,锁的 value 值为当前占有锁服务器内网IP编号拼接任务标识
- 在释放锁的时候进行判断。并使用expire 命令为锁添加一个超时时间,超过该时间则自动释放锁。(防止释放锁失败,到期自动释放)
- 返回1则成功获取锁。还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
setex(key,value,expire)过期以秒为单位 - 释放锁的时候,判断是不是该锁(即Value为当前服务器内网IP编号拼接任务标识),若是该锁,则执行delet进行锁释放。
2、Redis分布式锁的实现
简介:springboot定时任务,Redis分布式锁源码分析,高性能的分布式锁代码实现
2.1、springboot定时任务配置,定时任务配置步骤
- 1、开启springboot注解@EnableScheduling
- 2、执行方法加注解@Scheduled(cron=“0/10*****”)规律:秒分时日月年
2.2、本地服务器集群部署同一套代码?
2.2.1、面临问题分析
- jar包远程copy,scp源账户号@目标机器:路径,如scp
- 可单机部署多个节点也可部署在不同虚拟机上面,如果是单机部署多节点要保持端口不一致,如设置8080、8081、8082等
- 查看集群里面所有机器是否都启动成功
- netstat -anp | grep 8080 或者 ps -ef | grep 8080
- nohup java -jar jar包名称 &
3、本地服务器集群部署同一套代码
简介:单机多节点部署讲解,图解后端性能演变
3.1、服务器log日志打印, springboot已经logback
- 引入logback-spring.xml
- 配置路径,在application.properties加入路径引用(配置文件名称按照规则来,这下面的可不配置)
- logging.config=classpath:logback-spring.xml (日志配置文件路径)
- logging.path=/data/java/weblog/8080 (日志存储的文件夹,这个文件夹的路径要和logback-spring.xml配置文件中日志存储的路径一致)
- 修改启动端口
- nohup持久化启动方式
- nohup的意思是忽略SIGHUP信号, 所以当运行nohup a.jar的时候, 关闭shell, 那么a.jar进
程还是存在的(对SIGHUP信号免疫) - nohup java -jar jar名 &
- nohup的意思是忽略SIGHUP信号, 所以当运行nohup a.jar的时候, 关闭shell, 那么a.jar进
- nohup xdclass-mobile-redis-0.0.1-SNAPSHOT.jar &启动项目
- 可单机部署多个节点也可部署在不同虚拟机上面,如果是单机部署多节点要保持端口不一致,如设
置8080、8081、8082等 - 查看集群里面所有机器是否都启动成功 lsof -i:8080 ,如果没有安装lsof的话先执行
- yum install lsof
4、深入剖析TCP三次握手
查看本机TCP连接状态
- 查看当前机器的连接数
- netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
- 图解分析TCP三次握手协议
- 为什么要三次握手,不能像http或者UDP一样直接传输
- 主要是为了防止已失效的连接请求报文段突然又传到了B,因而报文错乱问题 假定A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放 以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建议连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多资源就这样白白浪费了。
- 主要是为了防止已失效的连接请求报文段突然又传到了B,因而报文错乱问题 假定A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放 以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建议连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多资源就这样白白浪费了。
4.2、copy其他
TCP三次握手
PS:TCP协议中,主动发起请求的一端称为『客户端』,被动连接的一端称为『服务端』。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据。
起初,服务器和客户端都为CLOSED状态。在通信开始前,双方都得创建各自的传输控制块(TCB)。
服务器创建完TCB后遍进入LISTEN状态,此时准备接收客户端发来的连接请求。
第一次握手
客户端向服务端发送连接请求报文段。该报文段的头部中SYN=1,ACK=0,seq=x。请求发送后,客户端便进入SYN-SENT状态。
- PS1:SYN=1,ACK=0表示该报文段为连接请求报文。
- PS2:x为本次TCP通信的字节流的初始序号。
TCP规定:SYN=1的报文段不能有数据部分,但要消耗掉一个序号。
第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。
该应答发送完成后便进入SYN-RCVD状态。 - PS1:SYN=1,ACK=1表示该报文段为连接同意的应答报文。
- PS2:seq=y表示服务端作为发送者时,发送字节流的初始序号。
- PS3:ack=x+1表示服务端希望下一个数据报发送序号从x+1开始的字节。
第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。
该报文段的头部为:ACK=1,seq=x+1,ack=y+1。
客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接的建立完成!
为什么连接建立需要三次握手,而不是两次握手?
防止失效的连接请求报文段被服务端接收,从而产生错误。
PS:失效的连接请求:若客户端向服务端发送的连接请求丢失,客户端等待应答超时后就会再次发送连接请求,此时,上一个连接请求就是『失效的』。
若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。
5、深入剖析TCP四次挥手
TCP网络调度原理和TCP四次挥手设计
5.1、你知道TCP四次挥手是什么吗?为什么要进行四次挥手
- 确保数据能够完整传输
- 当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了
- 但未必被动⽅所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,
它可能还需要发送一些数据给主动方后,再发送FIN报文给主动方,告诉主动方同意关闭连接。 - 所以这里的ACK报文和FIN报文多数情况下都是分开发送的。
- 模拟流程
A:“喂,我不说了 (FIN)。”A->FIN_WAIT1 B:“我知道了(ACK)。等下,上一句还没说完。Balabala…..(传输数据)”B->CLOSE_WAIT | A->FIN_WAIT2 B:”好了,说完了,我也不说了(FIN)。”B->LAST_ACK A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED
5.2、图解分析TCP四次挥手协议
- TCP前面10种状态切换
5.3、TCP第11种状态CLOSING 状态概念
- 这种状态在实际情况中应该很少见,属于这种比较罕见的例外状态。正常情况下,当一方发
送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING 状态表示一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?那就是当双方几乎在同时close()一个SOCKET的话,就出现了双方同时发送FIN报文的情况,这是就会出现CLOSING 状态,表示双方都正在关闭SOCKET连接。
5.4、查看tcp建立的状态 netstat -anp | grep 8080
5.5、TCP四次挥手 copy其他
TCP连接的释放一共需要四步,因此称为『四次挥手』。
我们知道,TCP连接是双向的,因此在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。
第一次挥手
若A认为数据发送完成,则它需要向B发送连接释放请求。该请求只有报文头,头中携带的主要参数为:
FIN=1,seq=u。此时,A将进入FIN-WAIT-1状态。
- PS1:FIN=1表示该报文段是一个连接释放请求。
- PS2:seq=u,u-1是A向B发送的最后一个字节的序号。
第二次挥手
B收到连接释放请求后,会通知相应的应用程序,告诉它A向B这个方向的连接已经释放。此时B进入CLOSE-WAIT状态,并向A发送连接释放的应答,其报文头包含:
ACK=1,seq=v,ack=u+1。
- PS1:ACK=1:除TCP连接请求报文段以外,TCP通信过程中所有数据报的ACK都为1,表示应答。
- PS2:seq=v,v-1是B向A发送的最后一个字节的序号。
- PS3:ack=u+1表示希望收到从第u+1个字节开始的报文段,并且已经成功接收了前u个字节。
A收到该应答,进入FIN-WAIT-2状态,等待B发送连接释放请求。
第二次挥手完成后,A到B方向的连接已经释放,B不会再接收数据,A也不会再发送数据。但B到A方向的连接仍然存在,B可以继续向A发送数据。
第三次挥手
当B向A发完所有数据后,向A发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。B便进入LAST-ACK状态。
第四次挥手
A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT状态。该状态会持续2MSL时间,若该时间段内没有B的重发请求的话,就进入CLOSED状态,撤销TCB。当B收到确认应答后,也便进入CLOSED状态,撤销TCB。
**为什么A要先进入TIME-WAIT状态,等待2MSL时间后才进入CLOSED状态? **
为了保证B能收到A的确认应答。
若A发完确认应答后直接进入CLOSED状态,那么如果该应答丢失,B等待超时后就会重新发送连接释放请求,但此时A已经关闭了,不会作出任何响应,因此B永远无法正常关闭
之所以存在 3-way hanshake 的说法,是因为 TCP 是双向通讯协议,作为响应一方(Responder) 要想初始化发送通道,必须也进行一轮 SYN + ACK。由于 SYN ACK 在 TCP 分组头部是两个标识位,因此处于优化目的被合并了。所以达到双方都能进行收发的状态只需要 3 个分组
在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。这两种不用的表述其实阐明的是同一个问题。
谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
参考:https://www.cnblogs.com/cenglinjinran/p/8482412.html