:::
场景: 在并发场景下更新数据库同一条数据(update *** from ** where ***), 当并发量上来时会造成上一条更新未完成,下一条更新指令又发起了,这时新的请求会被挂起,等待前一个命令执行完毕,当积累很多会造成明显的慢sql;
:::
# 方案1️⃣ 合并多次请求,当更新数到达一定量级时在更新数据到DB
# 源代码
/**
* 累加容器 The type Accumulation container.
*
* @author zhairuihao
*/
public class AccumulationContainer {
private final int limit;
private static final int DEFAULT_SIZE = 100;
private static final int DEFAULT_INITIAL_CAPACITY = 1000;
private static Map<String, AtomicInteger> MAP;
/** Instantiates a new Accumulation container. */
public AccumulationContainer() {
this.limit = DEFAULT_SIZE;
MAP = new HashMap<>(DEFAULT_INITIAL_CAPACITY);
}
/**
* Instantiates a new Accumulation container.
*
* @param size the size
* @param initialCapacity the initial capacity
*/
public AccumulationContainer(final Integer size, final int initialCapacity) {
this.limit = size;
MAP = new HashMap<>(initialCapacity);
}
/**
* Execute.
*
* @param <T> the type parameter
* @param key the key
* @param val the val
* @param function the consumer
* @return the t
*/
public synchronized <T> T execute(
final String key, final int val, final BiFunction<String, Integer, T> function) {
AtomicInteger atomicInteger = MAP.get(key);
if (Objects.isNull(atomicInteger)) {
atomicInteger = new AtomicInteger(0);
MAP.put(key, atomicInteger);
}
final int value = atomicInteger.addAndGet(val);
if (value >= this.limit) {
this.remove(key);
return function.apply(key, value);
}
return null;
}
/**
* Execute.
*
* @param <T> the type parameter
* @param key the key
* @param function the consumer
* @return the t
*/
public synchronized <T> T execute(
final String key, final BiFunction<String, Integer, T> function) {
return this.execute(key, 1, function);
}
private synchronized void remove(final String key) {
MAP.put(key, new AtomicInteger(0));
}
}
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
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
# 测试代码
public class AccumulationContainer {
static AtomicInteger atomicInteger = AtomicInteger(0);
public static void main(String args[]) {
AccumulationContainer accumulationContainer = new AccumulationContainer();
for (int i = 0; i < 1000; i++) {
new Thread(() -> test(accumulationContainer)).start();
}
}
private static void test(AccumulationContainer accumulationContainer) {
for (int i = 0; i < 100; i++) {
System.out.println(" i: " + i);
accumulationContainer.execute(
"1",
(key, val) -> {
System.out.println(" key val" + key + "---" + val);
System.out.println(
" atomicInteger.incrementAndGet()" + atomicInteger.incrementAndGet());
return val;
});
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 测试结果
i: 94
i: 95
i: 96
i: 97
i: 98
i: 99
i: 98
i: 99
i: 95
i: 96
i: 97
i: 98
i: 99
i: 97
i: 98
i: 99
key val1---100
atomicInteger.incrementAndGet()1000
Process finished with exit code 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21