最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis分布式限流生產(chǎn)環(huán)境落地方案

 更新時(shí)間:2026年02月06日 10:10:53   作者:三水不滴  
本文主要介紹了Redis分布式限流生產(chǎn)環(huán)境落地方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

該方案適配Spring Boot 2.x/3.x + Spring Cloud微服務(wù)生態(tài),覆蓋Lua 腳本原子限流(固定窗口 / 滑動(dòng)窗口)、Redisson 令牌桶 / 信號(hào)量限流Spring Cloud Gateway 網(wǎng)關(guān)統(tǒng)一限流、Redis 宕機(jī)兜底降級(jí)四大核心能力,兼顧原子性、動(dòng)態(tài)配置、高可用、可監(jiān)控,可直接復(fù)制到生產(chǎn)環(huán)境并按需微調(diào)。

前置依賴(lài)

生產(chǎn)環(huán)境統(tǒng)一引入以下核心依賴(lài)(Maven),版本適配自身 Spring Cloud/Spring Boot 版本:

<!-- Redis核心依賴(lài) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Redisson分布式限流 -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.3</version>
</dependency>
<!-- Spring Cloud Gateway網(wǎng)關(guān) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos動(dòng)態(tài)配置(限流規(guī)則熱更新) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 熔斷降級(jí)(Sentinel,可選替換為Resilience4j) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 工具類(lèi) -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.23</version>
</dependency>
<!-- 本地降級(jí)限流(Guava) -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

一、基礎(chǔ)環(huán)境配置

1. Redis 連接配置(application.yml)

包含連接池、序列化優(yōu)化,適配單機(jī) / 主從 / 集群:

spring:
  redis:
    host: 192.168.1.100 # 生產(chǎn)替換為Redis集群地址
    port: 6379
    password: prod_redis_123
    database: 2 # 限流專(zhuān)用庫(kù),與業(yè)務(wù)隔離
    lettuce:
      pool:
        max-active: 50 # 最大連接數(shù),按QPS調(diào)整
        max-idle: 20
        min-idle: 5
        max-wait: 3000ms # 連接超時(shí),生產(chǎn)建議3s內(nèi)
    timeout: 2000ms # Redis操作超時(shí)
  # Nacos配置(動(dòng)態(tài)限流規(guī)則)
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.101:8848
        namespace: prod
        group: DEFAULT_GROUP
        file-extension: yml
        shared-configs:
          - data-id: redis-limit-rules.yml # 限流規(guī)則統(tǒng)一配置文件
            group: DEFAULT_GROUP
            refresh: true # 支持熱更新

2. Redisson 配置(生產(chǎn)高可用版)

支持單機(jī) / 主從 / 哨兵 / 集群,這里以Redis Cluster為例(生產(chǎn)推薦),創(chuàng)建RedissonConfig.java

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SubscriptionMode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {
    // 從Nacos/配置文件讀取Redis集群地址
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.database:0}")
    private int database;

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        // 集群模式配置(生產(chǎn)核心)
        config.useClusterServers()
                .addNodeAddress(clusterNodes.split(","))
                .setPassword(password)
                .setDatabase(database)
                .setScanInterval(2000) // 節(jié)點(diǎn)掃描間隔
                .setMasterConnectionPoolSize(50) // 主節(jié)點(diǎn)連接池
                .setSlaveConnectionPoolSize(20) // 從節(jié)點(diǎn)連接池
                .setReadMode(ReadMode.SLAVE) // 讀從節(jié)點(diǎn),分擔(dān)壓力
                .setSubscriptionMode(SubscriptionMode.SLAVE); // 訂閱從節(jié)點(diǎn)
        // 超時(shí)配置,避免Redis阻塞
        config.setConnectTimeout(2000);
        config.setTimeout(2000);
        return Redisson.create(config);
    }
}

Nacos 補(bǔ)充配置:在application.yml添加 Redis 集群地址,支持熱更新:

spring:
  redis:
    cluster:
      nodes: redis://192.168.1.100:7001,redis://192.168.1.100:7002,redis://192.168.1.100:7003

二、Lua 腳本原子限流模板(固定窗口 + 滑動(dòng)窗口)

依托 Redis單線(xiàn)程原子執(zhí)行 Lua 腳本,解決計(jì)數(shù)限流的并發(fā)問(wèn)題,分為固定窗口(簡(jiǎn)單高效,生產(chǎn) 80% 場(chǎng)景適用)和滑動(dòng)窗口(解決固定窗口臨界超量問(wèn)題,高精度場(chǎng)景適用),封裝通用調(diào)用工具類(lèi),支持接口 / IP / 用戶(hù)多維度限流。

1. 核心 Lua 腳本(放在resources/lua目錄下,生產(chǎn)建議統(tǒng)一管理)

(1)固定窗口計(jì)數(shù)限流limit_fixed_window.lua

核心邏輯:計(jì)數(shù) + 過(guò)期時(shí)間原子設(shè)置,達(dá)到閾值返回 0(拒絕),否則返回 1(允許),支持自定義窗口時(shí)長(zhǎng)和閾值。

-- 固定窗口限流Lua腳本(原子性)
-- KEYS[1]:限流key(如limit:api:order:192.168.1.1)
-- ARGV[1]:限流閾值(如100)
-- ARGV[2]:窗口過(guò)期時(shí)間(秒,如60)
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local expire = tonumber(ARGV[2])

-- 原子計(jì)數(shù)
local current = redis.call('incr', key)
-- 首次計(jì)數(shù),設(shè)置過(guò)期時(shí)間(避免內(nèi)存泄漏)
if current == 1 then
    redis.call('expire', key, expire)
end
-- 超過(guò)閾值返回0,否則返回1
if current > limit then
    return 0
else
    return 1
end

(2)滑動(dòng)窗口計(jì)數(shù)限流limit_slide_window.lua

核心邏輯:基于 ZSet 存儲(chǔ)請(qǐng)求時(shí)間戳,自動(dòng)清理過(guò)期請(qǐng)求,統(tǒng)計(jì)窗口內(nèi)總請(qǐng)求數(shù),解決固定窗口臨界超量問(wèn)題(如 1 分鐘窗口,59 秒和 1 秒各請(qǐng)求 100 次,固定窗口會(huì)允許 200 次,滑動(dòng)窗口僅允許 100 次)。

-- 滑動(dòng)窗口限流Lua腳本(原子性)
-- KEYS[1]:限流key(如limit:api:seckill:192.168.1.1)
-- ARGV[1]:限流閾值(如100)
-- ARGV[2]:窗口時(shí)長(zhǎng)(毫秒,如60000)
-- ARGV[3]:當(dāng)前請(qǐng)求時(shí)間戳(毫秒,如System.currentTimeMillis())
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local windowMs = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
-- 窗口開(kāi)始時(shí)間:當(dāng)前時(shí)間 - 窗口時(shí)長(zhǎng)
local windowStart = now - windowMs

-- 1. 移除ZSet中過(guò)期的請(qǐng)求記錄(score < 窗口開(kāi)始時(shí)間)
redis.call('zremrangebyscore', key, 0, windowStart)
-- 2. 統(tǒng)計(jì)當(dāng)前窗口內(nèi)的請(qǐng)求數(shù)
local current = redis.call('zcard', key)
-- 3. 超過(guò)閾值,返回0拒絕
if current >= limit then
    return 0
end
-- 4. 未超閾值,添加當(dāng)前請(qǐng)求到ZSet(score=時(shí)間戳,value=唯一標(biāo)識(shí)避免重復(fù))
redis.call('zadd', key, now, now .. math.random(10000))
-- 5. 設(shè)置ZSet過(guò)期時(shí)間,避免內(nèi)存泄漏(窗口時(shí)長(zhǎng)+1秒)
redis.call('expire', key, math.ceil(windowMs / 1000) + 1)
return 1

2. Lua 腳本通用調(diào)用工具類(lèi)RedisLimitLuaUtil.java

封裝腳本加載、參數(shù)組裝、Redis 調(diào)用邏輯,全局唯一,避免重復(fù)加載腳本,支持多維度限流 key 生成:

import cn.hutool.core.util.StrUtil;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Objects;

/**
 * Redis Lua腳本限流通用工具類(lèi)(固定窗口+滑動(dòng)窗口)
 */
@Component
public class RedisLimitLuaUtil {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // 固定窗口腳本
    private DefaultRedisScript<Long> fixedWindowScript;
    // 滑動(dòng)窗口腳本
    private DefaultRedisScript<Long> slideWindowScript;

    // 限流key前綴,統(tǒng)一規(guī)范
    private static final String LIMIT_KEY_PREFIX = "limit:";

    /**
     * 初始化Lua腳本(項(xiàng)目啟動(dòng)時(shí)加載,避免重復(fù)加載)
     */
    @PostConstruct
    public void initScript() {
        // 固定窗口腳本初始化
        fixedWindowScript = new DefaultRedisScript<>();
        fixedWindowScript.setResultType(Long.class);
        fixedWindowScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/limit_fixed_window.lua")));

        // 滑動(dòng)窗口腳本初始化
        slideWindowScript = new DefaultRedisScript<>();
        slideWindowScript.setResultType(Long.class);
        slideWindowScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/limit_slide_window.lua")));
    }

    /**
     * 固定窗口限流判斷
     * @param limitDimension 限流維度(api/ip/user)
     * @param target 限流目標(biāo)(如接口名order/create、IP192.168.1.1、用戶(hù)ID1001)
     * @param limit 限流閾值
     * @param expire 窗口過(guò)期時(shí)間(秒)
     * @return true=允許,false=拒絕
     */
    public boolean fixedWindowLimit(String limitDimension, String target, int limit, int expire) {
        try {
            String key = generateLimitKey(limitDimension, target);
            // 執(zhí)行Lua腳本,原子判斷
            Long result = redisTemplate.execute(
                    fixedWindowScript,
                    Collections.singletonList(key),
                    limit,
                    expire
            );
            // 結(jié)果為1則允許,0則拒絕
            return Objects.nonNull(result) && result == 1;
        } catch (Exception e) {
            // Redis異常時(shí),返回false觸發(fā)降級(jí)策略
            log.error("固定窗口限流Redis執(zhí)行異常,維度:{},目標(biāo):{}", limitDimension, target, e);
            return false;
        }
    }

    /**
     * 滑動(dòng)窗口限流判斷
     * @param limitDimension 限流維度(api/ip/user)
     * @param target 限流目標(biāo)
     * @param limit 限流閾值
     * @param windowMs 窗口時(shí)長(zhǎng)(毫秒)
     * @return true=允許,false=拒絕
     */
    public boolean slideWindowLimit(String limitDimension, String target, int limit, long windowMs) {
        try {
            String key = generateLimitKey(limitDimension, target);
            long now = System.currentTimeMillis();
            // 執(zhí)行Lua腳本,原子判斷
            Long result = redisTemplate.execute(
                    slideWindowScript,
                    Collections.singletonList(key),
                    limit,
                    windowMs,
                    now
            );
            return Objects.nonNull(result) && result == 1;
        } catch (Exception e) {
            log.error("滑動(dòng)窗口限流Redis執(zhí)行異常,維度:{},目標(biāo):{}", limitDimension, target, e);
            return false;
        }
    }

    /**
     * 生成限流key:limit:維度:目標(biāo)
     * 例:limit:ip:192.168.1.1、limit:api:order/create
     */
    private String generateLimitKey(String limitDimension, String target) {
        return StrUtil.format("{}{}:{}", LIMIT_KEY_PREFIX, limitDimension, target);
    }
}

3. 業(yè)務(wù)層調(diào)用示例(Controller/Service)

直接注入工具類(lèi),按需選擇固定 / 滑動(dòng)窗口,一行代碼實(shí)現(xiàn)限流

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("/api/order")
public class OrderController {
    @Resource
    private RedisLimitLuaUtil redisLimitLuaUtil;
    @Resource
    private LimitDegradeUtil limitDegradeUtil; // 降級(jí)工具類(lèi)(后續(xù)實(shí)現(xiàn))

    @PostMapping("/create")
    public Result createOrder(HttpServletRequest request) {
        // 1. 提取限流目標(biāo)(接口+IP雙維度,生產(chǎn)常用)
        String apiTarget = "order/create";
        String ipTarget = request.getRemoteAddr();
        // 2. 限流規(guī)則:接口每分鐘1000次,IP每分鐘100次
        boolean apiLimit = redisLimitLuaUtil.fixedWindowLimit("api", apiTarget, 1000, 60);
        boolean ipLimit = redisLimitLuaUtil.fixedWindowLimit("ip", ipTarget, 100, 60);
        // 3. 限流判斷+降級(jí)(Redis異常時(shí)觸發(fā)本地降級(jí))
        if (!apiLimit || !ipLimit) {
            // 觸發(fā)降級(jí):先嘗試本地兜底,失敗則返回限流提示
            if (!limitDegradeUtil.localLimitFallback(apiTarget)) {
                return Result.fail(429, "請(qǐng)求過(guò)于頻繁,請(qǐng)稍后再試");
            }
        }
        // 4. 執(zhí)行業(yè)務(wù)邏輯
        return Result.success("訂單創(chuàng)建成功");
    }
}

三、Redisson 限流核心模板(令牌桶 + 信號(hào)量)

Redisson 底層基于 Lua 腳本實(shí)現(xiàn)原子性,開(kāi)箱即用支持令牌桶限流(應(yīng)對(duì)突發(fā)流量,如秒殺 / 網(wǎng)關(guān))和信號(hào)量限流(控制并發(fā)數(shù),如數(shù)據(jù)庫(kù) / 中間件資源訪(fǎng)問(wèn)),封裝通用工具類(lèi),支持全局唯一令牌池動(dòng)態(tài)規(guī)則調(diào)整

1. Redisson 限流通用工具類(lèi)RedissonLimitUtil.java

封裝令牌桶(RateLimiter)和信號(hào)量(Semaphore)核心方法,生產(chǎn)建議單例,避免重復(fù)創(chuàng)建 Redisson 對(duì)象:

import org.redisson.api.RRateLimiter;
import org.redisson.api.RSemaphore;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * Redisson限流工具類(lèi)(令牌桶+信號(hào)量)
 * 令牌桶:控制QPS,支持突發(fā)流量
 * 信號(hào)量:控制并發(fā)數(shù),保護(hù)下游資源
 */
@Component
public class RedissonLimitUtil {
    @Resource
    private RedissonClient redissonClient;

    // 限流key前綴
    private static final String RATE_LIMIT_PREFIX = "rate:limit:";
    private static final String SEMAPHORE_PREFIX = "semaphore:limit:";

    /**
     * 令牌桶限流(獲取1個(gè)令牌,無(wú)超時(shí))
     * @param target 限流目標(biāo)(如seckill/sku1001、gateway/api)
     * @param rate 令牌生成速率(如100)
     * @param rateInterval 令牌生成時(shí)間間隔(如1)
     * @param unit 時(shí)間單位(如SECONDS)
     * @param capacity 令牌桶最大容量(突發(fā)流量上限,如200)
     * @return true=獲取令牌成功,false=失敗
     */
    public boolean rateLimit(String target, int rate, int rateInterval, RateIntervalUnit unit, int capacity) {
        try {
            String key = RATE_LIMIT_PREFIX + target;
            // 獲取令牌桶實(shí)例(全局唯一,Redisson自動(dòng)緩存)
            RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
            // 初始化令牌桶規(guī)則(僅首次執(zhí)行有效,后續(xù)修改需調(diào)用setRate)
            rateLimiter.trySetRate(RateType.OVERALL, rate, rateInterval, unit, capacity);
            // 獲取1個(gè)令牌,無(wú)超時(shí)等待
            return rateLimiter.tryAcquire(1);
        } catch (Exception e) {
            log.error("Redisson令牌桶限流異常,目標(biāo):{}", target, e);
            return false;
        }
    }

    /**
     * 令牌桶限流(帶超時(shí)等待,適合高并發(fā)突發(fā)場(chǎng)景)
     * @param target 限流目標(biāo)
     * @param rate 生成速率
     * @param rateInterval 時(shí)間間隔
     * @param unit 時(shí)間單位
     * @param capacity 桶容量
     * @param waitTime 超時(shí)等待時(shí)間
     * @param waitUnit 等待時(shí)間單位
     * @return true=成功,false=失敗
     */
    public boolean rateLimitWithWait(String target, int rate, int rateInterval, RateIntervalUnit unit,
                                     int capacity, long waitTime, TimeUnit waitUnit) {
        try {
            String key = RATE_LIMIT_PREFIX + target;
            RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
            rateLimiter.trySetRate(RateType.OVERALL, rate, rateInterval, unit, capacity);
            return rateLimiter.tryAcquire(1, waitTime, waitUnit);
        } catch (Exception e) {
            log.error("Redisson令牌桶限流(帶等待)異常,目標(biāo):{}", target, e);
            return false;
        }
    }

    /**
     * 信號(hào)量限流(獲取1個(gè)許可,控制并發(fā)數(shù))
     * @param target 限流目標(biāo)(如resource/mysql、resource/kafka)
     * @param permits 最大許可數(shù)(最大并發(fā)數(shù))
     * @return true=成功,false=失敗
     */
    public boolean semaphoreLimit(String target, int permits) {
        try {
            String key = SEMAPHORE_PREFIX + target;
            RSemaphore semaphore = redissonClient.getSemaphore(key);
            // 初始化許可數(shù)(僅首次有效)
            if (!semaphore.isExists()) {
                semaphore.trySetPermits(permits);
            }
            // 獲取1個(gè)許可,無(wú)超時(shí)
            return semaphore.tryAcquire(1);
        } catch (Exception e) {
            log.error("Redisson信號(hào)量限流異常,目標(biāo):{}", target, e);
            return false;
        }
    }

    /**
     * 信號(hào)量限流(帶超時(shí),釋放許可必須在finally中執(zhí)行)
     * @param target 限流目標(biāo)
     * @param permits 最大并發(fā)數(shù)
     * @param waitTime 超時(shí)時(shí)間
     * @param unit 時(shí)間單位
     * @return RSemaphore實(shí)例(用于釋放許可),null=獲取失敗
     */
    public RSemaphore semaphoreLimitWithWait(String target, int permits, long waitTime, TimeUnit unit) {
        try {
            String key = SEMAPHORE_PREFIX + target;
            RSemaphore semaphore = redissonClient.getSemaphore(key);
            if (!semaphore.isExists()) {
                semaphore.trySetPermits(permits);
            }
            if (semaphore.tryAcquire(1, waitTime, unit)) {
                return semaphore;
            }
        } catch (Exception e) {
            log.error("Redisson信號(hào)量限流(帶等待)異常,目標(biāo):{}", target, e);
        }
        return null;
    }

    /**
     * 釋放信號(hào)量許可(必須調(diào)用,避免資源泄漏)
     */
    public void releaseSemaphore(RSemaphore semaphore) {
        if (semaphore != null && semaphore.isAcquired()) {
            semaphore.release(1);
        }
    }
}

2. 核心場(chǎng)景調(diào)用示例

(1)令牌桶限流(秒殺場(chǎng)景,支持突發(fā)流量)

@RestController
@RequestMapping("/api/seckill")
public class SeckillController {
    @Resource
    private RedissonLimitUtil redissonLimitUtil;
    @Resource
    private LimitDegradeUtil limitDegradeUtil;

    @PostMapping("/buy/{skuId}")
    public Result seckill(@PathVariable String skuId) {
        String target = "seckill/sku" + skuId;
        // 限流規(guī)則:每秒生成100個(gè)令牌,桶容量200(支持200的突發(fā)流量)
        boolean acquire = redissonLimitUtil.rateLimitWithWait(
                target, 100, 1, RateIntervalUnit.SECONDS, 200,
                500, TimeUnit.MILLISECONDS // 超時(shí)等待500ms
        );
        if (!acquire) {
            if (!limitDegradeUtil.localLimitFallback(target)) {
                return Result.fail(429, "秒殺太火爆了,請(qǐng)稍后再試");
            }
        }
        // 執(zhí)行秒殺業(yè)務(wù)
        return Result.success("秒殺成功");
    }
}

(2)信號(hào)量限流(數(shù)據(jù)庫(kù)資源保護(hù),控制并發(fā)數(shù))

@Service
public class OrderQueryService {
    @Resource
    private RedissonLimitUtil redissonLimitUtil;
    @Resource
    private LimitDegradeUtil limitDegradeUtil;

    public List<Order> queryOrderByUserId(Long userId) {
        String target = "resource/mysql/orderQuery";
        // 限流規(guī)則:最大并發(fā)數(shù)20(避免數(shù)據(jù)庫(kù)連接池打滿(mǎn))
        RSemaphore semaphore = redissonLimitUtil.semaphoreLimitWithWait(
                target, 20, 1, TimeUnit.SECONDS
        );
        if (semaphore == null) {
            if (!limitDegradeUtil.localLimitFallback(target)) {
                throw new BusinessException(429, "當(dāng)前查詢(xún)?nèi)藬?shù)過(guò)多,請(qǐng)稍后再試");
            }
        }
        // 必須在finally中釋放許可,避免資源泄漏
        try {
            // 執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)
            return orderMapper.selectByUserId(userId);
        } finally {
            redissonLimitUtil.releaseSemaphore(semaphore);
        }
    }
}

四、Spring Cloud Gateway 網(wǎng)關(guān)整合限流模板

網(wǎng)關(guān)是分布式限流的最佳入口,實(shí)現(xiàn)全鏈路統(tǒng)一限流,避免限流邏輯散落在各個(gè)微服務(wù),這里整合Redisson 令牌桶限流(網(wǎng)關(guān)主流方案),支持路由級(jí) / 全局級(jí)限流、Nacos 動(dòng)態(tài)規(guī)則多維度提取(接口 / IP / 用戶(hù)),返回標(biāo)準(zhǔn) HTTP 429 響應(yīng)。

1. 網(wǎng)關(guān)限流規(guī)則配置(Nacosredis-limit-rules.yml,支持熱更新)

# 網(wǎng)關(guān)限流規(guī)則(key=路由ID,與gateway路由配置一致)
gateway:
  limit:
    rules:
      order-service: # 訂單服務(wù)路由ID
        enable: true # 是否開(kāi)啟限流
        target: gateway/order-service # 限流目標(biāo)
        rate: 200 # 令牌生成速率(QPS)
        rateInterval: 1 # 時(shí)間間隔(秒)
        capacity: 400 # 令牌桶容量
        waitTime: 500 # 超時(shí)等待時(shí)間(毫秒)
      seckill-service: # 秒殺服務(wù)路由ID
        enable: true
        target: gateway/seckill-service
        rate: 500
        rateInterval: 1
        capacity: 1000
        waitTime: 300
      default: # 全局默認(rèn)規(guī)則
        enable: true
        target: gateway/default
        rate: 1000
        rateInterval: 1
        capacity: 2000
        waitTime: 200

2. 限流規(guī)則實(shí)體類(lèi)GatewayLimitRule.java

映射 Nacos 配置,支持配置熱更新

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 網(wǎng)關(guān)限流規(guī)則配置(Nacos熱更新)
 */
@Data
@Component
@RefreshScope // 開(kāi)啟配置熱更新
@ConfigurationProperties(prefix = "gateway.limit")
public class GatewayLimitRule {
    // key=路由ID,value=具體規(guī)則
    private Map<String, GatewayLimitItem> rules;

    @Data
    public static class GatewayLimitItem {
        private boolean enable; // 是否開(kāi)啟限流
        private String target; // 限流目標(biāo)
        private int rate; // 令牌速率
        private int rateInterval; // 時(shí)間間隔
        private int capacity; // 桶容量
        private long waitTime; // 超時(shí)等待時(shí)間(毫秒)
    }
}

3. 網(wǎng)關(guān)全局限流過(guò)濾器GatewayLimitGlobalFilter.java

實(shí)現(xiàn)GlobalFilterOrdered,攔截所有網(wǎng)關(guān)請(qǐng)求,按路由 ID 匹配限流規(guī)則,原子執(zhí)行限流判斷,限流失敗直接返回 429 響應(yīng):

import cn.hutool.core.util.StrUtil;
import org.redisson.api.RateIntervalUnit;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * Spring Cloud Gateway全局限流過(guò)濾器(Redisson令牌桶)
 * 優(yōu)先級(jí)最高,最先執(zhí)行
 */
@Component
public class GatewayLimitGlobalFilter implements GlobalFilter, Ordered {
    @Resource
    private RedissonLimitUtil redissonLimitUtil;
    @Resource
    private GatewayLimitRule gatewayLimitRule;
    @Resource
    private LimitDegradeUtil limitDegradeUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 1. 獲取當(dāng)前路由ID(gateway路由配置的ID)
        String routeId = exchange.getAttribute("org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ID");
        if (StrUtil.isBlank(routeId)) {
            routeId = "default"; // 無(wú)路由ID,使用默認(rèn)規(guī)則
        }
        // 2. 匹配限流規(guī)則
        GatewayLimitRule.GatewayLimitItem limitItem = gatewayLimitRule.getRules().get(routeId);
        if (Objects.isNull(limitItem) || !limitItem.isEnable()) {
            return chain.filter(exchange); // 未開(kāi)啟限流,直接放行
        }
        // 3. 執(zhí)行令牌桶限流
        boolean acquire = redissonLimitUtil.rateLimitWithWait(
                limitItem.getTarget(),
                limitItem.getRate(),
                limitItem.getRateInterval(),
                RateIntervalUnit.SECONDS,
                limitItem.getCapacity(),
                limitItem.getWaitTime(),
                java.util.concurrent.TimeUnit.MILLISECONDS
        );
        // 4. 限流判斷+降級(jí)
        if (!acquire) {
            // 觸發(fā)本地降級(jí),失敗則返回429
            if (!limitDegradeUtil.localLimitFallback(limitItem.getTarget())) {
                response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                String errorMsg = "{"code":429,"msg":"網(wǎng)關(guān)限流:請(qǐng)求過(guò)于頻繁"}";
                return response.writeWith(Mono.just(response.bufferFactory().wrap(errorMsg.getBytes())));
            }
        }
        // 5. 放行,執(zhí)行后續(xù)過(guò)濾器
        return chain.filter(exchange);
    }

    /**
     * 過(guò)濾器優(yōu)先級(jí):最高(Ordered.HIGHEST_PRECEDENCE)
     */
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

4. 網(wǎng)關(guān)路由配置(application.yml)

關(guān)聯(lián)限流規(guī)則的路由 ID,生產(chǎn)建議配合 Nacos 動(dòng)態(tài)路由:

spring:
  cloud:
    gateway:
      routes:
        # 訂單服務(wù)路由(ID=order-service,與限流規(guī)則一致)
        - id: order-service
          uri: lb://order-service # 負(fù)載均衡到訂單服務(wù)
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1 # 去除/api前綴
        # 秒殺服務(wù)路由(ID=seckill-service,與限流規(guī)則一致)
        - id: seckill-service
          uri: lb://seckill-service
          predicates:
            - Path=/api/seckill/**
          filters:
            - StripPrefix=1
        # 全局默認(rèn)路由
        - id: default
          uri: lb://common-service
          predicates:
            - Path=/**

五、生產(chǎn)環(huán)境降級(jí)策略模板(Redis 宕機(jī)兜底 + 限流降級(jí))

限流的核心降級(jí)目標(biāo):Redis 宕機(jī) / 超時(shí) / 壓力過(guò)大時(shí),不影響核心業(yè)務(wù)可用,通過(guò)本地內(nèi)存限流(Guava RateLimiter) 做兜底,同時(shí)結(jié)合Sentinel 熔斷限制降級(jí)后的請(qǐng)求量,避免本地限流被擊穿。

1. 降級(jí)核心工具類(lèi)LimitDegradeUtil.java

封裝本地令牌桶兜底限流指標(biāo)統(tǒng)計(jì),支持按目標(biāo)單獨(dú)配置本地規(guī)則,避免全局本地限流被擊穿:

import com.google.common.util.concurrent.RateLimiter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 限流降級(jí)工具類(lèi)(Redis異常時(shí)本地兜底)
 * 基于Guava RateLimiter實(shí)現(xiàn)本地令牌桶限流
 */
@Component
public class LimitDegradeUtil {
    // 本地限流實(shí)例緩存:key=限流目標(biāo),value=Guava RateLimiter
    private final Map<String, RateLimiter> localRateLimiterMap = new ConcurrentHashMap<>();
    // 本地默認(rèn)QPS(可從Nacos動(dòng)態(tài)配置)
    private static final double DEFAULT_LOCAL_QPS = 50.0;

    /**
     * 初始化核心目標(biāo)的本地限流規(guī)則(生產(chǎn)建議從Nacos加載)
     */
    @PostConstruct
    public void initLocalLimit() {
        // 秒殺服務(wù)本地兜底QPS=10
        localRateLimiterMap.put("seckill/sku1001", RateLimiter.create(10.0));
        // 訂單服務(wù)本地兜底QPS=20
        localRateLimiterMap.put("order/create", RateLimiter.create(20.0));
        // 網(wǎng)關(guān)全局本地兜底QPS=100
        localRateLimiterMap.put("gateway/default", RateLimiter.create(100.0));
    }

    /**
     * 本地限流兜底方法
     * @param target 限流目標(biāo)
     * @return true=獲取本地令牌成功,false=失敗
     */
    public boolean localLimitFallback(String target) {
        try {
            // 從緩存獲取本地限流實(shí)例,無(wú)則創(chuàng)建默認(rèn)實(shí)例
            RateLimiter rateLimiter = localRateLimiterMap.getOrDefault(target, RateLimiter.create(DEFAULT_LOCAL_QPS));
            // 嘗試獲取1個(gè)本地令牌(無(wú)超時(shí))
            return rateLimiter.tryAcquire();
        } catch (Exception e) {
            log.error("本地限流兜底異常,目標(biāo):{}", target, e);
            return false;
        }
    }

    /**
     * 動(dòng)態(tài)更新本地限流規(guī)則(支持Nacos熱更新調(diào)用)
     * @param target 限流目標(biāo)
     * @param qps 目標(biāo)QPS
     */
    public void updateLocalLimit(String target, double qps) {
        localRateLimiterMap.put(target, RateLimiter.create(qps));
        log.info("本地限流規(guī)則更新成功,目標(biāo):{},QPS:{}", target, qps);
    }
}

2. Redis 異常熔斷降級(jí)(Sentinel 整合)

通過(guò)Sentinel對(duì) Redis 操作做熔斷,當(dāng) Redis 異常率達(dá)到閾值時(shí),直接觸發(fā)本地降級(jí),避免 Redis 異常拖垮整個(gè)服務(wù),添加SentinelConfig.java

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * Sentinel熔斷配置(Redis操作熔斷)
 */
@Configuration
public class SentinelConfig {
    /**
     * 開(kāi)啟Sentinel注解支持
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

    /**
     * 初始化Redis操作熔斷規(guī)則
     * 策略:異常比例熔斷,5秒內(nèi)異常率>50%,熔斷10秒
     */
    @PostConstruct
    public void initDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        // Redis Lua腳本限流熔斷規(guī)則
        DegradeRule luaRule = new DegradeRule();
        luaRule.setResource("redisLimitLua"); // 資源名,與@SentinelResource一致
        luaRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); // 異常比例
        luaRule.setCount(0.5); // 異常比例閾值50%
        luaRule.setTimeWindow(10); // 熔斷時(shí)間10秒
        luaRule.setMinRequestAmount(10); // 最小請(qǐng)求數(shù):5秒內(nèi)至少10次請(qǐng)求才觸發(fā)

        // Redisson限流熔斷規(guī)則
        DegradeRule redissonRule = new DegradeRule();
        redissonRule.setResource("redissonLimit");
        redissonRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
        redissonRule.setCount(0.5);
        redissonRule.setTimeWindow(10);
        redissonRule.setMinRequestAmount(10);

        rules.add(luaRule);
        rules.add(redissonRule);
        DegradeRuleManager.loadRules(rules);
    }
}

3. 熔斷注解使用(修改限流工具類(lèi))

在 Lua/Redisson 限流工具類(lèi)的核心方法添加@SentinelResource,指定熔斷降級(jí)方法

// 在RedisLimitLuaUtil的fixedWindowLimit方法添加
@SentinelResource(value = "redisLimitLua", fallback = "fixedWindowFallback")
public boolean fixedWindowLimit(String limitDimension, String target, int limit, int expire) {
    // 原有邏輯
}
// 熔斷降級(jí)方法(參數(shù)與原方法一致)
public boolean fixedWindowFallback(String limitDimension, String target, int limit, int expire) {
    log.warn("Redis Lua限流觸發(fā)Sentinel熔斷,觸發(fā)本地降級(jí),目標(biāo):{}", target);
    return false; // 返回false觸發(fā)本地兜底
}

// 在RedissonLimitUtil的rateLimit方法添加
@SentinelResource(value = "redissonLimit", fallback = "rateLimitFallback")
public boolean rateLimit(String target, int rate, int rateInterval, RateIntervalUnit unit, int capacity) {
    // 原有邏輯
}
// 熔斷降級(jí)方法
public boolean rateLimitFallback(String target, int rate, int rateInterval, RateIntervalUnit unit, int capacity) {
    log.warn("Redisson令牌桶限流觸發(fā)Sentinel熔斷,觸發(fā)本地降級(jí),目標(biāo):{}", target);
    return false;
}

六、生產(chǎn)環(huán)境通用配置 & 監(jiān)控埋點(diǎn)

1. Redis 序列化優(yōu)化(避免默認(rèn) JDK 序列化問(wèn)題)

創(chuàng)建RedisConfig.java,替換為Jackson2JsonRedisSerializer,節(jié)省內(nèi)存且避免序列化兼容問(wèn)題:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // JSON序列化器
        Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSerializer.setObjectMapper(om);
        // String序列化器
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        // key采用String序列化
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        // value采用JSON序列化
        template.setValueSerializer(jacksonSerializer);
        template.setHashValueSerializer(jacksonSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

2. 限流監(jiān)控埋點(diǎn)(Micrometer+Prometheus)

添加監(jiān)控指標(biāo),統(tǒng)計(jì)限流次數(shù)、Redis 異常次數(shù)、本地降級(jí)次數(shù),方便 Grafana 可視化和告警:

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 限流監(jiān)控指標(biāo)工具類(lèi)
 */
@Component
public class LimitMonitorUtil {
    @Resource
    private MeterRegistry meterRegistry;
    // 限流拒絕次數(shù)
    private Counter limitRejectCounter;
    // Redis異常次數(shù)
    private Counter redisErrorCounter;
    // 本地降級(jí)次數(shù)
    private Counter localDegradeCounter;

    @PostConstruct
    public void initCounter() {
        limitRejectCounter = Counter.builder("redis.limit.reject.count")
                .description("Redis分布式限流拒絕請(qǐng)求次數(shù)")
                .register(meterRegistry);
        redisErrorCounter = Counter.builder("redis.limit.error.count")
                .description("Redis分布式限流Redis操作異常次數(shù)")
                .register(meterRegistry);
        localDegradeCounter = Counter.builder("redis.limit.local.degrade.count")
                .description("Redis分布式限流本地降級(jí)觸發(fā)次數(shù)")
                .register(meterRegistry);
    }

    // 記錄限流拒絕
    public void recordLimitReject() {
        limitRejectCounter.increment();
    }

    // 記錄Redis異常
    public void recordRedisError() {
        redisErrorCounter.increment();
    }

    // 記錄本地降級(jí)
    public void recordLocalDegrade() {
        localDegradeCounter.increment();
    }
}

使用示例:在限流判斷失敗處調(diào)用監(jiān)控方法:

if (!apiLimit || !ipLimit) {
    limitMonitorUtil.recordLimitReject(); // 記錄限流拒絕
    if (!limitDegradeUtil.localLimitFallback(apiTarget)) {
        limitMonitorUtil.recordLocalDegrade(); // 記錄本地降級(jí)
        return Result.fail(429, "請(qǐng)求過(guò)于頻繁");
    }
}

七、生產(chǎn)環(huán)境落地關(guān)鍵注意事項(xiàng)

  1. Redis 高可用:必須使用Redis 主從 + 哨兵Redis Cluster,開(kāi)啟RDB+AOF 混合持久化,避免 Redis 單點(diǎn)故障導(dǎo)致限流失效;
  2. 限流 key 設(shè)計(jì):遵循前綴:維度:目標(biāo)規(guī)范,避免鍵沖突,同時(shí)設(shè)置過(guò)期時(shí)間,防止 Redis 內(nèi)存泄漏;
  3. 避免熱點(diǎn) key:對(duì)高并發(fā)限流 key(如秒殺接口)采用分段限流(如按 IP 哈希到不同 key:limit:seckill:sku1001:{hash(ip)%10}),分擔(dān) Redis 單節(jié)點(diǎn)壓力;
  4. 動(dòng)態(tài)配置:所有限流規(guī)則(閾值、窗口、QPS)均從Nacos/Apollo加載,支持熱更新,無(wú)需重啟服務(wù);
  5. 異常隔離:Redis 操作添加超時(shí)時(shí)間(生產(chǎn)建議 200-500ms),避免 Redis 阻塞導(dǎo)致服務(wù)線(xiàn)程池耗盡;
  6. 降級(jí)兜底:本地限流的 QPS 必須遠(yuǎn)低于分布式限流,避免本地兜底被擊穿,同時(shí)結(jié)合 Sentinel 做熔斷;
  7. 監(jiān)控告警:對(duì)redis.limit.reject.countredis.limit.error.count設(shè)置告警閾值,及時(shí)發(fā)現(xiàn)限流規(guī)則不合理或 Redis 故障;
  8. 壓測(cè)驗(yàn)證:上線(xiàn)前通過(guò) JMeter/Gatling 做壓測(cè),驗(yàn)證限流規(guī)則的有效性和 Redis 的性能瓶頸。

總結(jié)

該模板是 Redis 分布式限流的生產(chǎn)級(jí)開(kāi)箱即用方案,核心亮點(diǎn):

  1. 雙核心限流:Lua 腳本(輕量原子)+ Redisson(開(kāi)箱即用),覆蓋 99% 生產(chǎn)場(chǎng)景;
  2. 網(wǎng)關(guān)統(tǒng)一限流:Spring Cloud Gateway 整合,實(shí)現(xiàn)全鏈路入口限流,避免邏輯散落;
  3. 高可用降級(jí):Redis 宕機(jī) / 異常時(shí)自動(dòng)觸發(fā) Guava 本地兜底,結(jié)合 Sentinel 熔斷,保證服務(wù)可用;
  4. 可配置可監(jiān)控:Nacos 動(dòng)態(tài)配置規(guī)則,Micrometer 埋點(diǎn)監(jiān)控,支持告警和可視化;
  5. 規(guī)范可擴(kuò)展:統(tǒng)一的 key 設(shè)計(jì)、工具類(lèi)封裝,支持多維度限流(接口 / IP / 用戶(hù) / 租戶(hù))和自定義擴(kuò)展。

使用時(shí)僅需根據(jù)自身業(yè)務(wù)調(diào)整限流規(guī)則、降級(jí) QPSRedis 部署方式,即可快速落地到生產(chǎn)環(huán)境。

到此這篇關(guān)于Redis分布式限流生產(chǎn)環(huán)境落地方案的文章就介紹到這了,更多相關(guān)Redis 分布式限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis連接報(bào)錯(cuò)error:NOAUTH Authentication required

    redis連接報(bào)錯(cuò)error:NOAUTH Authentication required

    本文主要介紹了redis連接報(bào)錯(cuò)error:NOAUTH Authentication required,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 基于Redission的分布式鎖實(shí)戰(zhàn)

    基于Redission的分布式鎖實(shí)戰(zhàn)

    本文主要介紹了基于Redission的分布式鎖實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • springboot中操作redis實(shí)例分享

    springboot中操作redis實(shí)例分享

    本文介紹了如何在Spring?Boot應(yīng)用中整合Redis緩存技術(shù),包括配置Redis連接、定義Redis模板、實(shí)現(xiàn)Redis的基本操作以及使用Spring?Cache注解。這些內(nèi)容可幫助開(kāi)發(fā)者快速掌握Spring?Boot與Redis的集成,并提高應(yīng)用性能。
    2023-06-06
  • Redis查看KEY的數(shù)據(jù)類(lèi)型的方法和步驟

    Redis查看KEY的數(shù)據(jù)類(lèi)型的方法和步驟

    在Redis中,可以使用 TYPE 命令來(lái)查看指定key的數(shù)據(jù)類(lèi)型,該命令會(huì)返回存儲(chǔ)在指定key中的值的數(shù)據(jù)類(lèi)型,本文給大家介紹了具體的使用方法和步驟,感興趣的朋友可以參考下
    2024-04-04
  • redis yml配置的用法小結(jié)

    redis yml配置的用法小結(jié)

    RedisYML配置是Redis的一種配置文件格式,,對(duì)Redis的配置進(jìn)行統(tǒng)一管理,本文就來(lái)介紹了redis yml配置的用法小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • redis+lua實(shí)現(xiàn)分布式限流的示例

    redis+lua實(shí)現(xiàn)分布式限流的示例

    本文主要介紹了redis+lua實(shí)現(xiàn)分布式限流的示例,可以實(shí)現(xiàn)復(fù)雜的限流邏輯,如滑動(dòng)窗口限流,并且避免了多步操作導(dǎo)致的并發(fā)問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • Redis整合SpringBoot的RedisTemplate實(shí)現(xiàn)類(lèi)(實(shí)例詳解)

    Redis整合SpringBoot的RedisTemplate實(shí)現(xiàn)類(lèi)(實(shí)例詳解)

    這篇文章主要介紹了Redis整合SpringBoot的RedisTemplate實(shí)現(xiàn)類(lèi),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Govern Service 基于 Redis 的服務(wù)治理平臺(tái)安裝過(guò)程詳解

    Govern Service 基于 Redis 的服務(wù)治理平臺(tái)安裝過(guò)程詳解

    Govern Service 是一個(gè)輕量級(jí)、低成本的服務(wù)注冊(cè)、服務(wù)發(fā)現(xiàn)、 配置服務(wù) SDK,通過(guò)使用現(xiàn)有基礎(chǔ)設(shè)施中的 Redis 不用給運(yùn)維部署帶來(lái)額外的成本與負(fù)擔(dān),接下來(lái)通過(guò)本文給大家分享Govern Service 基于 Redis 的服務(wù)治理平臺(tái)的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-05-05
  • 解析Redis未授權(quán)訪(fǎng)問(wèn)漏洞復(fù)現(xiàn)與利用危害

    解析Redis未授權(quán)訪(fǎng)問(wèn)漏洞復(fù)現(xiàn)與利用危害

    這篇文章主要介紹了Redis未授權(quán)訪(fǎng)問(wèn)漏洞復(fù)現(xiàn)與利用,介紹了redis未授權(quán)訪(fǎng)問(wèn)漏洞的基本概念及漏洞的危害,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • Redis實(shí)現(xiàn)短信登錄的企業(yè)實(shí)戰(zhàn)

    Redis實(shí)現(xiàn)短信登錄的企業(yè)實(shí)戰(zhàn)

    本文主要介紹了Redis實(shí)現(xiàn)短信登錄的企業(yè)實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07

最新評(píng)論

吉首市| 五原县| 邮箱| 临沧市| 盱眙县| 宣化县| 南木林县| 珲春市| 宣城市| 新河县| 乐都县| 阿克陶县| 高青县| 北辰区| 兴隆县| 城固县| 汽车| 邓州市| 从化市| 浪卡子县| 自贡市| 牟定县| 云龙县| 个旧市| 廊坊市| 绥阳县| 潜江市| 石首市| 泗阳县| 扎兰屯市| 广河县| 双辽市| 郸城县| 綦江县| 宁乡县| 中牟县| 长宁县| 丹寨县| 南江县| 南开区| 遵义市|