Redis-07-常見Redis使用場景

文章目錄

    • 01.緩存數據(Cache)
    • 02.布式鎖(Distributed Lock)
    • 03.計數器(Counter)
    • 04.排行榜(Leaderboard)
    • 05.消息隊列(Message Queue)
    • 06.限流(Rate Limiting)
    • 07.會話存儲(Session Storage)
    • 08.地理位置(Geo)
    • 09. 發布訂閱(Pub/Sub)

01.緩存數據(Cache)

將數據庫查詢結果緩存到Redis,減輕數據庫壓力

示例:在電商網站中,可以將熱門商品的信息存儲在Redis中,當用戶訪問這些商品時,首先從Redis中讀取,如果Redis中沒有,再從數據庫中讀取并更新到Redis中。

@Service
public class ProductService {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String PRODUCT_CACHE_PREFIX = "product:";public Product getProductById(Long id) {String cacheKey = PRODUCT_CACHE_PREFIX + id;// 1. 先查緩存Product product = (Product) redisTemplate.opsForValue().get(cacheKey);if (product != null) {return product;}// 2. 緩存沒有則查數據庫product = productRepository.findById(id).orElse(null);if (product != null) {// 3. 寫入緩存,設置過期時間redisTemplate.opsForValue().set(cacheKey, product, 30, TimeUnit.MINUTES);}return product;}
}

02.布式鎖(Distributed Lock)

在分布式系統中,Redis可以用于實現分布式鎖,可以在分布式系統中協調多節點對共享資源的訪問,確保操作的原子性。

示例:分布式系統中用戶購買商品,同一時間只能一個用戶創建訂單。

@Service
public class OrderService {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String LOCK_PREFIX = "lock:";private static final long LOCK_EXPIRE = 30; // 30秒public boolean createOrder(Long productId, Long userId) {String lockKey = LOCK_PREFIX + "order_" + productId;String requestId = UUID.randomUUID().toString();try {// 嘗試獲取鎖Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, LOCK_EXPIRE, TimeUnit.SECONDS);if (Boolean.TRUE.equals(locked)) {// 獲取鎖成功,執行業務邏輯return doCreateOrder(productId, userId);}return false;} finally {// 釋放鎖 - 使用Lua腳本保證原子性String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(lockKey),requestId);}}
}

03.計數器(Counter)

Redis的原子增減操作非常適合用于計數器和排行榜應用,如社交媒體的點贊數、閱讀數、排名等。

示例:實現文章閱讀量、商品點擊量等統計

@Service
public class ArticleService {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String VIEW_COUNT_PREFIX = "article:view:";// 增加閱讀量public void incrementViewCount(Long articleId) {String key = VIEW_COUNT_PREFIX + articleId;redisTemplate.opsForValue().increment(key);}// 獲取閱讀量public Long getViewCount(Long articleId) {String key = VIEW_COUNT_PREFIX + articleId;String count = redisTemplate.opsForValue().get(key);return count == null ? 0L : Long.parseLong(count);}// 批量獲取閱讀量public Map<Long, Long> getBatchViewCounts(List<Long> articleIds) {List<String> keys = articleIds.stream().map(id -> VIEW_COUNT_PREFIX + id).collect(Collectors.toList());List<String> counts = redisTemplate.opsForValue().multiGet(keys);Map<Long, Long> result = new HashMap<>();for (int i = 0; i < articleIds.size(); i++) {Long articleId = articleIds.get(i);String count = counts.get(i);result.put(articleId, count == null ? 0L : Long.parseLong(count));}return result;}
}

04.排行榜(Leaderboard)

Redis的原子增減操作非常適合用于計數器和排行榜應用,如社交媒體的點贊數、閱讀數、排名等。

示例:實現商品銷量排行、游戲積分排行等

@Service
public class RankingService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String SALES_RANK_KEY = "product:sales:rank";// 更新商品銷量public void updateProductSales(Long productId, int sales) {redisTemplate.opsForZSet().add(SALES_RANK_KEY, productId, sales);}// 獲取銷量前N的商品public List<Long> getTopSalesProducts(int topN) {Set<Object> productIds = redisTemplate.opsForZSet().reverseRange(SALES_RANK_KEY, 0, topN - 1);return productIds.stream().map(id -> Long.parseLong(id.toString())).collect(Collectors.toList());}// 獲取商品排名public Long getProductRank(Long productId) {// ZREVRANK返回的是從0開始的排名Long rank = redisTemplate.opsForZSet().reverseRank(SALES_RANK_KEY, productId);return rank == null ? null : rank + 1; // 轉換為1-based排名}// 獲取商品銷量public Double getProductSales(Long productId) {return redisTemplate.opsForZSet().score(SALES_RANK_KEY, productId);}
}

05.消息隊列(Message Queue)

Redis支持發布/訂閱模式,可以用作輕量級的消息隊列系統,用于異步任務處理、事件處理等。

示例:實現簡單的消息隊列系統

@Service
public class MessageQueueService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String QUEUE_KEY = "message:queue";// 發送消息public void sendMessage(String message) {redisTemplate.opsForList().rightPush(QUEUE_KEY, message);}// 接收消息 - 阻塞式public String receiveMessage() throws InterruptedException {return (String) redisTemplate.opsForList().leftPop(QUEUE_KEY, 30, TimeUnit.SECONDS);}// 批量發送消息public void batchSendMessages(List<String> messages) {redisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (String message : messages) {connection.listCommands().rPush(QUEUE_KEY.getBytes(), message.getBytes());}return null;});}
}

06.限流(Rate Limiting)

Redis 適合用于限流(Rate Limiting)場景。限流的目的是控制某個操作在特定時間內的訪問頻率,比如 API 請求、短信發送、登錄嘗試等。Redis 的原子操作和高效性能使其成為實現限流的理想工具。

示例:實現API訪問限流

@Service
public class RateLimitService {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String RATE_LIMIT_PREFIX = "rate_limit:";/*** 限流檢查* @param key 限流key(如用戶ID或IP)* @param limit 時間窗口內允許的最大請求數* @param windowInSeconds 時間窗口大小(秒)* @return true-允許訪問 false-拒絕訪問*/public boolean allowRequest(String key, int limit, int windowInSeconds) {String redisKey = RATE_LIMIT_PREFIX + key;// 使用Lua腳本保證原子性String script = "local current = redis.call('incr', KEYS[1])\n" +"if current == 1 then\n" +"    redis.call('expire', KEYS[1], ARGV[1])\n" +"end\n" +"return current <= tonumber(ARGV[2])";Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(redisKey),String.valueOf(windowInSeconds),String.valueOf(limit));return result != null && result == 1;}
}

07.會話存儲(Session Storage)

在Web應用中,Redis常用于存儲用戶會話信息,如登錄狀態、購物車內容等。由于其快速的讀寫速度,Redis非常適合這種需要頻繁訪問和更新的數據。

示例:分布式系統中的會話存儲

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) // 30分鐘過期
public class RedisSessionConfig {// Spring Session會自動配置Redis連接
}// 使用示例
@RestController
public class UserController {@PostMapping("/login")public String login(@RequestParam String username, HttpSession session) {// 存儲用戶信息到sessionsession.setAttribute("username", username);return "登錄成功";}@GetMapping("/userinfo")public String getUserInfo(HttpSession session) {// 從session獲取用戶信息String username = (String) session.getAttribute("username");return "當前用戶: " + (username != null ? username : "未登錄");}
}

08.地理位置(Geo)

Redis支持地理空間數據,可以用于構建地理位置應用,如附近的人、地點推薦等功能。

示例:實現附近的人、附近的商家等功能

@Service
public class LocationService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String GEO_KEY = "shop:locations";// 添加商家位置public void addShopLocation(Long shopId, double lng, double lat) {redisTemplate.opsForGeo().add(GEO_KEY, new Point(lng, lat), shopId.toString());}// 獲取附近商家public List<Long> getNearbyShops(double lng, double lat, double radius) {Circle within = new Circle(new Point(lng, lat),  new Distance(radius, Metrics.KILOMETERS));RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending().limit(10);GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo().radius(GEO_KEY, within, args);return results.getContent().stream().map(geoResult -> Long.parseLong(geoResult.getContent().getName().toString())).collect(Collectors.toList());}// 計算兩個商家距離public Distance calculateDistance(Long shopId1, Long shopId2) {List<String> ids = Arrays.asList(shopId1.toString(), shopId2.toString());return redisTemplate.opsForGeo().distance(GEO_KEY, ids.get(0), ids.get(1), Metrics.KILOMETERS);}
}

09. 發布訂閱(Pub/Sub)

示例:實現實時消息通知、事件廣播等

// 配置消息監聽容器
@Configuration
public class RedisPubSubConfig {@Beanpublic RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,MessageListenerAdapter orderEventListenerAdapter) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.addMessageListener(orderEventListenerAdapter, new ChannelTopic("order:events"));return container;}@Beanpublic MessageListenerAdapter orderEventListenerAdapter(OrderEventListener listener) {return new MessageListenerAdapter(listener, "handleMessage");}
}// 消息監聽器
@Component
public class OrderEventListener {public void handleMessage(OrderEvent event) {switch (event.getType()) {case CREATED:handleOrderCreated(event);break;case PAID:handleOrderPaid(event);break;// 其他事件處理...}}private void handleOrderCreated(OrderEvent event) {// 處理訂單創建事件}
}// 消息發布服務
@Service
public class OrderEventPublisher {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public void publishOrderEvent(OrderEvent event) {redisTemplate.convertAndSend("order:events", event);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76158.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76158.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76158.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

長亭2月公開賽Web-ssrfme

環境部署 拉取環境報錯&#xff1a; 可以嘗試拉取一下ubuntu:16.04&#xff0c;看是否能拉取成功 將wersion&#xff1a;"3"刪掉 我拉去成功之后&#xff0c;再去拉取環境&#xff0c;成功&#xff01; 訪問環境 測試ssrf 源碼 <?php highlight_file(__file__…

RK3506+net9+VS2022跨平臺調試C#程序

下載GetVsDbg.sh &#xff0c;這腳本會下載一個壓縮包&#xff0c;然后解壓縮&#xff0c;設置x權限等等。但是目標板子連不上&#xff0c;就想辦法獲取到下載路徑&#xff0c;修改這個腳本&#xff0c;顯示這個下載鏈接后&#xff0c;復制一下&#xff0c;用電腦下下來 修改好…

MySQL GTID集合運算函數總結

MySQL GTID 有一些運算函數可以幫助我們在運維工作中提高運維效率。 1 GTID內置函數 MySQL 包含GTID_SUBSET、GTID_SUBTRACT、WAIT_FOR_EXECUTED_GTID_SET、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 4個內置函數&#xff0c;用于GTID集合的基本運算。 1.1 GTID_SUBSET(set1,set2) …

Java學習手冊:Java內存模型

Java內存模型&#xff08;Java Memory Model&#xff0c;簡稱JMM&#xff09;是Java語言中用于定義線程之間如何共享和操作內存的規范。它描述了Java程序中變量的內存可見性行為&#xff0c;并定義了線程之間的通信規則。理解Java內存模型對于編寫正確的并發程序至關重要。本文…

神經網絡優化 - 高維變量的非凸優化

網絡優化是指尋找一個神經網絡模型來使得經驗(或結構)風險最小化的過程&#xff0c;包括模型選擇以及參數學習等。 關于經驗風險最小化和結構風險最小化&#xff0c;請參考博文&#xff1a; 認識機器學習中的經驗風險最小化準則_樣本均值近似與經驗風險最小化的關系-CSDN博客…

Python自學第2天:條件語句,循環語句

條件語句 1.條件判斷 score 60 if score > 90:print("優秀") elif score > 60:print("及格") else:print("不及格") 注意&#xff1a; 1、每個條件后面要使用冒號 :&#xff0c;表示接下來是滿足條件后要執行的語句塊。2、使用縮進來劃…

C# dll 打包進exe

Framework4.x推薦使用 Costura.Fody 1. 安裝 NuGet 包 Install-Package Costura.Fody工程自動生成packages文件夾&#xff0c;300M左右。生成FodyWeavers.xml、FodyWeavers.xsd文件。 2. 自動嵌入 編譯后&#xff0c;所有依賴的 DLL 會被自動嵌入到 EXE 中。 運行時自動解壓…

Redis之緩存更新策略

緩存更新策略 文章目錄 緩存更新策略一、策略對比二、常見的緩存更新策略三、如何選擇策略四、實際應用示例五、使用 Cache-Aside TTL 的方式&#xff0c;實現緩存商鋪信息詳情1.引入StringRedisTemplate2.將查詢商鋪信息加入緩存3.更新商鋪信息時移除緩存總結 六、注意事項 一…

【工具變量】各地級市人口集聚及多中心程度數據集(2000-2023年)

多中心程度描述的是一個城市或區域內多個功能性中心的存在和分布情況&#xff1b;人口集聚度是指一定區域內人口的集中程度&#xff0c;它反映了區域內人口分布的不均衡性&#xff0c;這兩個概念相互關聯&#xff0c;通過分析地級市的多中心程度及人口集聚度可以幫助研究者理解…

函數對象-C++

1.定義 2.特點 、 1.解釋第一句 #include<stdio.h> using namespace std; #include<string> #include<map> #include <iostream> class print { public:void operator()(string s){cout << s << endl;} }; int main() {print print;pri…

Apifox下載安裝與使用

一、Apifox下載 官網地址:Apifox 點擊"免費下載",即可進行下載。 二、Apifox安裝 雙擊安裝文件即可安裝。

Python與圖像處理:從基礎操作到智能應用的全面解析

目錄 一、Python圖像處理的三大核心優勢 1.1 生態庫矩陣支撐 1.2 開發效率革命 1.3 跨領域協同能力 二、六大核心處理技術詳解 2.1 圖像基礎操作 2.2 圖像增強技術 2.3 特征提取算法 2.4 目標檢測技術 2.5 圖像分割技術 2.6 圖像生成技術 三、實戰案例&#xff1a;智…

雙 Token 與 單 Token 優缺點

雙Token與單Token認證機制對比 在Web應用開發中&#xff0c;身份認證和授權是保障系統安全的核心環節。隨著技術演進&#xff0c;基于Token的認證機制逐漸取代傳統Session方案&#xff0c;而雙Token與單Token架構的選型爭議也日益成為開發者關注的焦點。本文將從技術原理、優缺…

Spring Boot管理Spring MVC

Spring Boot真正的核心功能是自動配置和快速整合&#xff0c;通常Spring Boot應用的前端MVC框架依然使用Spring MVC。Spring Boot提供的spring-boot-starter-web啟動器嵌入了Spring MVC的依賴&#xff0c;并為Spring MVC提供了大量自動配置&#xff0c;可以適用于大多數Web開發…

1.凸包、極點、極邊基礎概念

目錄 1.凸包 2.調色問題 3.極性(Extrem) 4.凸組合(Convex Combination) 5.問題轉化(Strategy)?編輯 6.In-Triangle test 7.To-Left-test 8.極邊&#xff08;Extream Edges&#xff09; 1.凸包 凸包就是上面藍色皮筋圍出來的范圍 這些釘子可以轉換到坐標軸中&#xff0…

《如何用 Function 實現動態配置驅動的處理器注冊機制?》

大家好呀&#xff01;&#x1f44b; 今天我們來聊聊一個超實用的技術話題 - 如何用Java的Function接口實現動態配置驅動的處理器注冊機制。聽起來很高大上&#xff1f;別擔心&#xff0c;我會用最簡單的方式講清楚&#xff01;&#x1f60a; 一、為什么要用Function實現處理器…

【最新版】蕓眾商城獨立版源碼 425+插件 全新后臺框架

一.系統介紹 蕓眾商城系統最新版 已經更新425全插件版&#xff0c;一套系統支持各種新零售、商城、模式&#xff0c;天天美麗鏈動商城。不要相信那些外面的舊版本。舊版本等于是廢品&#xff0c;無法小程序運營的&#xff0c;框架還是舊的&#xff01; 蕓眾系統最新版 服務器可…

java 設計模式之單例模式

簡介 單例模式&#xff1a;一個類有且僅有一個實例&#xff0c;該類負責創建自己的對象&#xff0c;同時確保只有一個對象被創建。 特點&#xff1a;類構造器私有、持有自己實例、對外提供獲取實例的靜態方法。 單例模式的實現方式 餓漢式 類被加載時&#xff0c;就會實例…

Milvus 索引如何選擇

以下是幾種索引類型的特點及適用場景&#xff0c;可據此選擇&#xff1a; AUTOINDEX 特點&#xff1a;數據庫自動選擇合適索引類型&#xff0c;無需深入了解索引細節。適用場景&#xff1a;對索引知識了解有限&#xff0c;或不確定哪種索引適合當前數據和查詢需求&#xff0c…

CentOS 7 安裝教程

準備&#xff1a; 軟件&#xff1a;VMware Workstation 鏡像文件&#xff1a;CentOS-7-x86_64-bin-DVD1.iso &#xff08;附&#xff1a;教程較為詳細&#xff0c;注釋較多&#xff0c;故將操作的選項進行了加粗字體顯示。&#xff09; 1、文件–新建虛擬機–自定義 2、硬盤…