?分布式鎖:在一個公共的存儲服務上打上一個標記,如Redis的setnx命令,是''先到先得''方式獲得鎖,ZooKeeper有點像下面的demo,比較大小的方式判決誰獲得鎖。
package com.ldj.mybatisflex.demo;import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;/*** User: ldj* Date: 2025/1/12* Time: 1:50* Description: 基于文件系統制作的分布式鎖demo*/
public class LockDemo {public static void main(String[] args) throws InterruptedException {//模擬文件存儲系統List<String> files = new CopyOnWriteArrayList<>();List<Integer> hashCodes = new ArrayList<>();//使用3個線程模擬3臺服務往文件存儲系統寫消息writeMsg(files, hashCodes);System.out.println("result:" + hashCodes.toString());//構建hashCode與IP的對映關系Map<String, String> map = new LinkedHashMap<>();for (int i = 0; i < hashCodes.size(); i++) {map.put(hashCodes.get(i).toString(), files.get(i).split(";")[0]);}System.out.println(map.toString());//排序獲取最大數值Collections.sort(hashCodes);String key = hashCodes.get(hashCodes.size() - 1).toString();System.out.println("key: " + key);//比較3個消息code那個數字最大,最大的就是獲得鎖System.out.println("獲得分布式鎖的服務IP是: " + map.get(key));//模擬獲得鎖服務處理業務TimeUnit.SECONDS.sleep(3);//處理完成業務,通知文件存儲系統清理消息文件(或者文件系統的定時任務自己處理也行)files.clear();System.out.println(files.toString());/*假設一個場景,1號服務獲得鎖,處理業務過程中掛了,會怎么樣???響應超時用戶重試請求需要服務協調器去注冊中心,根據心跳機制找到健康的服務然后再重新獲取分布式鎖當然這個場景不需要分布式鎖,直接讓服務協調器負載均衡派發請求就好了*/}private static void writeMsg(List<String> files, List<Integer> hashCodes) throws InterruptedException {//計數器,用于等待線程執行完畢!CountDownLatch count = new CountDownLatch(3);new Thread(() -> {files.add("192.168.208.1;" + UUID.randomUUID().toString().replaceAll("-", ""));count.countDown();}).start();new Thread(() -> {files.add("192.168.208.2;" + UUID.randomUUID().toString().replaceAll("-", ""));count.countDown();}).start();new Thread(() -> {files.add("192.168.208.3;" + UUID.randomUUID().toString().replaceAll("-", ""));count.countDown();}).start();//等待3個線程(服務器)往文件系統寫消息count.await();System.out.println("3個模擬服務器往文件存儲器完畢!");System.out.println(files.toString());//將消息字符串轉為正整數字if (files.size() > 0) {for (String file : files) {hashCodes.add(Math.abs(file.hashCode()));}}//重復判單,確保每個數字不相等,如果相等再來一次HashSet<Integer> set = new HashSet<>(hashCodes);if (set.size() != hashCodes.size()) {files.clear();hashCodes.clear();writeMsg(files, hashCodes);}}
}