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

Redis利用原子操作(INCR,DECR)實(shí)現(xiàn)分布式計(jì)數(shù)器

 更新時(shí)間:2025年07月31日 09:05:35   作者:冰糖心書房  
在分布式系統(tǒng)中,由于多個(gè)服務(wù)實(shí)例需要共享和修改同一個(gè)計(jì)數(shù)值,實(shí)現(xiàn)一個(gè)準(zhǔn)確、高效的分布式計(jì)數(shù)器至關(guān)重要,下面我們就來看看具體實(shí)現(xiàn)方法吧

在分布式系統(tǒng)中,由于多個(gè)服務(wù)實(shí)例需要共享和修改同一個(gè)計(jì)數(shù)值,實(shí)現(xiàn)一個(gè)準(zhǔn)確、高效的分布式計(jì)數(shù)器至關(guān)重要。Redis 憑借其內(nèi)存存儲(chǔ)的高性能和原子操作命令,成為實(shí)現(xiàn)這一功能的理想選擇。

核心原理:Redis 的原子操作

Redis 的單線程命令處理模型確保了單個(gè)命令的執(zhí)行是原子性的。 這意味著當(dāng)一個(gè)命令正在執(zhí)行時(shí),不會(huì)被其他客戶端的命令打斷。對(duì)于計(jì)數(shù)器而言,INCRDECR 這兩個(gè)命令是核心。

  • INCR key: 將存儲(chǔ)在 key 的數(shù)字值增一。如果 key 不存在,那么 key 的值會(huì)先被初始化為 0,然后再執(zhí)行 INCR 操作。
  • DECR key: 將 key 中儲(chǔ)存的數(shù)字值減一。如果 key 不存在,其值同樣會(huì)先被初始化為 0 再執(zhí)行 DECR

這兩個(gè)操作的原子性是實(shí)現(xiàn)分布式計(jì)數(shù)器的基石,它保證了即使在大量并發(fā)請(qǐng)求下,計(jì)數(shù)結(jié)果也是準(zhǔn)確的,避免了“讀取-修改-寫入”模式中可能出現(xiàn)的競(jìng)態(tài)條件。

基本實(shí)現(xiàn)方法

實(shí)現(xiàn)一個(gè)基本的分布式計(jì)數(shù)器非常簡(jiǎn)單,只需要為你的計(jì)數(shù)器定義一個(gè)唯一的鍵(key),然后調(diào)用相應(yīng)的原子命令即可。

使用場(chǎng)景示例:

  • 文章閱讀量統(tǒng)計(jì): 每當(dāng)有用戶閱讀一篇文章,就對(duì)該文章的計(jì)數(shù)器執(zhí)行 INCR。
  • 在線用戶數(shù): 用戶登錄時(shí)執(zhí)行 INCR,登出時(shí)執(zhí)行 DECR。
  • 庫(kù)存管理: 用戶下單時(shí)執(zhí)行 DECR,取消訂單或補(bǔ)貨時(shí)執(zhí)行 INCR

Python 代碼示例 (使用redis-py)

import redis

# 連接到 Redis
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

def get_post_views(post_id: int) -> int:
    """獲取文章的閱讀量"""
    key = f"post:{post_id}:views"
    view_count = r.get(key)
    return int(view_count) if view_count else 0

def increment_post_views(post_id: int) -> int:
    """增加文章的閱讀量"""
    key = f"post:{post_id}:views"
    # INCR 是原子操作,返回增加后的值
    return r.incr(key)

# --- 使用示例 ---
post_id = 123
print(f"文章 {post_id} 的初始閱讀量: {get_post_views(post_id)}")

# 模擬10次并發(fā)的閱讀請(qǐng)求
for _ in range(10):
    new_views = increment_post_views(post_id)
    print(f"閱讀量已增加至: {new_views}")

print(f"文章 {post_id} 的最終閱讀量: {get_post_views(post_id)}")

Java 代碼示例 (使用Jedis)

import redis.clients.jedis.Jedis;

public class DistributedCounter {

    private final Jedis jedis;

    public DistributedCounter(String host, int port) {
        this.jedis = new Jedis(host, port);
    }

    public long increment(String key) {
        // incr 是原子操作
        return jedis.incr(key);
    }

    public long decrement(String key) {
        // decr 是原子操作
        return jedis.decr(key);
    }

    public long getCount(String key) {
        String value = jedis.get(key);
        return value != null ? Long.parseLong(value) : 0;
    }

    public static void main(String[] args) {
        DistributedCounter counter = new DistributedCounter("localhost", 6379);
        String counterKey = "online_users";

        System.out.println("初始在線人數(shù): " + counter.getCount(counterKey));

        // 模擬用戶登錄
        long user1_login = counter.increment(counterKey);
        System.out.println("用戶1登錄,當(dāng)前在線人數(shù): " + user1_login);

        long user2_login = counter.increment(counterKey);
        System.out.println("用戶2登錄,當(dāng)前在線人數(shù): " + user2_login);

        // 模擬用戶登出
        long user1_logout = counter.decrement(counterKey);
        System.out.println("用戶1登出,當(dāng)前在線人數(shù): " + user1_logout);

        System.out.println("最終在線人數(shù): " + counter.getCount(counterKey));
    }
}

處理需要重置的計(jì)數(shù)器(例如每日計(jì)數(shù))

在某些場(chǎng)景下,計(jì)數(shù)器需要定期重置,例如統(tǒng)計(jì)每日活躍用戶或每日API調(diào)用次數(shù)。一種常見的錯(cuò)誤做法是先 INCR,再用 EXPIRE 設(shè)置過期時(shí)間。這種方式存在競(jìng)態(tài)條件:如果在 INCR 執(zhí)行后、EXPIRE 執(zhí)行前,服務(wù)發(fā)生故障,這個(gè)鍵就會(huì)永久存在,導(dǎo)致計(jì)數(shù)器無(wú)法自動(dòng)重置。

正確的做法是使用 Lua 腳本將 INCREXPIRE 捆綁成一個(gè)原子操作。

Lua 腳本示例

-- increment_with_ttl.lua
local key = KEYS[1]
local ttl = ARGV[1]

local count = redis.call("INCR", key)

-- 如果是第一次增加(即增加后的值為1),則設(shè)置過期時(shí)間
if count == 1 then
    redis.call("EXPIRE", key, ttl)
end

return count

在應(yīng)用程序中,通過 EVAL 命令執(zhí)行此腳本,可以確保增加計(jì)數(shù)和設(shè)置過期時(shí)間這兩步操作的原子性。

復(fù)雜操作與事務(wù)

如果需要根據(jù)計(jì)數(shù)值執(zhí)行更復(fù)雜的操作(例如,檢查庫(kù)存是否足夠再減庫(kù)存),簡(jiǎn)單的 DECR 可能不夠用。雖然可以使用 WATCH, MULTI, EXEC 事務(wù)來解決,但這會(huì)增加代碼的復(fù)雜性。 在這種情況下,使用 Lua 腳本通常是更簡(jiǎn)單、更高效的選擇,因?yàn)樗鼘⒄麄€(gè)邏輯封裝在服務(wù)器端作為一個(gè)原子單元執(zhí)行。

總結(jié)

利用 Redis 的 INCRDECR 原子操作是實(shí)現(xiàn)分布式計(jì)數(shù)器的標(biāo)準(zhǔn)且高效的方法。其核心優(yōu)勢(shì)在于 Redis 保證了單個(gè)命令的原子性,從而避免了分布式環(huán)境下的競(jìng)態(tài)條件。對(duì)于需要自動(dòng)重置的計(jì)數(shù)器,強(qiáng)烈建議使用 Lua 腳本來確保操作的原子性,防止數(shù)據(jù)不一致。

到此這篇關(guān)于Redis利用原子操作(INCR,DECR)實(shí)現(xiàn)分布式計(jì)數(shù)器的文章就介紹到這了,更多相關(guān)Redis分布式計(jì)數(shù)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis?持久化原理分析和使用建議詳解

    Redis?持久化原理分析和使用建議詳解

    本文主要介紹了Redis提供的三大持久化機(jī)制,即AOF日志、RDB快照以及混合持久化機(jī)制,結(jié)合圖文實(shí)例給大家講解的非常詳細(xì),感興趣的朋友一起看看吧
    2025-02-02
  • Redis哨兵模式的實(shí)現(xiàn)

    Redis哨兵模式的實(shí)現(xiàn)

    Redis的哨兵模式是一種用于自動(dòng)監(jiān)控Redis實(shí)例狀態(tài)并在主服務(wù)器出現(xiàn)故障時(shí)自動(dòng)切換到從服務(wù)器的機(jī)制,本文主要介紹了Redis哨兵模式的實(shí)現(xiàn),感興趣的可以了解一下
    2024-02-02
  • Redis字符串String操作詳解從基礎(chǔ)到高級(jí)應(yīng)用小結(jié)

    Redis字符串String操作詳解從基礎(chǔ)到高級(jí)應(yīng)用小結(jié)

    本文全面解析Redis字符串類型,涵蓋設(shè)置、修改、數(shù)字運(yùn)算、過期處理及分布式鎖、計(jì)數(shù)器等高級(jí)應(yīng)用,提供基礎(chǔ)命令與性能優(yōu)化策略,助開發(fā)者高效利用這一核心數(shù)據(jù)類型實(shí)現(xiàn)緩存、統(tǒng)計(jì)等功能,感興趣的朋友一起看看吧
    2025-07-07
  • Redis集群方案

    Redis集群方案

    前段時(shí)間搞了搞Redis集群,想用做推薦系統(tǒng)的線上存儲(chǔ),說來挺有趣,這邊基礎(chǔ)架構(gòu)不太完善,因此需要我們做推薦系統(tǒng)的自己來搭這個(gè)存儲(chǔ)環(huán)境,就自己折騰了折騰
    2020-07-07
  • Redis Tag 字段詳解與最佳實(shí)踐

    Redis Tag 字段詳解與最佳實(shí)踐

    本文將深入介紹Tag 字段的工作原理、創(chuàng)建方式、查詢語(yǔ)法,以及常見場(chǎng)景下的最佳實(shí)踐與注意事項(xiàng),對(duì)Redis Tag字段相關(guān)知識(shí)感興趣的朋友一起看看吧
    2025-07-07
  • 通過kubesphere部署redis的方法

    通過kubesphere部署redis的方法

    這篇文章主要介紹了通過kubesphere部署redis的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • redis的持久化和緩存機(jī)制解讀

    redis的持久化和緩存機(jī)制解讀

    這篇文章主要介紹了redis的持久化和緩存機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Redis慢日志的實(shí)現(xiàn)示例

    Redis慢日志的實(shí)現(xiàn)示例

    慢查詢?nèi)罩臼荝edis提供的一個(gè)用于觀察系統(tǒng)性能的功能,本文主要介紹了Redis慢日志的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • Redis報(bào)錯(cuò):Could not create server TCP listening socket 127.0.0.1:6379: bind:解決方法

    Redis報(bào)錯(cuò):Could not create server TCP 

    這篇文章主要介紹了Redis報(bào)錯(cuò):Could not create server TCP listening socket 127.0.0.1:6379: bind:解決方法,是安裝與啟動(dòng)Redis過程中比較常見的問題,需要的朋友可以參考下
    2023-06-06
  • reids自定義RedisTemplate以及亂碼問題解決

    reids自定義RedisTemplate以及亂碼問題解決

    本文主要介紹了reids自定義RedisTemplate以及亂碼問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04

最新評(píng)論

会昌县| 奉新县| 永嘉县| 乌兰县| 射阳县| 电白县| 遵义县| 北海市| 郁南县| 金沙县| 汉沽区| 鄂托克前旗| 乌鲁木齐县| 迁西县| 阿尔山市| 黔东| 镇安县| 博湖县| 文山县| 黄石市| 盘锦市| 文安县| 岑巩县| 四川省| 高青县| 霸州市| 广元市| 鄂伦春自治旗| 林甸县| 张掖市| 吉木萨尔县| 绵竹市| 廊坊市| 龙口市| 加查县| 周口市| 萨迦县| 五台县| 蓬莱市| 绿春县| 屯留县|