精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

聊聊分頁列表緩存設計

jf_ro2CN3Fa ? 來源:勇哥java實戰(zhàn)分享 ? 2023-06-06 18:25 ? 次閱讀

1 直接緩存分頁列表結果

這是最簡單易懂的方案,我們按照不同的分頁條件查詢出結果后,直接緩存分頁結果 。

c38fc192-043c-11ee-90ce-dac502259ad0.png

偽代碼如下:

publicListgetPageList(Stringparam,intpage,intsize){
Stringkey="productList"+page+"size:"+size+
"param:"+param;
ListdataList=cacheUtils.get(key);
if(dataList!=null){
returndataList;
}
dataList=queryFromDataBase(param,page,size);
if(dataList!=null){
cacheUtils.set(key,dataList,Constants.ExpireTime);
}
}

這種方案的優(yōu)點是工程簡單,性能也快,但是有一個明顯的缺陷基因:列表緩存的顆粒度非常大

假如列表中數據發(fā)生增刪,為了保證數據的一致性,需要修改分頁列表緩存。

有兩種方式 :

1、依靠緩存過期來惰性的實現 ,但業(yè)務場景必須包容;

2、使用 Redis 的 keys 找到該業(yè)務的分頁緩存,執(zhí)行刪除指令。但 keys 命令對性能影響很大,會導致 Redis 很大的延遲 。

生產環(huán)境使用 keys 命令比較危險,發(fā)生事故的幾率高,非常不推薦使用

2 查詢對象ID列表,再緩存每個對象條目

直接緩存分頁結果雖然好用,但緩存的顆粒度太大,保證數據一致性比較麻煩。

所以我們的目標是更細粒度的控制緩存

c3b84ca2-043c-11ee-90ce-dac502259ad0.png

我們先查詢出商品分頁對象ID列表,然后為每一個商品對象創(chuàng)建緩存 , 通過商品ID和商品對象緩存聚合成列表返回給前端。

偽代碼如下:

c3cb0982-043c-11ee-90ce-dac502259ad0.png

核心流程:

1、從數據庫中查詢分頁 ID 列表

//從數據庫中查詢分頁商品ID列表
ListproductIdList=queryProductIdListFromDabaBase(
param,
page,
size);

對應的 SQL 類似:

SELECTidFROMproducts
ORDERBYidASC
LIMIT(page-1)*size,size

2、批量從緩存中獲取商品對象

MapcachedProductMap=cacheUtils.mget(productIdList);

假如我們使用本地緩存,直接一條一條從本地緩存中聚合也極快。

假如我們使用分布式緩存,Redis 天然支持批量查詢的命令 ,比如 mget ,hmget 。

3、組裝沒有命中的商品ID

ListnoHitIdList=newArrayList<>(cachedProductMap.size());
for(LongproductId:productIdList){
if(!cachedProductMap.containsKey(productId)){
noHitIdList.add(productId);
}
}

因為緩存中可能因為過期或者其他原因導致緩存沒有命中的情況,所以我們需要找到哪些商品沒有在緩存里。

4、批量從數據庫查詢未命中的商品信息列表,重新加載到緩存

首先從數據庫里批量 查詢出未命中的商品信息列表 ,請注意是批量

ListnoHitProductList=batchQuery(noHitIdList);

參數是未命中緩存的商品ID列表,組裝成對應的 SQL,這樣性能更快 :

SELECT*FROMproductsWHEREidIN
(1,
2,
3,
4);

然后這些未命中的商品信息存儲到緩存里 , 使用 Redis 的 mset 命令。

//將沒有命中的商品加入到緩存里
MapnoHitProductMap=
noHitProductList.stream()
.collect(
Collectors.toMap(Product::getId,Function.identity())
);
cacheUtils.mset(noHitProductMap);
//將沒有命中的商品加入到聚合map里
cachedProductMap.putAll(noHitProductMap);

5、 遍歷商品ID列表,組裝對象列表

for(LongproductId:productIdList){
Productproduct=cachedProductMap.get(productId);
if(product!=null){
result.add(product);
}
}

當前方案里,緩存都有命中的情況下,經過兩次網絡 IO ,第一次數據庫查詢 IO ,第二次 Redis 查詢 IO , 性能都會比較好。

所有的操作都是批量操作,就算有緩存沒有命中的情況,整體速度也較快。

查詢對象ID列表,再緩存每個對象條目 “ 這個方案比較靈活,當我們查詢對象ID列表 ,可以不限于數據庫,還可以是搜索引擎,Redis 等等。

下圖是開源中國的搜索流程:

c42fe136-043c-11ee-90ce-dac502259ad0.png

精髓在于:搜索的分頁結果只包含業(yè)務對象 ID ,對象的詳細資料需要從緩存 + MySQL 中獲取。

3 緩存對象ID列表,同時緩存每個對象條目

筆者曾經重構過類似朋友圈的服務,進入班級頁面 ,瀑布流的形式展示班級成員的所有動態(tài)。

c443a2e8-043c-11ee-90ce-dac502259ad0.png

我們使用推模式將每一條動態(tài) ID 存儲在 Redis ZSet 數據結構中 。Redis ZSet 是一種類型為有序集合的數據結構,它由多個有序的唯一的字符串元素組成,每個元素都關聯(lián)著一個浮點數分值。

ZSet 使用的是 member -> score 結構 :

member : 成員,也是默認的第二排序維度( score 相同時,Redis 以 member 的字典序排列)

score : 分值,存儲類型是 double

c46dec4c-043c-11ee-90ce-dac502259ad0.png

如上圖所示:ZSet 存儲動態(tài) ID 列表 , member 的值是動態(tài)編號 , score 值是創(chuàng)建時間

通過 ZSet 的 ZREVRANGE 命令 就可以實現分頁的效果。

ZREVRANGE 是 Redis 中用于有序集合(sorted set)的命令之一,它用于按照成員的分數從大到小返回有序集合中的指定范圍的成員。

c48084d8-043c-11ee-90ce-dac502259ad0.png

為了達到分頁的效果,傳遞如下的分頁參數 :

c496a452-043c-11ee-90ce-dac502259ad0.png

通過 ZREVRANGE 命令,我們可以查詢出動態(tài) ID 列表。

查詢出動態(tài) ID 列表后,還需要緩存每個動態(tài)對象條目,動態(tài)對象包含了詳情,評論,點贊,收藏這些功能數據 ,我們需要為這些數據提供單獨做緩存配置。

c4af9ff2-043c-11ee-90ce-dac502259ad0.png

無論是查詢緩存,還是重新寫入緩存,為了提升系統(tǒng)性能,批量操作效率更高。

緩存對象結構簡單,使用 mget 、hmget 命令;若結構復雜,可以考慮使用 pipleline,Lua 腳本模式 。 筆者選擇的批量方案是 Redis 的 pipleline 功能。

我們再來模擬獲取動態(tài)分頁列表的流程:

使用 ZSet 的 ZREVRANGE 命令 ,傳入分頁參數,查詢出動態(tài) ID 列表 ;

傳遞動態(tài) ID 列表參數,通過 Redis 的 pipleline 功能從緩存中批量獲取動態(tài)的詳情,評論,點贊,收藏這些功能數據 ,組裝成列表 。

4 總結

本文介紹了實現分頁列表緩存的三種方式:

直接緩存分頁列表結果

查詢對象ID列表,只緩存每個對象條目

緩存對象ID列表,同時緩存每個對象條目

這三種方式是一層一層遞進的,要訣是:細粒度的控制緩存批量加載對象





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 存儲器
    +關注

    關注

    38

    文章

    7453

    瀏覽量

    163608
  • SQL
    SQL
    +關注

    關注

    1

    文章

    760

    瀏覽量

    44078
  • MYSQL數據庫
    +關注

    關注

    0

    文章

    95

    瀏覽量

    9382
  • Redis
    +關注

    關注

    0

    文章

    371

    瀏覽量

    10846

原文標題:分頁列表緩存就該這樣設計!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    多列列表分頁顯示

    現在希望對多列列表框做如下操作:從數據庫中輸入10000行數據導入多列列表框,要求多列列表框能夠分100頁顯示,每頁顯示100條數據,且能夠利用數值控件進行翻頁。
    發(fā)表于 11-04 11:15

    mysql分頁

    第7章 分頁程序(4課時)
    發(fā)表于 04-30 11:51

    JPA分頁查詢的常用方法

    JPA分頁查詢與條件分頁查詢
    發(fā)表于 10-23 17:10

    請問mybatis分頁插件有哪些使用案列?

    mybatis分頁插件使用案例
    發(fā)表于 11-09 06:21

    聊聊環(huán)形緩存在單片機程序中的使用

    片頭因為環(huán)形緩存在單片機程序中的使用是非常有效的,非常有用的,關于這個話題在此專門開一文章來聊聊這個話題。環(huán)形緩存的用途主要是來緩存數據,而需要緩存
    發(fā)表于 12-06 08:29

    XML數據分頁索引技術研究

    對海量XML文檔的索引查詢技術進行研究,提出一種XML數據分頁索引查詢實現方法。該方法把頁面元素標記數量作為數據分頁依據,建立XML數據的分頁索引,并在該分頁索引上實現XPath
    發(fā)表于 03-31 10:07 ?10次下載

    Jquery簡單分頁實現

    這篇文章主要介紹了Jquery簡單分頁實現方法,實例分析了jquery分頁的相關實現技巧,具有一定參考借鑒價值,需要的朋友可以參考下。
    發(fā)表于 11-28 11:55 ?1076次閱讀

    串口 單片機 文件_從環(huán)形緩存到流水緩存在STM32單片機的應用

    片頭因為環(huán)形緩存在單片機程序中的使用是非常有效的,非常有用的,關于這個話題在此專門開一文章來聊聊這個話題。環(huán)形緩存的用途主要是來緩存數據,而需要緩存
    發(fā)表于 11-23 18:21 ?15次下載
    串口 單片機  文件_從環(huán)形<b class='flag-5'>緩存</b>到流水<b class='flag-5'>緩存</b>在STM32單片機的應用

    如何優(yōu)化MySQL百萬數據的深分頁問題

    我們日常做分頁需求時,一般會用limit實現,但是當偏移量特別大的時候,查詢效率就變得低下。本文將分四個方案,討論如何優(yōu)化MySQL百萬數據的深分頁問題,并附上最近優(yōu)化生產慢SQL的實戰(zhàn)案例。
    的頭像 發(fā)表于 04-06 15:12 ?1865次閱讀

    聊聊緩存數據庫一致性

    在云服務中,緩存是極其重要的一點。所謂緩存,其實是一個高速數據存儲層。當緩存存在后,日后再次請求該數據就會直接訪問緩存,提升數據訪問的速度。
    的頭像 發(fā)表于 01-30 17:41 ?739次閱讀

    圖文詳解Linux分頁機制

    分頁機制是 80x86 內存管理機制的第二種機制,分段機制用于把虛擬地址轉換為線性地址,而分頁機制用于把線性地址轉換為物理地址。
    發(fā)表于 05-30 09:10 ?429次閱讀
    圖文詳解Linux<b class='flag-5'>分頁</b>機制

    聊聊本地緩存和分布式緩存

    本地緩存 :應用中的緩存組件,緩存組件和應用在同一進程中,緩存的讀寫非常快,沒有網絡開銷。但各應用或集群的各節(jié)點都需要維護自己的單獨緩存,無
    發(fā)表于 06-11 15:12 ?811次閱讀
    <b class='flag-5'>聊聊</b>本地<b class='flag-5'>緩存</b>和分布式<b class='flag-5'>緩存</b>

    聊聊如何實現一種閃存緩存設計

    許多web服務需要對數十億個小對象實現快速訪問,而每個小對象只有幾百個字節(jié)。為了實現這一點同時考慮實際生產效益,緩存系統(tǒng)必須做到同時低成本,大容量與高性能。
    的頭像 發(fā)表于 08-29 09:01 ?686次閱讀
    <b class='flag-5'>聊聊</b>如何實現一種閃存<b class='flag-5'>緩存</b>設計

    mybatis邏輯分頁和物理分頁的區(qū)別

    MyBatis是一個開源的Java持久層框架,它與其他ORM(對象關系映射)框架相比,具有更加靈活和高性能的特點。MyBatis提供了兩種分頁方式,即邏輯分頁和物理分頁。在本文中,我們將詳細介紹
    的頭像 發(fā)表于 12-03 14:54 ?864次閱讀

    聊聊緩存擊穿的解決方法

    緩存擊穿,Redis中的某個熱點key不存在或者過期,但是此時有大量的用戶訪問該key。比如xxx直播間優(yōu)惠券搶購、xxx商品活動,這時候大量用戶會在某個時間點一同訪問該熱點事件。但是可能
    的頭像 發(fā)表于 10-23 13:54 ?140次閱讀