從零搭建高可用分布式限流組件:設計模式與Redis令牌桶實踐

一、需求背景與設計目標

在分布式系統中,面對突發流量時需要一種精準可控的流量控制手段。我們的組件需要具備:

  1. 多維度限流(用戶/IP/服務節點/自定義表達式)
  2. 分布式環境下精準控制
  3. 開箱即用的Spring Boot Starter集成
  4. 高擴展性的架構設計

二、架構設計全景圖

┌───────────────────┐
│   RateLimiter注解   │
└─────────┬─────────┘│▼
┌───────────────────┐
│     AOP切面處理     │
└─────────┬─────────┘│├──→ IP解析器 (ClientIpRateLimiterKeyResolver)├──→ 用戶解析器 (UserRateLimiterKeyResolver)├──→ 服務節點解析器 (ServerNodeRateLimiterKeyResolver)└──→ 表達式解析器 (ExpressionRateLimiterKeyResolver)│▼
┌───────────────────┐
│ Redis令牌桶算法實現  │
│  (RateLimiterRedisDAO) │
└───────────────────┘

設計亮點

  • ? 策略模式:KeyResolver 實現可插拔的限流維度
  • ? 代理模式:AOP 實現
  • ? 原子性保障:Redis Lua 腳本保證計算原子性

三、核心實現步驟

步驟1:聲明式注解定義(策略入口)


/*** 限流注解** @author dyh*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimiter {/*** 限流的時間,默認為 1 秒*/int time() default 1;/*** 時間單位,默認為 SECONDS 秒*/TimeUnit timeUnit() default TimeUnit.SECONDS;/*** 限流次數*/int count() default 100;/*** 提示信息,請求過快的提示** @see GlobalErrorCodeConstants#TOO_MANY_REQUESTS*/String message() default ""; // 為空時,使用 TOO_MANY_REQUESTS 錯誤提示/*** 使用的 Key 解析器** @see DefaultRateLimiterKeyResolver 全局級別* @see UserRateLimiterKeyResolver 用戶 ID 級別* @see ClientIpRateLimiterKeyResolver 用戶 IP 級別* @see ServerNodeRateLimiterKeyResolver 服務器 Node 級別* @see ExpressionIdempotentKeyResolver 自定義表達式,通過 {@link #keyArg()} 計算*/Class<? extends RateLimiterKeyResolver> keyResolver() default DefaultRateLimiterKeyResolver.class;/*** 使用的 Key 參數*/String keyArg() default "";}

步驟2:策略模式設計Key解析器接口

/*** 限流 Key 解析器接口** @author dyh*/
public interface RateLimiterKeyResolver {/*** 解析一個 Key** @param rateLimiter 限流注解* @param joinPoint  AOP 切面* @return Key*/String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);}

步驟3:實現五種核心策略

  • 默認策略:MD5(方法簽名+參數)
  • IP策略:MD5(方法簽名+參數+IP)
  • 用戶策略:MD5(方法簽名+參數+用戶ID)
  • 服務節點策略:MD5(方法簽名+參數+服務節點地址)
  • 表達式策略:SpEL動態解析參數

3.1 默認策略

/*** 默認(全局級別)限流 Key 解析器,使用方法名 + 方法參數,組裝成一個 Key* <p>* 為了避免 Key 過長,使用 MD5 進行“壓縮”** @author dyh*/
public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());return SecureUtil.md5(methodName + argsStr);}
}

3.2 IP策略

/*** IP 級別的限流 Key 解析器,使用方法名 + 方法參數 + IP,組裝成一個 Key** 為了避免 Key 過長,使用 MD5 進行“壓縮”** @author dyh*/
public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver
{@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());String clientIp = ServletUtils.getClientIP();return SecureUtil.md5(methodName + argsStr + clientIp);}
}

3.3 用戶策略

/*** 用戶級別的限流 Key 解析器,使用方法名 + 方法參數 + userId + userType,組裝成一個 Key** 為了避免 Key 過長,使用 MD5 進行“壓縮”** @author dyh*/
public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());Long userId = WebFrameworkUtils.getLoginUserId();Integer userType = WebFrameworkUtils.getLoginUserType();return SecureUtil.md5(methodName + argsStr + userId + userType);}
}

3.4 服務節點策略

/*** Server 節點級別的限流 Key 解析器,使用方法名 + 方法參數 + IP,組裝成一個 Key* <p>* 為了避免 Key 過長,使用 MD5 進行“壓縮”** @author dyh*/
public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());return SecureUtil.md5(methodName + argsStr + serverNode);}
}

3.5 表達式策略


/*** 基于 Spring EL 表達式的 {@link RateLimiterKeyResolver} 實現類** @author dyh*/
public class ExpressionRateLimiterKeyResolver implements RateLimiterKeyResolver {private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();private final ExpressionParser expressionParser = new SpelExpressionParser();@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {// 獲得被攔截方法參數名列表Method method = getMethod(joinPoint);Object[] args = joinPoint.getArgs();String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);// 準備 Spring EL 表達式解析的上下文StandardEvaluationContext evaluationContext = new StandardEvaluationContext();if (ArrayUtil.isNotEmpty(parameterNames)) {for (int i = 0; i < parameterNames.length; i++) {evaluationContext.setVariable(parameterNames[i], args[i]);}}// 解析參數Expression expression = expressionParser.parseExpression(rateLimiter.keyArg());return expression.getValue(evaluationContext, String.class);}private static Method getMethod(JoinPoint point) {// 處理,聲明在類上的情況MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();if (!method.getDeclaringClass().isInterface()) {return method;}// 處理,聲明在接口上的情況try {return point.getTarget().getClass().getDeclaredMethod(point.getSignature().getName(), method.getParameterTypes());} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}

步驟4:AOP切面編排(流程控制)

import lombok.extern.slf4j.Slf4j; // Lombok日志注解
import cn.hutool.core.util.StrUtil; // 字符串工具類
import org.aspectj.lang.JoinPoint; // AOP連接點
import org.aspectj.lang.annotation.Aspect; // AOP切面注解
import org.aspectj.lang.annotation.Before; // 前置通知注解
import org.springframework.util.Assert; // Spring斷言工具
import java.util.List;
import java.util.Map;
/*** 基于AOP實現的限流切面* 攔截所有使用@RateLimiter注解的方法,實現分布式限流功能* 核心原理:通過Redis實現令牌桶算法控制請求速率** @author dyh*/
@Aspect // 聲明當前類是一個切面
@Slf4j  // 自動生成日志對象
public class RateLimiterAspect {/*** 限流KEY解析器集合(線程安全)* Key: 解析器類類型(Class對象)* Value: 對應的解析器實例*/private final Map<Class<? extends RateLimiterKeyResolver>, RateLimiterKeyResolver> keyResolvers;/*** Redis限流操作組件* 封裝了與Redis交互的限流操作方法*/private final RateLimiterRedisDAO rateLimiterRedisDAO;/*** 構造函數(Spring會自動注入依賴)* @param keyResolvers 所有實現RateLimiterKeyResolver接口的Bean列表* @param rateLimiterRedisDAO Redis限流操作組件*/public RateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {// 將List轉換為Map,方便根據類類型快速查找解析器this.keyResolvers = CollectionUtils.convertMap(keyResolvers, RateLimiterKeyResolver::getClass);this.rateLimiterRedisDAO = rateLimiterRedisDAO;}/*** 前置通知:在標注@RateLimiter的方法執行前進行限流控制* @param joinPoint 連接點信息(包含方法簽名、參數等)* @param rateLimiter 方法上的限流注解實例* @throws ServiceException 當觸發限流時拋出業務異常*/@Before("@annotation(rateLimiter)") // 攔截所有標注@RateLimiter的方法public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {// 根據注解配置的解析器類型獲取對應的解析器實例RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());// 確保解析器存在(避免空指針異常)Assert.notNull(keyResolver, "找不到對應的 RateLimiterKeyResolver");// 生成當前請求的限流唯一標識(不同解析器實現不同策略,如:基于方法、IP、用戶等)String key = keyResolver.resolver(joinPoint, rateLimiter);// 嘗試獲取令牌(true表示獲取成功,false表示觸發限流)boolean success = rateLimiterRedisDAO.tryAcquire(key,                     // 限流KEYrateLimiter.count(),     // 令牌桶容量rateLimiter.time(),      // 時間間隔rateLimiter.timeUnit()); // 時間單位if (!success) { // 觸發限流// 記錄限流日志(INFO級別便于監控)log.info("[beforePointCut][方法({}) 參數({}) 請求過于頻繁]",joinPoint.getSignature().toString(), joinPoint.getArgs());// 優先使用注解中定義的消息,若未配置則使用默認消息String message = StrUtil.blankToDefault(rateLimiter.message(),GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getMsg());// 拋出限流異常(錯誤碼默認429 Too Many Requests)throw new ServiceException(GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getCode(),message);}}
}

步驟5:Redis令牌桶算法實現


// 導入依賴的類庫
import lombok.AllArgsConstructor; // Lombok全參構造函數注解
import org.redisson.api.*; // Redisson客戶端相關接口
import java.util.Objects; // 對象工具類
import java.util.concurrent.TimeUnit; // 時間單位枚舉/*** 基于Redis的分布式限流數據訪問對象* 使用Redisson的RRateLimiter實現令牌桶限流算法* 支持動態配置限流規則,自動處理限流器配置變更** @author 芋道源碼*/
@AllArgsConstructor // 自動生成全參構造函數
public class RateLimiterRedisDAO {/*** Redis鍵格式模板* 完整鍵格式示例:rate_limiter:user_123 (當傳入key為user_123時)* 作用:統一管理限流器在Redis中的存儲結構*/private static final String RATE_LIMITER_KEY_TEMPLATE = "rate_limiter:%s";/*** Redisson客戶端實例(通過構造函數注入)* 用于操作Redis分布式限流器*/private final RedissonClient redissonClient;/*** 嘗試獲取限流許可(核心方法)* @param key 限流唯一標識(業務維度)* @param count 時間窗口內允許的請求數(令牌桶容量)* @param time 時間窗口數值* @param timeUnit 時間窗口單位* @return true-獲取成功(允許請求),false-獲取失敗(觸發限流)*/public Boolean tryAcquire(String key, int count, int time, TimeUnit timeUnit) {// 1. 獲取或創建限流器,并配置限流規則RRateLimiter rateLimiter = getRRateLimiter(key, count, time, timeUnit);// 2. 嘗試獲取1個令牌(立即返回結果)return rateLimiter.tryAcquire();}/*** 格式化Redis鍵* @param key 原始業務鍵* @return 格式化后的完整Redis鍵*/private static String formatKey(String key) {return String.format(RATE_LIMITER_KEY_TEMPLATE, key);}/*** 獲取或創建限流器(帶智能配置管理)* 處理三種情況:* 1. 限流器不存在:創建并配置* 2. 限流器存在且配置相同:直接使用* 3. 限流器存在但配置不同:更新配置** @param key 業務維度唯一標識* @param count 每秒允許的請求數* @param time 時間窗口數值* @param timeUnit 時間窗口單位* @return 配置好的限流器實例*/private RRateLimiter getRRateLimiter(String key, long count, int time, TimeUnit timeUnit) {// 生成完整Redis鍵String redisKey = formatKey(key);// 獲取限流器實例(可能未初始化)RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);// 將時間單位統一轉換為秒(Redisson配置需要)long rateInterval = timeUnit.toSeconds(time);// 獲取當前限流器配置RateLimiterConfig config = rateLimiter.getConfig();// 情況1:限流器未初始化if (config == null) {// 設置分布式限流規則(整體限流模式)rateLimiter.trySetRate(RateType.OVERALL,       // 全局限流模式count,                  // 令牌生成速率(每秒生成count個)rateInterval,           // 速率計算間隔(秒)RateIntervalUnit.SECONDS);// 設置鍵過期時間(防止內存泄漏),參考知識庫說明rateLimiter.expire(rateInterval, TimeUnit.SECONDS);return rateLimiter;}// 情況2:配置完全匹配現有配置if (config.getRateType() == RateType.OVERALL&& Objects.equals(config.getRate(), count)&& Objects.equals(config.getRateInterval(), TimeUnit.SECONDS.toMillis(rateInterval))) {return rateLimiter;}// 情況3:配置變更需要更新rateLimiter.setRate(RateType.OVERALL,count,rateInterval,RateIntervalUnit.SECONDS);// 更新過期時間(保持鍵的有效期)rateLimiter.expire(rateInterval, TimeUnit.SECONDS);return rateLimiter;}
}

步驟6:自動裝配

/*** @author dyh* @date 2025/4/24 15:06*/
@AutoConfiguration(before = DyhRedisAutoConfiguration.class)
public class DyhRateLimiterConfiguration {@Beanpublic RateLimiterAspect rateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {return new RateLimiterAspect(keyResolvers, rateLimiterRedisDAO);}@Bean@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")public RateLimiterRedisDAO rateLimiterRedisDAO(RedissonClient redissonClient) {return new RateLimiterRedisDAO(redissonClient);}// ========== 各種 RateLimiterRedisDAO Bean ==========@Beanpublic DefaultRateLimiterKeyResolver defaultRateLimiterKeyResolver() {return new DefaultRateLimiterKeyResolver();}@Beanpublic UserRateLimiterKeyResolver userRateLimiterKeyResolver() {return new UserRateLimiterKeyResolver();}@Beanpublic ClientIpRateLimiterKeyResolver clientIpRateLimiterKeyResolver() {return new ClientIpRateLimiterKeyResolver();}@Beanpublic ServerNodeRateLimiterKeyResolver serverNodeRateLimiterKeyResolver() {return new ServerNodeRateLimiterKeyResolver();}@Beanpublic ExpressionRateLimiterKeyResolver expressionRateLimiterKeyResolver() {return new ExpressionRateLimiterKeyResolver();}}

四、核心設計模式解析

1. 策略模式(核心設計)

模式結構

           ┌───────────────────┐│ 策略接口            ││ RateLimiterKeyResolver │└─────────┬─────────┘△┌─────────────┴─────────────┐│                           │
┌──────┴──────┐           ┌───────┴───────┐
│ 具體策略實現   │           │ 具體策略實現    │
│ (IP解析器)    │           │ (用戶解析器)    │
└─────────────┘           └──────────────┘

代碼體現

public interface RateLimiterKeyResolver {String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);
}// 具體策略實現(以IP解析器為例) 
public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver { @Override public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) { String clientIp = ServletUtils.getClientIP(); // 獲取策略參數 return SecureUtil.md5(...); // 策略算法 } 
}

設計優勢

  • 開閉原則:新增限流維度只需添加新策略類(如OrderRateLimiterKeyResolver
  • 業務解耦:限流策略與核心算法分離,修改策略不影響其他組件
  • 動態切換:通過注解參數即時切換策略(@RateLimiter(keyResolver=...)

2. 代理模式(AOP實現)

模式結構

           [業務方法]                 [代理對象]△                       △│                       │
┌──────────────┴──────────────┐ ┌──────┴───────┐
│       原始業務邏輯             │ │  AOP 增強邏輯  │
│ (如:businessMethod 實現)     │ │ (限流校驗邏輯)  │
└─────────────────────────────┘ └──────────────┘

代碼體現

@Aspect
public class RateLimiterAspect { @Before("@annotation(rateLimiter)") public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {// 代理增強邏輯 if (!rateLimiterRedisDAO.tryAcquire(...)) { throw new ServiceException("觸發限流"); } } 
}

設計優勢

  • 無侵入性:業務代碼無需感知限流邏輯的存在
  • 集中管理:所有限流規則在切面中統一處理
  • 動態增強:運行時動態創建代理對象,無需修改源碼

五、使用示例與場景

1. API接口全局限流

@RateLimiter(count = 100) // 默認全局維度 
@GetMapping("/api/list") 
public ApiResult<List> queryList() { // 每秒鐘最多100次請求 
}

2. 用戶維度精細控制

@RateLimiter( count = 10, keyResolver = UserRateLimiterKeyResolver.class ) 
@PostMapping("/user/update") 
public ApiResult updateUserInfo() { // 每個用戶每秒最多操作10次 
}

3. 防爬蟲IP限制

@RateLimiter(count = 5, keyResolver = ClientIpRateLimiterKeyResolver.class)
@GetMapping("/product/detail")
public ProductDetailVO getDetail() { // 每個IP每秒最多5次訪問 
}

4. 復雜表達式場景

@RateLimiter(keyResolver = ExpressionRateLimiterKeyResolver.class, keyArg = "#userId + ':' + #type")
public void businessMethod(Long userId, Integer type) { // 根據userId+type組合限流 
}

六、設計總結

策略模式優勢

  1. 靈活擴展 ? 新增策略只需實現接口,無需修改核心邏輯
    ? 示例:添加 OrderRateLimiterKeyResolver 只需 10 行代碼
  2. 動態切換 ? 通過注解參數即時切換策略
    ? 如 @RateLimiter(keyResolver=UserRateLimiterKeyResolver.class)
  3. 隔離變化 ? 算法變化僅影響具體策略類

代理模式優勢

  1. 業務無侵入 ? 原始代碼無需任何修改
    ? 通過 @Before 注解實現邏輯增強
  2. 集中管控 ? 所有限流規則在切面中統一處理
    ? 統計顯示限流代碼減少業務類 80% 的冗余
  3. 動態織入 ? 運行時決定代理邏輯
    ? 可通過配置動態啟用/停用限流

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

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

相關文章

Node.js 事件循環和線程池任務完整指南?

在 Node.js 的運行體系中&#xff0c;事件循環和線程池是保障其高效異步處理能力的核心組件。事件循環負責調度各類異步任務的執行順序&#xff0c;而線程池則承擔著處理 CPU 密集型及部分特定 I/O 任務的工作。接下來&#xff0c;我們將結合圖示&#xff0c;詳細剖析兩者的工作…

echarts自定義圖表--儀表盤

基于儀表盤類型的自定義表盤 上圖為3層結構組成 正常一個儀表盤配置要在外圈和內圈之間制造一條縫隙間隔 再創建一個儀表盤配置 背景透明 進度條拉滿 進度條顏色和數據的背景相同開始處的線 又一個儀表盤配置 數值固定一個比較小的值 <!DOCTYPE html> <html><h…

【數據結構】圖論存儲結構深度解析:鄰接多重表如何實現無向圖O(1)刪邊?鄰接矩陣/鏈表/十字鏈對比

鄰接多重表 導讀一、有向圖的存儲結構二、鄰接多重表三、存儲結構四、算法評價4.1 時間復雜度4.2 空間復雜度 五、四種存儲方式的總結5.1 空間復雜度5.2 找相鄰邊5.3 刪除邊或結點5.4 適用于5.5 表示方式 六、圖的基本操作結語 導讀 大家好&#xff0c;很高興又和大家見面啦&a…

【Rust】所有權

目錄 所有權基本概念所有權介紹棧與堆變量作用域 字符串字符串字面值&#xff08;&str&#xff09;String 類型相互轉換所有權 內存結構對比注意事項和常見坑使用場景 內存與分配變量與數據交互的方式&#xff08;一&#xff09;&#xff1a;移動變量與數據交互的方式&…

4月29日日記

終于是考完解析幾何了&#xff0c;今天昨天突擊了一下&#xff0c;感覺確實學會了很多之前不會的東西&#xff0c;但是可能距離高分還差很多。這次考試不太理想。大部分原因是前期沒學&#xff0c;吸取教訓&#xff0c;早點開始復習微積分。明天還有一節微積分&#xff0c;但是…

【深度對比】Google Play與IOS 馬甲包處理差異分析

在移動應用發布與推廣過程中&#xff0c;馬甲包&#xff08;Cloned App / Alternate Version&#xff09; 曾被廣泛用于流量測試、風險隔離、多品牌運營等場景中。隨著 Google Play 與 Apple App Store 審核政策不斷收緊&#xff0c;開發者們越來越關注兩個平臺對“馬甲包”的態…

MCP 架構全解析:Host、Client 與 Server 的協同機制

目錄 &#x1f3d7;? MCP 架構全解析&#xff1a;Host、Client 與 Server 的協同機制 &#x1f4cc; 引言 &#x1f9e9; 核心架構組件 1. Host&#xff08;主機&#xff09; 2. Client&#xff08;客戶端&#xff09; 3. Server&#xff08;服務器&#xff09; &#…

記錄一次無界微前端的簡單使用

記錄一次無界微前端使用 無界微前端主應用子應用nginx配置 無界微前端 https://wujie-micro.github.io/doc/ 因為使用的是vue項目主應用和次應用都是 所以用的封裝的。 https://wujie-micro.github.io/doc/pack/ 主應用 安裝 選擇對應的版本 # vue2 框架 npm i wujie-vue2…

LLM應用于自動駕駛方向相關論文整理(大模型在自動駕駛方向的相關研究)

1、《HILM-D: Towards High-Resolution Understanding in Multimodal Large Language Models for Autonomous Driving》 2023年9月發表的大模型做自動駕駛的論文&#xff0c;來自香港科技大學和人華為諾亞實驗室&#xff08;代碼開源&#xff09;。 論文簡介&#xff1a; 本文…

FTP-網絡文件服務器

部署思路 單純上傳下載ftp系統集成間的共享 samba網絡存儲服務器 NFS 網絡文件服務器&#xff1a;通過網絡共享文件或文件夾&#xff0c;實現數據共享 NAS &#xff08; network append storage):共享的是文件夾 FTP&#xff1a;文件服務器samba&#xff1a;不同系統間的文件…

在 Ubuntu 22.04 x64 系統安裝/卸載 1Panel 面板

一、 1Panel 是什么&#xff1f; 1Panel 是一款基于 Go 語言開發的現代化開源服務器管理面板&#xff08;類似寶塔面板&#xff09;&#xff0c;專注于容器化&#xff08;Docker&#xff09;和云原生環境管理&#xff0c;提供可視化界面簡化服務器運維操作。 1. 1Panel主要功…

Redis | Redis集群模式技術原理介紹

關注&#xff1a;CodingTechWork Redis 集群模式概述 Redis 集群&#xff08;Cluster&#xff09;模式是 Redis 官方提供的分布式解決方案&#xff0c;旨在解決單機 Redis 在數據量和性能上的限制。它通過數據分片、高可用性和自動故障轉移等特性&#xff0c;提供了水平擴展和…

Servlet小結

視頻鏈接&#xff1a;黑馬servlet視頻全套視頻教程&#xff0c;快速入門servlet原理servlet實戰 什么是Servlet&#xff1f; 菜鳥教程&#xff1a;Java Servlet servlet&#xff1a; server applet Servlet是一個運行在Web服務器&#xff08;如Tomcat、Jetty&#xff09;或應用…

數據庫進階之MySQL 程序

1.目標 1> 了解mysqlId服務端程序 2> 掌握mysql客戶端程序的使用 3> 了解工具包中的其他程序 2. MySQL程序簡介 本章介紹 MySQL 命令?程序以及在運?這些程序時指定選項的?般語法(如:mysql -uroot -p)。 對常?程序進?詳細的講解(實用工具的使用方法)&#xf…

VS2022 設置 Qt Project Settings方法

本文解決的問題&#xff1a;創建完成后&#xff0c;如需要用到Sql或者Socket等技術&#xff0c;需要設置Qt Project Settings&#xff1b; 1、打開VS2022編譯器&#xff0c;創建QT項目工程 2、創建完成后&#xff0c;點擊 解決方案 →右鍵屬性 3、選擇 Qt Project Settings →…

React:封裝一個評論回復組件

分析 用戶想要一個能夠顯示評論列表&#xff0c;并且允許用戶進行回復的組件。可能還需要支持多級回復&#xff0c;也就是對回復進行再回復。然后&#xff0c;我要考慮組件的結構和功能。 首先&#xff0c;數據結構方面&#xff0c;評論應該包含id、內容、作者、時間&#xf…

wx讀書某sign算法詳解

未加固 版本&#xff1a;9.2.3 前置知識&#xff1a; (v41 & 0xFFFFFFFFFFFFFFFELL) 是一種高效的奇偶檢查方法&#xff0c;用于判斷數值 v41 是否為奇數。 std::sort<std::lessstd::string,std::string &,std::string>(a1, v6, s); 排序算法 # 完全等價的字…

Django的異步任務隊列管理_Celery

1 基本原理 Celery 是一個異步任務隊列&#xff0c;能夠將耗時操作&#xff08;如發郵件、處理圖片、網絡爬蟲等&#xff09;從 Django 主線程中分離出來&#xff0c;由后臺的 worker 處理&#xff0c;避免阻塞請求。Celery 作為獨立運行的后臺進程&#xff08;Worker&#xf…

【計算機網絡】Linux網絡的幾個常用命令

&#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f152; C 語言 | &#x1f310; 計算機網絡 相關文章&#xff1a;計算機網絡專欄 目錄 ping&#xff08;檢測網絡連通性&#xff09;…

全開源、私有化部署!輕量級用戶行為分析系統-ClkLog

ClkLog是一款支持私有化部署的全開源埋點數據采集與分析系統&#xff0c;兼容Web、App、小程序多端埋點&#xff0c;快速洞察用戶訪問路徑、行為軌跡&#xff0c;并生成多維用戶畫像。助力中小團隊搭建輕量靈活的用戶行為分析平臺。 為什么需要一款私有化的埋點分析系統&#x…