前言

参与度算法是用在计算多个节点之间的参与情况的算法,也就是说在多个已经确认的节点个数之间的一种算法。

说人话
就是假设有10个节点,这10个节点都正常工作参与度就是100%,如果挂了一个节点,参与度就是:90%。
是不是有点感觉了。

在分布式场景下,参与度是个重要的指标,尤其是各种分布式应用,那用的更是多。
比如有一堆reids集群,挂了几个还可以工作,这就是一个参与度的阀值。
DPOS共识的区块链的场景下,这个值就可以起到一个参考指标的作用。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.liukai.blockchain.labs;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

import static java.util.Arrays.fill;

/**
* @author liukai
* @since 2022/4/25.
*/
public class BlockFilledSlot {

public static Map<String, Object> database = new HashMap<>();

public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;

static {
initFill();
initBlockFilledSlotsIndex();
}

public static void initFill() {
int[] blockFilledSlots = new int[getBlockFilledSlotsNumber()];
fill(blockFilledSlots, 1);
database.put("BLOCK_FILLED_SLOTS", blockFilledSlots);
System.out.println("init param");
System.out.println("SlotCount=" + IntStream.of(blockFilledSlots).sum());
System.out.println("Percent=" + calculateFilledSlotsCount() + "%");
System.out.println("===================");
}

public static void initBlockFilledSlotsIndex() {
database.put("BLOCK_FILLED_SLOTS_INDEX", 0);
}

public static int getBlockFilledSlotsIndex() {
return (int) database.get("BLOCK_FILLED_SLOTS_INDEX");
}

public static int getBlockFilledSlotsNumber() {
return BLOCK_FILLED_SLOTS_NUMBER;
}

public static int[] getBlockFilledSlots() {
return (int[]) database.get("BLOCK_FILLED_SLOTS");
}

// 每一次 true false 都会让 index 往前移动一步
public static void applyBlock(boolean fillBlock) {
int[] blockFilledSlots = getBlockFilledSlots();
int blockFilledSlotsIndex = getBlockFilledSlotsIndex();
// System.out.println("blockFilledSlotsIndex before: " + blockFilledSlotsIndex);
blockFilledSlots[blockFilledSlotsIndex] = fillBlock ? 1 : 0;
saveBlockFilledSlots(blockFilledSlots);
saveBlockFilledSlotsIndex((blockFilledSlotsIndex + 1) % getBlockFilledSlotsNumber());
// System.out.println("blockFilledSlotsIndex after: " + getBlockFilledSlotsIndex());
}

private static void saveBlockFilledSlots(int[] blockFilledSlots) {
// System.out.println("array: " + Arrays.toString(blockFilledSlots));
database.put("BLOCK_FILLED_SLOTS", blockFilledSlots);
}

private static void saveBlockFilledSlotsIndex(int i) {
database.put("BLOCK_FILLED_SLOTS_INDEX", i);
}

public static int calculateFilledSlotsCount() {
int[] blockFilledSlots = getBlockFilledSlots();
int sum = IntStream.of(blockFilledSlots).sum();
// System.out.println("calculateFilledSlotsCount: " + sum);
return 100 * sum / getBlockFilledSlotsNumber();
}

public static void main(String[] args) {
int slot = 64;
// 实际中,slot 的个数是根据 witness 的产块与否来决定的
for (int i = 0; i < slot; i++) {
applyBlock(false);
System.out.println("SlotsCount: " + IntStream.of(getBlockFilledSlots()).sum());
System.out.println("Percent: " + calculateFilledSlotsCount() + " %");
}
System.out.println("-----------");
for (int i = 0; i < 128; i++) {
applyBlock(true);
System.out.println("SlotsCount: " + IntStream.of(getBlockFilledSlots()).sum());
System.out.println("Percent: " + calculateFilledSlotsCount() + " %");
}
}
}

总结

这个算法,其实就是对一个百分比波动的简单算法的实现。不管是否简单,在实际应用中,确可以发挥作用,也值得学习。