惊群效应是什么

线程惊群

1 惊群效应(thundering herd)是指多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群效应。

性能影响

Linux内核对用户进程(线程)频繁地做无效的调度、上下文切换等使系统性能大打折扣。上下文切换(context switch)过高会导致CPU像个搬运工,频繁地在寄存器和运行队列之间奔波,更多的时间花在了进程(线程)切换,而不是在真正工作的进程(线程)上面。

代码示例

在一段无缓存则请求数据库的代码中,当高并发时只有一个线程能获取到锁,其他线程都休眠1秒,1秒后可能有成千上百个线程从休眠中被唤醒来争夺锁,但也只有一个线程能获取到锁,其他线程又继续休眠等待。```
public String getData2(String keywords) throws InterruptedException {
String data = getDataFromCache(keywords);
if (data == null) {
while (!lock.tryLock()) {
TimeUnit.SECONDS.sleep(1);
}
try {
data = getDataFromCache(keywords);
if (data == null) {
data = getDataFromDB(keywords);
saveToCache(keywords, data);
}
} finally {
lock.unlock();
}
}
return data;
}

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

退避策略
----

增加随机策略,每次休眠的时间为一个随机数,避免多个线程同一时间被唤醒。```
public String getData3(String keywords) throws InterruptedException {
String data = getDataFromCache(keywords);
if (data == null) {
while (!lock.tryLock()) {
// 使用随机数,免出现惊群效应,防止相同时间执行大量操作
long randomSleepTs = ThreadLocalRandom.current().nextLong(1000);
TimeUnit.MILLISECONDS.sleep(randomSleepTs);
}
try {
data = getDataFromCache(keywords);
if (data == null) {
data = getDataFromDB(keywords);
saveToCache(keywords, data);
}
} finally {
lock.unlock();
}
}
return data;
}

缓存惊群

缓存惊群换个名词就是缓存击穿、缓存踩踏。当缓存过期时,大量并发请求直接到数据库请求。