缓存一致性容错机制-租约 代码demo

80 阅读1分钟
@Data
public class Lease {
    private String value;
    private Integer interval;
    private Long expireTime;

    private Lease() {
    }

    private Lease(int interval) {
        this.interval = interval;
    }

    public static Lease generate(int interval) {
        Lease lease = new Lease(interval);
        lease.setValue(UUID.randomUUID().toString());
        lease.setExpireTime(System.currentTimeMillis() + lease.interval * 1000);
        return lease;
    }
}
@Data
public class Client {
    private int num;
    private Lease lease;

    public int get(Server server) {
        // 租约过期
        if (this.lease == null || this.lease.getExpireTime() < System.currentTimeMillis()) {
            System.out.println("租约不存在 || 租约过期,重新申请");
            this.num = server.get(this);
        }
        return this.num;
    }

    public int update(Server server, int val) {
        return server.update(this, val);
    }

}
@Data
public class Server {
    private int num;
    // 租约
    private Lease lease;
    // 修改状态
    private boolean updateing;
    // 客户端
    private Set<Client> clients = new HashSet<>();

    public int get(Client client) {
        this.clients.add(client);

        // 数值修改,阻塞
        while (this.updateing) {
            System.out.println("数据修改,阻塞...");
        }

        // 首次发布租约
        if (this.lease == null || this.lease.getExpireTime() < System.currentTimeMillis()) {
            this.lease = Lease.generate(10);
        }
        client.setLease(this.lease);
        return num;
    }

    public int update(Client client, int val) {

        if (updateing) {
            return this.num;
        }
        updateing = true;

        // 用于模拟阻塞
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 租约过期
        this.lease = null;
        for (Client c : clients) {
            c.setLease(this.lease);
        }
        this.num += val;
        client.setNum(this.num);
        this.updateing = false;
        return this.num;
    }

}
public class Test {

    public static void execThread(Runnable runnable) {
        new Thread(runnable).start();
    }

    public static void main(String[] args) {
        Server server = new Server();
        Client a = new Client();
        Client b = new Client();
        Client c = new Client();

        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入操作");
            String input = scanner.nextLine();
            int val = 0;
            switch (input) {
                case "mock_block":
                    // 模拟数据更新阻塞
                    execThread(() -> {
                        b.update(server, 2);
                    });
                    execThread(() -> {
                        System.out.println("a val: " + a.get(server));
                        System.out.println("b val: " + b.get(server));
                        System.out.println("c val: " + c.get(server));
                    });
                case "a_get":
                    val = a.get(server);
                    break;
                case "b_get":
                    val = b.get(server);
                    break;
                case "c_get":
                    val = b.get(server);
                    break;
                case "a_update":
                    val = a.update(server, 1);
                    break;
                case "b_update":
                    val = b.update(server, 2);
                    break;
                case "c_update":
                    val = c.update(server, 3);
                    break;
                default:
                    break;
            }
            System.out.println("val: " + val);
        }
    }
}