缓存雪崩、缓存击穿
2019獨角獸企業重金招聘Python工程師標準>>>
雪崩:因某一時刻,緩存集中失效導致??
解決辦法:加鎖??
package com.enjoy.service;import com.enjoy.entity.Provinces; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service;import javax.annotation.Resource; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;/*** 緩存雪崩*/ @Service("provincesService") public class ProvincesServiceImpl3 extends ProvincesServiceImpl implements ProvincesService{private static final Logger logger = LoggerFactory.getLogger(ProvincesServiceImpl3.class);@Resourceprivate CacheManager cm;private ConcurrentHashMap<String, Lock> locks = new ConcurrentHashMap<>();//線程安全的private static final String CACHE_NAME = "province";//public Provinces detail(String provinceid) {// 1.從緩存中取數據Cache.ValueWrapper valueWrapper = cm.getCache(CACHE_NAME).get(provinceid);if (valueWrapper != null) {logger.info("緩存中得到數據");return (Provinces) (valueWrapper.get());}//2.加鎖排隊,阻塞式鎖doLock(provinceid);//32個省,最多只有32把鎖,1000個線程try{//第二個線程進來了// 一次只有一個線程//雙重校驗,不加也沒關系,無非是多刷幾次庫valueWrapper = cm.getCache(CACHE_NAME).get(provinceid);//第二個線程,能從緩存里拿到值?if (valueWrapper != null) {logger.info("緩存中得到數據");return (Provinces) (valueWrapper.get());//第二個線程,這里返回}Provinces provinces = super.detail(provinceid);// 3.從數據庫查詢的結果不為空,則把數據放入緩存中,方便下次查詢if (null != provinces){cm.getCache(CACHE_NAME).put(provinceid, provinces);}return provinces;}catch(Exception e){return null;}finally{//4.解鎖releaseLock(provinceid);}}private void releaseLock(String userCode) {ReentrantLock oldLock = (ReentrantLock) locks.get(userCode);if(oldLock !=null && oldLock.isHeldByCurrentThread()){oldLock.unlock();}}private void doLock(String lockcode) {//provinceid有不同的值,參數多樣化//provinceid相同的,加一個鎖,---- 不是同一個key,不能用同一個鎖ReentrantLock newLock = new ReentrantLock();//創建一個鎖Lock oldLock = locks.putIfAbsent(lockcode, newLock);//若已存在,則newLock直接丟棄if(oldLock == null){newLock.lock();}else{oldLock.lock();}} }擊穿:惡意攻擊? 大量查詢不存在的記錄
解決方法:布隆過濾器
package com.enjoy.service;import com.enjoy.entity.Provinces; import com.google.common.base.Charsets; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable;import javax.annotation.PostConstruct; import java.util.List;/*** 緩存穿透*/ //@Service("provincesService") public class ProvincesServiceImpl4 extends ProvincesServiceImpl implements ProvincesService{private BloomFilter<String> bf =null; //等效成一個set集合@PostConstruct //對象創建后,自動調用本方法public void init(){//在bean初始化完成后,實例化bloomFilter,并加載數據List<Provinces> provinces = this.list();//當成一個SET----- 占內存,比hashset占得小很多bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), provinces.size());// 32個for (Provinces p : provinces) {bf.put(p.getProvinceid());}}@Cacheable(value = "province")public Provinces detail(String provinceid) {//先判斷布隆過濾器中是否存在該值,值存在才允許訪問緩存和數據庫if(!bf.mightContain(provinceid)){System.out.println("非法訪問--------"+System.currentTimeMillis());return null;}System.out.println("數據庫中得到數據--------"+System.currentTimeMillis());Provinces provinces = super.detail(provinceid);return provinces;}@CachePut(value = "province",key = "#entity.provinceid")public Provinces update(Provinces entity) {super.update(entity);return entity;}@CacheEvict(value = "province",key = "#entity.provinceid")public Provinces add(Provinces entity) {super.add(entity);return entity;}@Override@CacheEvict("province")public void delete(String provinceid) {super.delete(provinceid);}}?
轉載于:https://my.oschina.net/u/2351011/blog/3043174
總結
- 上一篇: 1_STM32cubeIDE_黑色主题修
- 下一篇: excel导入数据库的简单方法