成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Redis實現(xiàn)廣告緩存、并完善緩存擊穿

KitorinZero / 2226人閱讀

摘要:完善緩存擊穿問題問題描述,分布式場景中,有時候存在高并發(fā)訪問,比如秒殺活動。在高并發(fā)訪問下請求全部懟到數(shù)據(jù)庫,可能導致數(shù)據(jù)庫掛掉,這就是緩存擊穿。緩存擊穿解決方案已經(jīng)能解決日常情況,但還是有一定提升的空間的。

“做人、做程序,變則通,不變只能一直死循環(huán)下去”      ————尼古斯拉
Docker安裝官方Redis

參考文章:Docker安裝官方Redis鏡像并啟用密碼認證

拉取最新版的redis鏡像:docker pull redis:latest

啟動容器并帶密碼:

docker run --name redis-test -p 6379:6379 -d --restart=always redis:latest redis-server --appendonly yes --requirepass "your passwd"

查看容器、注意看id: docker ps

查看進程: ps -ef|grep redis

進入容器執(zhí)行redis客戶端:

docker exec -it a126ec987cfe redis-cli -h yourhost -p 6379 -a "your passwd"
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> info
...

能ping通即可正常使用,這個例子比起原先方式,省去了編譯、配置、開機啟動服務一大堆麻煩。docker就是好,docker就是棒,docker頂呱呱。

廣告緩存功能的實現(xiàn) 添加依賴

    org.springframework.boot
    spring-boot-starter-data-redis
    2.1.3.RELEASE
添加配置
# Redis服務器地址
spring.redis.host=yourhost
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認為空)
spring.redis.password=xxxx
# Redis數(shù)據(jù)庫索引(默認為0)
spring.redis.database=0
# 連接池最大連接數(shù)(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 連接池中的最大空閑連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.jedis.pool.min-idle=0
# 連接超時時間(毫秒)
spring.redis.timeout=0
緩存功能核心邏輯代碼
@Service
public class ContentServiceImpl implements ContentService {
    @Autowired
    private ContentMapper contentMapper;
    @Autowired
    private StringRedisTemplate redis;
    @Override
    public Object contentList(Long cid) throws Exception {
        String test= (String) redis.opsForHash().get("ContentList", cid.toString());
        if(test==null) {
        System.out.println("緩存未命中,執(zhí)行SQL");
        ContentExample example=new ContentExample();
        example.createCriteria().andCategoryIdEqualTo(cid);
        List list=contentMapper.selectByExample(example);
        test=new ObjectMapper().writeValueAsString(list);
        redis.opsForHash().put("ContentList", cid.toString(), test);
        return test;
        }
        System.out.println("緩存命中,直接使用");
        return test;
    }
}
功能測試、調(diào)錯

首次請求:


二次請求、多次請求:


Tips:

有時會報redis連接超時connect timed out,把鏈接超時時間改大一點就好了,建議200以上,一個小bug,不作過多闡述。
完善緩存擊穿問題

問題描述,分布式場景中,有時候存在高并發(fā)訪問,比如秒殺活動?;蚴怯泻诳兔看喂室獠樵円粋€在緩存內(nèi)必然不存在的數(shù)據(jù),導致每次請求都要去存儲層去查詢,這樣緩存就失去了意義。在高并發(fā)訪問下請求全部懟到數(shù)據(jù)庫,可能導致數(shù)據(jù)庫掛掉,這就是緩存擊穿。
場景如下圖所示:

方法一:使用synchronized

public Object contentList(Long cid) throws Exception {
        String test= null;
        synchronized (redis) {
            test=(String) redis.opsForHash().get("ContentList", cid.toString());
        }            
        if(test==null) {
        System.out.println("緩存未命中,執(zhí)行SQL");
        ContentExample example=new ContentExample();
        example.createCriteria().andCategoryIdEqualTo(cid);
        List list=contentMapper.selectByExample(example);
        test=new ObjectMapper().writeValueAsString(list);
        redis.opsForHash().put("ContentList", cid.toString(), test);
        return test;
        }
        System.out.println("緩存命中,直接使用");
        return test;
}

方法二:使用互斥鎖

@Override    
    public Object contentList(Long cid) throws Exception {        
        String test= (String) redis.opsForHash().get("ContentList", cid.toString());        
        if(test==null) {
            System.out.println("緩存未命中,執(zhí)行SQL");
            if(redis.opsForValue().setIfAbsent("key", "value")){ 
                redis.expire("key", 30000, TimeUnit.MILLISECONDS);
                ContentExample example=new ContentExample();
                example.createCriteria().andCategoryIdEqualTo(cid);
                List list=contentMapper.selectByExample(example);
                test=new ObjectMapper().writeValueAsString(list);
                redis.opsForHash().put("ContentList", cid.toString(), test);
                redis.delete("key");
                return test;
            }
        }
        System.out.println("緩存命中,直接使用");
        return test;
    }

方法二原理就第一個請求進來執(zhí)行redis.opsForValue().setIfAbsent("key", "value")沒有值為true才執(zhí)行業(yè)務邏輯。如果沒有執(zhí)行完業(yè)務邏輯、delete("key")。第二個請求就會查到有值為flase,那是進不去的,相當于被鎖住了。
使用redis.expire("key", 30000, TimeUnit.MILLISECONDS)為了防止調(diào)用setIfAbsent方法之后線程掛掉了,沒有執(zhí)行到delete("key")這一步。這樣的話,如果沒有給鎖設置過期的時間,默認會永不過期。那么這個鎖就會一直存在,想查庫也查不到了。

評價:這兩個解決方案已經(jīng)能應對日程大部分情況。方案一一存在一定性能損耗,方案二在極端情況下有死鎖的可能性,那么還是使用方案二吧。

完善數(shù)據(jù)同步的問題

問題描述:如果廣告內(nèi)容改變了,即數(shù)據(jù)庫內(nèi)容已經(jīng)改變的,但請求還是從原來的緩存里拿數(shù)據(jù),這顯然是不對的,所以我們更改數(shù)據(jù)庫時要把緩存清一清。

public Object contentSave(Content content) {
        Date date =new Date();
        content.setCreated(date);
        content.setUpdated(date);
        contentMapper.insert(content);
        redis.delete("ContentList");
        return Result.of(200, "添加成功");
    }
總結

這個小案例碰到了不少問題,值得一提的是在云上安裝redis安裝了好幾次都不對,最后改用docker才安成了,做程序還是得學會靈活變通呀。緩存擊穿解決方案已經(jīng)能解決日常99.9%情況,但還是有一定提升的空間的。加油吧,騷年。
最后,寫這樣一篇文章真的好費時間,有緣人記得點贊哦,筆芯!

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/27689.html

相關文章

  • redis相關問題

    摘要:若其他線程發(fā)現(xiàn)獲取鎖失敗,則睡眠后重試。容易造成死鎖問題布隆過濾器,迅速判斷一個元素是否在一個集合中。將已存在的緩存放到布隆過濾器中,當黑客訪問不存在的緩存時迅速返回避免緩存及掛掉。 redis理解 A.執(zhí)行流程 showImg(https://user-gold-cdn.xitu.io/2019/1/11/1683aabdeb2fcc3a); 緩存雪崩 showImg(https:/...

    mist14 評論0 收藏0
  • Redis 分布式鎖--PHP

    摘要:分布式鎖的作用在單機環(huán)境下,有個秒殺商品的活動,在短時間內(nèi),服務器壓力和流量會陡然上升。分布式集群業(yè)務業(yè)務場景下,每臺服務器是獨立存在的。這里就用到了分布式鎖這里簡單介紹一下,以的事務機制來延生。 Redis 分布式鎖的作用 在單機環(huán)境下,有個秒殺商品的活動,在短時間內(nèi),服務器壓力和流量會陡然上升。這個就會存在并發(fā)的問題。想要解決并發(fā)需要解決以下問題 1、提高系統(tǒng)吞吐率也就是qps 每...

    canger 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<