那曲檬骨新材料有限公司

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

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

3天內不再提示

Redis工具集的實現和使用

jf_ro2CN3Fa ? 來源:稀土掘金技術社區 ? 2023-12-03 17:32 ? 次閱讀

1 前言

Redis 基本上是互聯網公司必備的工具了,Redis的應用場景實在太多了,但是有很多相似的功能如果每個項目都要實現一遍就顯得太麻煩了,所以為了方便,我打算開發一個基于 Redis 的工具集,盡量做到開箱即用。

2 目前實現功能

這個工具集并沒有開發完成,實現了部分功能,如下圖

8577182e-91bd-11ee-939d-92fbcf53809c.png

簡單介紹下已經實現的模塊:

common : 整個項目公共模塊,比如AOP工具等;

delay: Redis實現的延遲隊列;

lock: Redis實現的分布式鎖;

mq: Redis實現消息隊列;

query: Redis實現分頁模糊查詢;

web: Redis實現web相關的功能;

duplicate :防止重復提交;

以上的這些模塊都是已經實現的了,還有 社交、限流、冪等相關功能后面會陸續實現。

3 如何使用

1.引入 Maven 依賴

目前可以下載代碼上傳到自己的私服或者本地倉庫,后面會推到 Maven 中央倉庫


cn.org.wangchangjiu
redis-util-spring-boot-starter
1.0.0-SNAPSHOT

2.配置文件(application.yaml)開啟各模塊功能開關

redis:
util:
mq:
enable:true
delay:
enable:true

3.實現消息發送者

MQ消息發送:

858caa4a-91bd-11ee-939d-92fbcf53809c.png

延遲消息發送:

85a23932-91bd-11ee-939d-92fbcf53809c.png

4.實現消息監聽器

MQ消息監聽器:

85c4f9fe-91bd-11ee-939d-92fbcf53809c.png

延遲消息監聽器:

85d4b9d4-91bd-11ee-939d-92fbcf53809c.png

4 MQ和delay實現細節

MQ實現細節

容器啟動時,簡單來說就是通過springboot自動裝配,創建一些Bean,如下圖:

85f415c2-91bd-11ee-939d-92fbcf53809c.png

值得注意的是,springboot3.X 自動裝配方式有點變化,需要創建文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,文件內容就直接寫 自動配置類

8611a2cc-91bd-11ee-939d-92fbcf53809c.png

RedisUtilAutoConfiguration 主自動裝配類會 import 各個模塊的自動裝配類:

8621012c-91bd-11ee-939d-92fbcf53809c.png

我們以 RedisStreamAutoConfiguration 為例:

864536d2-91bd-11ee-939d-92fbcf53809c.png

該裝配類生效需要顯示打開,然后就是創建各種Bean。

最主要的Bean有:

RedisMessageConsumerManager:

865c99da-91bd-11ee-939d-92fbcf53809c.png

該Bean實現了 BeanPostProcessor 接口,主要作用是,獲取被注解 RedisMessageListener 修飾的方法,把信息封裝在 RedisMessageConsumerContainer 對象里,方便后面反射調用。

8668f98c-91bd-11ee-939d-92fbcf53809c.png

StreamMessageListenerContainer:

這個Bean主要是做 redis MQ 的配置,比如配置:一次最多獲取多少條消息、沒有消息時阻塞時間、執行任務的executor、錯誤處理器、以及消費組、是否自動ACK等配置,具體代碼如下:

@Bean(initMethod="start",destroyMethod="stop")
@DependsOn("redisMessageConsumerManager")
@ConditionalOnMissingBean
publicStreamMessageListenerContainer>streamMessageListenerContainer(@AutowiredRedisMessageConsumerManagerredisMessageConsumerManager,
@AutowiredRedisConnectionFactoryredisConnectionFactory,
@AutowiredErrorHandlererrorHandler){
MyRedisStreamProperties.Optionsoptions=myRedisStreamProperties.getOptions();
StreamMessageListenerContainer.StreamMessageListenerContainerOptions>containerOptions=
StreamMessageListenerContainer.StreamMessageListenerContainerOptions
.builder()
//一次最多獲取多少條消息
.batchSize(options.getBatchSize())
//運行Stream的polltask
.executor(getStreamMessageListenerExecutor())
//Stream中沒有消息時,阻塞多長時間,需要比`spring.redis.timeout`的時間小
.pollTimeout(options.getPollTimeout())
//獲取消息的過程或獲取到消息給具體的消息者處理的過程中,發生了異常的處理
.errorHandler(errorHandler)
.build();

StreamMessageListenerContainer>streamMessageListenerContainer=
StreamMessageListenerContainer.create(redisConnectionFactory,containerOptions);

//獲取被RedisMessageListener注解修飾的bean
MapconsumerContainerGroups=
redisMessageConsumerManager.getConsumerContainerGroups();

//循環遍歷,創建消費組
consumerContainerGroups.forEach((groupQueue,redisMessageConsumerContainer)->{
String[]groupQueues=groupQueue.split("#");

//創建消費組
createGroups(groupQueues);

RedisMessageListenerredisMessageListener=redisMessageConsumerContainer.getRedisMessageListener();
if(!redisMessageListener.useGroup()){
//獨立消費不使用組
streamMessageListenerContainer.receive(StreamOffset.fromStart(groupQueues[1]),newDefaultGroupStreamListener(redisMessageConsumerContainer));
}else{
//消費組消費
if(redisMessageListener.autoAck()){
//自動ACK
streamMessageListenerContainer.receiveAutoAck(Consumer.from(groupQueues[0],"consumer:"+UUID.randomUUID()),
StreamOffset.create(groupQueues[1],ReadOffset.lastConsumed()),newDefaultGroupStreamListener(redisMessageConsumerContainer));
}else{
//手動ACK
streamMessageListenerContainer.receive(Consumer.from(groupQueues[0],"consumer:"+UUID.randomUUID()),
StreamOffset.create(groupQueues[1],ReadOffset.lastConsumed()),newDefaultGroupStreamListener(redisMessageConsumerContainer));
}
}
});
returnstreamMessageListenerContainer;
}

/**
*創建消費組
*@paramgroupQueues
*/
privatevoidcreateGroups(String[]groupQueues){
//判斷是否存在隊列Key
if(stringRedisTemplate.hasKey(groupQueues[1])){
//獲取消費組沒有則創建
StreamInfo.XInfoGroupsgroups=stringRedisTemplate.opsForStream().groups(groupQueues[1]);
if(groups.isEmpty()){
stringRedisTemplate.opsForStream().createGroup(groupQueues[1],groupQueues[0]);
}else{
AtomicBooleanexists=newAtomicBoolean(false);
groups.forEach(xInfoGroup->{
if(xInfoGroup.groupName().equals(groupQueues[0])){
exists.set(true);
}
});
if(!exists.get()){
stringRedisTemplate.opsForStream().createGroup(groupQueues[1],groupQueues[0]);
}
}
}else{
stringRedisTemplate.opsForStream().createGroup(groupQueues[1],groupQueues[0]);
}
}

//todo后面這個線程池也可以交由用戶配置
privateExecutorgetStreamMessageListenerExecutor(){
AtomicIntegerindex=newAtomicInteger(1);
intprocessors=Runtime.getRuntime().availableProcessors();
ThreadPoolExecutorexecutor=newThreadPoolExecutor(processors,processors,0,TimeUnit.SECONDS,
newLinkedBlockingDeque<>(),r->{
Threadthread=newThread(r);
thread.setName("async-stream-consumer-"+index.getAndIncrement());
thread.setDaemon(true);
returnthread;
});
returnexecutor;
}

發送消息流程:

8680490c-91bd-11ee-939d-92fbcf53809c.png

redis 延遲隊列的實現原理和這個差不多,主要是 redission延遲隊列 + 自定義注解 + 反射,代碼都差不多。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4825

    瀏覽量

    69043
  • 隊列
    +關注

    關注

    1

    文章

    46

    瀏覽量

    10927
  • Redis
    +關注

    關注

    0

    文章

    378

    瀏覽量

    10939

原文標題:為了方便開發,我打算實現一個Redis 工具集

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

收藏 人收藏

    評論

    相關推薦

    Redis的LRU實現和應用

    在編程中,計數器是一種基本但強大的工具,用于跟蹤和管理數據和資源。本文將深入探討不同類型的計數器的應用,從Redis的LRU(最近最少使用)緩存淘汰算法的實現,到如何在內存受限的環境中有效地使用計數器,再到普通計數器的巧妙應用。
    的頭像 發表于 12-15 09:24 ?639次閱讀

    Redis Stream應用案例

    的基本使用介紹和設計理念可以看我之前的一篇文章(Redis Stream簡介)。Redis Stream本質上是在Redis內核上(非Redis Module)
    發表于 06-26 17:15

    centos7 redis的安裝

    centos7 redis 使用,查看Redis工具(安裝、添加權限驗證、添加開機自啟)
    發表于 05-14 17:13

    Redis Cluster的基本原理及實現細節

    Redis Cluster的基本原理和架構 Redis Cluster是分布式Redis實現。隨著Redis版本的更替,以及各種已知bug
    發表于 09-28 19:09 ?0次下載
    <b class='flag-5'>Redis</b> Cluster的基本原理及<b class='flag-5'>實現</b>細節

    Java 使用Redis緩存工具的詳細解說

    本文是關于Java 使用Redis緩存工具的詳細解說。詳細步驟請看下文
    的頭像 發表于 02-09 14:10 ?7923次閱讀
    Java 使用<b class='flag-5'>Redis</b>緩存<b class='flag-5'>工具</b>的詳細解說

    Windows環境下使用Redis緩存工具的圖文詳細方法

    Windows環境下使用Redis緩存工具的圖文詳細方法。Redis 是一個高性能的key-value數據庫。redis的出現,很大程度補償了memcached這類key/value存
    的頭像 發表于 02-09 14:25 ?4828次閱讀
    Windows環境下使用<b class='flag-5'>Redis</b>緩存<b class='flag-5'>工具</b>的圖文詳細方法

    redis設計與實現

    redis
    發表于 06-20 14:44 ?0次下載

    談談Redis怎樣配置實現主從復制?

    之前總結過redis的持久化機制:深度剖析Redis持久化機制,持久化機制主要解決redis數據單機備份問題;redis的高可用需要考慮數據的多機備份,多機備份通過主從復制來
    發表于 01-31 11:31 ?685次閱讀

    Redis實現限流的三種方式分享

    當然,限流有許多種實現的方式,Redis具有很強大的功能,我用Redis實踐了三種的實現方式,可以較為簡單的實現其方式。
    的頭像 發表于 02-22 09:52 ?1133次閱讀

    Redis官方可視化工具功能強大

    RedisInsight 是一個高顏值,直觀高效的 Redis GUI 管理工具,它可以對 Redis 的內存、連接數、命中率以及正常運行時間進行監控
    的頭像 發表于 04-23 09:55 ?994次閱讀
    <b class='flag-5'>Redis</b>官方可視化<b class='flag-5'>工具</b>功能強大

    Java redis鎖怎么實現

    在Java中實現Redis鎖涉及到以下幾個方面:Redis的安裝配置、Redis連接池的使用、Redis數據結構的選擇、
    的頭像 發表于 12-04 10:47 ?1211次閱讀

    redis集群性能測試工具有哪些

    Redis是一種高性能的內存鍵值存儲系統,它被廣泛應用于各種互聯網應用和大規模的數據存儲中。為了評估Redis在不同場景下的性能,我們需要使用一些性能測試工具來對Redis集群進行基準
    的頭像 發表于 12-04 11:36 ?867次閱讀

    redis hash底層實現原理

    數據結構是如何實現的呢?本文將詳細介紹Redis哈希底層的實現原理。 在Redis中,每個哈希都是由一個類似于字典(Dictionary)的結構實現
    的頭像 發表于 12-04 16:27 ?619次閱讀

    redis持久化機制和如何實現持久化

    File)。 RDB是Redis默認采用的持久化方式,它通過在指定時間間隔內將內存中的數據快照寫入到磁盤的二進制文件中,實現數據的持久化。RDB方式具有高效和緊湊的特點,可以周期性地將數據
    的頭像 發表于 12-05 10:02 ?497次閱讀

    redis數據結構的底層實現

    Redis是一種內存鍵值數據庫,常用于緩存、消息隊列、實時數據分析等場景。它的高性能得益于其精心設計的數據結構和底層實現。本文將詳細介紹Redis常用的數據結構和它們的底層實現
    的頭像 發表于 12-05 10:14 ?664次閱讀
    百家乐分析仪博彩正网| 百家乐官网网络游戏信誉怎么样| 八大胜百家乐官网娱乐城| 嘉禾百家乐官网的玩法技巧和规则 | 百家乐官网具体怎么收费的| 百家乐浴盆博彩通排名| 苹果百家乐的玩法技巧和规则| 大发888娱乐城加盟| 皇冠网vip小说| 百家乐官网视频游戏掉线 | 风水97年农历6月24八字| 百家乐21点游戏| 大发888娱乐游戏技巧| 射阳县| 百家乐官网小揽| 中国百家乐游戏| 赌球网址| 百家乐官网娱乐网站| 涂山百家乐官网的玩法技巧和规则| 广州百家乐赌场| 大发888真人娱乐场网址官网| 大发888娱乐游戏| 金臂百家乐官网开户送彩金| 蓝盾百家乐官网的玩法技巧和规则 | 全讯网网址| 利记娱乐| 百家乐官网出牌规| 百家乐凯时赌场娱乐网规则| 澳门金沙| 现场百家乐官网的玩法技巧和规则 | 大中华百家乐的玩法技巧和规则 | 正安县| 百家乐官网平注法到6568| 包赢百家乐的玩法技巧和规则| 乐众国际娱乐| 新梦想百家乐官网的玩法技巧和规则 | 必博备用网站| 瑞士百家乐官网的玩法技巧和规则| 捷豹百家乐的玩法技巧和规则| 孝昌县| 宝龙百家乐娱乐城|