內網滲透常用命令
阿新 • • 發佈:2021-01-19
一、快取雪崩
快取雪崩:
redis掛掉了,請求全部走資料庫
對快取資料設定了相同的過期時間,導致快取有段時間失效,請求全部走資料庫
快取雪崩,請求全部走資料庫,資料庫會掛掉,這樣可能造成整個伺服器坍塌
解決方案:
- 針對“對快取資料設定了相同的過期時間,請求全部走資料庫”
在快取的時候給過期時間設定一個隨機值,這樣就會大幅的減少快取過期時間在同一時間 - 分事發前、事發中、事發後的解決
事發前: 實現redis的高可用(利用redis cluster叢集 或 主從+哨兵),減少redis掛掉
事發中: 萬一redis真的掛掉了,可以設定本地快取(ehcache)+限流(hystrix),儘量避免我們資料庫掛掉
二、快取穿透
快取穿透:
不停的訪問一個數據庫根本沒有的資料,比如黑客在攻擊資料庫時會請求ID為負值的,但是資料庫中不存在的資料時不會存到快取中,這樣就會導致資料庫崩潰,服務宕機
解決方案:
- 當資料庫查詢沒有資料時,將空物件設定到快取中,並給此物件設定一個過期時間
- 在請求redis之前就做攔截,非法資料的攔截、過濾
三、快取擊穿
快取擊穿:
某個 key 非常熱點,訪問非常頻繁,處於集中式高併發訪問的情況,當這個 key 在失效的瞬間,大量的請求就擊穿了快取,直接請求資料庫,就像是在一道屏障上鑿開了一個洞
解決方案
- 將熱點資料設定為永不過期
- 使用redis或者zookeeper的互斥鎖,等一個請求構建萬快取之後再釋放鎖,進而其他請求才能訪問此key( 一般使用此種方法來解決)
四、程式碼實現
1、防止快取穿透原始碼實現
(1)使用的是Google的Bloom Filter <1>引入依賴 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> (2)使用雙重驗證鎖解決高併發環境下的快取穿透問題 @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentMapper studentMapper; //springboot自動配置的,直接注入到類中即可使用 @Autowired private RedisTemplate<Object, Object> redisTemplate; /** * 查詢所有學生資訊,帶有快取 * @return */ public List<Student> getAllStudent() { //在高併發條件下,會出現快取穿透 List<Student> studentList = (List<Student>)redisTemplate.opsForValue().get("allStudent"); if (null == studentList) { //5個人, 4個等,1個進入 synchronized (this) { //雙重檢測鎖,假使同時有5個請求進入了上一個if(null == studentList), //加了鎖之後one by one 的訪問,這裡再次對快取進行檢測,盡一切可能防止快取穿透的產生,但是效能會有所損失 studentList = (List<Student>)redisTemplate.opsForValue().get("allStudent"); if (null == studentList) { studentList = studentMapper.getAllStudent(); redisTemplate.opsForValue().set("allStudent", studentList);System.out.println("請求的資料庫。。。。。。");} else {//System.out.println("請求的快取。。。。。。"); }}} else {System.out.println("請求的快取。。。。。。"); }return studentList;}}
2、防止快取雪崩、快取擊穿原始碼實現
(1)加互斥鎖,互斥鎖參考程式碼如下:
static Lock reenLock = new ReentrantLock();
public List<String> getData04() throws InterruptedException {
List<String> result = new ArrayList<String>();
// 從快取讀取資料
result = getDataFromCache();
if (result.isEmpty()) {
if (reenLock.tryLock()) {
try {
System.out.println("我拿到鎖了,從DB獲取資料庫後寫入快取");
// 從資料庫查詢資料
result = getDataFromDB();
// 將查詢到的資料寫入快取
setDataToCache(result);
} finally {
reenLock.unlock();// 釋放鎖
}
} else {
result = getDataFromCache();// 先查一下快取
if (result.isEmpty()) {
System.out.println("我沒拿到鎖,快取也沒資料,先小憩一下");
Thread.sleep(100);// 小憩一會兒
return getData04();// 重試
}
}
}
return result;
}
3、快取穿透、雪崩、擊穿最終結果都是對資料庫造成壓力
(1)不管是使用雙重檢索還是加互斥鎖,都是為了減輕DB壓力
(2)一般情況下使用加互斥鎖來實現