2024年最新接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁,java常见面试题

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Cloud实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Boot实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

server.connectZk();

server.saveServerInfo(args[0], args[1]);

//提供时间服务的线程没有启动,创建一个线程类,可以接收socket请求

new TimeService(Integer.parseInt(args[1])).start();

}

}

服务端提供时间查询的线程类:

import java.io.IOException;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Date;

//提供时间查询服务

public class TimeService extends Thread {

private int port = 0;

public TimeService(int port) {

this.port = port;

}

@Override

public void run() {

//通过socket与client进行交流,启动serversocket监听请求

try {

//指定监听的端口

final ServerSocket serverSocket = new ServerSocket(port);

//保证服务端一直运行

while (true) {

final Socket socket = serverSocket.accept();

//不关心client发送内容,server只考虑发送一个时间值

final OutputStream out = socket.getOutputStream();

out.write(new Date().toString().getBytes());

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

client端:

import org.I0Itec.zkclient.IZkChildListener;

import org.I0Itec.zkclient.ZkClient;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

// 注册监听zk指定目录,

//维护自己本地一个servers信息,收到通知要进行更新

//发送时间查询请求并接受服务端返回的数据

public class Client {

//获取zkclient

ZkClient zkClient = null;

//维护一个serversi 信息集合

ArrayList infos = new ArrayList();

private void connectZk() {

// 创建zkclient

zkClient = new ZkClient(“linux121:2181,linux122:2181”);

//第一次获取服务器信息,所有的子节点

final List childs = zkClient.getChildren(“/servers”);

for (String child : childs) {

//存储着ip+port

final Object o = zkClient.readData(“/servers/” + child);

infos.add(String.valueOf(o));

}

//对servers目录进行监听

zkClient.subscribeChildChanges(“/servers”, new IZkChildListener() {

public void handleChildChange(String s, List children) throws Exception {

//接收到通知,说明节点发生了变化,client需要更新infos集合中的数据

ArrayList list = new ArrayList();

//遍历更新过后的所有节点信息

for (String path : children) {

final Object o = zkClient.readData(“/servers/” + path);

list.add(String.valueOf(o));

}

//最新数据覆盖老数据

infos = list;

System.out.println(“–》接收到通知,最新服务器信息为:” + infos);

}

});

}

//发送时间查询的请求

public void sendRequest() throws IOException {

//目标服务器地址

final Random random = new Random();

final int i = random.nextInt(infos.size()); //随机选择一个服务器

final String ipPort = infos.get(i);

final String[] arr = ipPort.split(“:”);

//建立socket连接

final Socket socket = new Socket(arr[0], Integer.parseInt(arr[1]));

final OutputStream out = socket.getOutputStream();

final InputStream in = socket.getInputStream();

//发送数据

out.write(“query time”.getBytes());

out.flush();

//接收返回结果

final byte[] b = new byte[1024];

in.read(b);//读取服务端返回数据

System.out.println(“client端接收到server:+” + ipPort + “+返回结果:” + new String(b));

//释放资源

in.close();

out.close();

socket.close();

}

public static void main(String[] args) throws InterruptedException {

final Client client = new Client();

client.connectZk(); //监听器逻辑

while (true) {

try {

client.sendRequest(); //发送请求

} catch (IOException e) {

e.printStackTrace();

try {

client.sendRequest();

} catch (IOException e1) {

e1.printStackTrace();

}

}

//每隔几秒中发送一次请求到服务端

Thread.sleep(2000);

}

}

}

分布式锁:

=====

1.什么是锁:

=======

  • 在单机程序中,当存在多个线程可以同时改变某个变量(可变共享变量)时,为了保证线程安全 (数据不能出现脏数据)就需要对变量或代码块做同步,使其在修改这种变量时能够串⾏执⾏消除并 发修改变量。

  • 对变量或者堆代码码块做同步本质上就是加锁。⽬的就是实现多个线程在⼀个时刻同⼀个代码块只 能有⼀个线程可执⾏

2. 分布式锁

========

分布式的环境中会不会出现脏数据的情况呢?类似单机程序中线程安全的问题。观察下⾯的例⼦:

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

上⾯的设计是存在线程安全问题。

问题:

假设Redis ⾥⾯的某个商品库存为 1;此时两个⽤户同时下单,其中⼀个下单请求执⾏到第 3 步,更新 数据库的库存为 0,但是第 4 步还没有执⾏。

⽽另外⼀个⽤户下单执⾏到了第 2 步,发现库存还是 1,就继续执⾏第 3 步。但是商品库存已经为0, 所以如果数据库没有限制就会出现超卖的问题。

解决方案:

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

公司业务发展迅速,系统应对并发不断提⾼,解决⽅案是要增加⼀台机器,结果会出现更⼤的问题:

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

利⽤Zookeeper可以创建临时带序号节点的特性来实现⼀个分布式锁。

分布式锁的作⽤:在整个系统提供⼀个全局、唯⼀的锁,在分布式系统中每个系统在进⾏相关操作的时 候需要获取到该锁,才能执⾏相应操作。

zk实现分布式锁:

=========

利⽤Zookeeper可以创建临时带序号节点的特性来实现⼀个分布式锁。

实现思路:

  • 锁就是zk指定⽬录下序号最⼩的临时序列节点,多个系统的多个线程都要在此⽬录下创建临时的顺 序节点,因为Zk会为我们保证节点的顺序性,所以可以利⽤节点的顺序进⾏锁的判断。

  • 每个线程都是先创建临时顺序节点,然后获取当前⽬录下最⼩的节点(序号),判断最⼩节点是不是 当前节点,如果是那么获取锁成功,如果不是那么获取锁失败。

  • 获取锁失败的线程获取当前节点上⼀个临时顺序节点,并对对此节点进⾏监听,当该节点删除的时 候(上⼀个线程执⾏结束删除或者是掉线zk删除临时节点)这个线程会获取到通知,代表获取到了 锁。

流程图:

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

分布式锁的具体代码实现:

整体框架:

接上篇:一套方案轻松实现Zookeeper服务器动态上下线和分布式锁

//zk实现分布式锁

public class DisLockTest {

public static void main(String[] args) {

//使用10个线程模拟分布式环境

for (int i = 0; i < 10; i++) {

new Thread(new DisLockRunnable()).start();//启动线程

}

}

static class DisLockRunnable implements Runnable {

public void run() {

//每个线程具体的任务,每个线程就是抢锁,

final DisClient client = new DisClient();

client.getDisLock();

//模拟获取锁之后的其它动作

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

//释放锁

client.deleteLock();

}

}

}

具体抢锁类:

import org.I0Itec.zkclient.IZkDataListener;

import org.I0Itec.zkclient.ZkClient;

import java.util.Collections;

import java.util.List;

import java.util.concurrent.CountDownLatch;

//抢锁

//1. 去zk创建临时序列节点,并获取到序号

//2. 判断自己创建节点序号是否是当前节点最小序号,如果是则获取锁

//执行相关操作,最后要释放锁

//3. 不是最小节点,当前线程需要等待,等待你的前一个序号的节点

总结

对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)

image

Java面试精选题、架构实战文档

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  1. 不是最小节点,当前线程需要等待,等待你的前一个序号的节点

总结

对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)

[外链图片转存中…(img-pTxq7P0N-1715248365726)]

Java面试精选题、架构实战文档

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值