Redis 多方式實現計數器功能(附代碼)

本文由 yanglbme 原創,首發於掘金,禁止未受權轉載。python

計數器在不少網站中都進行了普遍的應用,好比文章的點贊數、頁面的瀏覽數、網站的訪客數、視頻的播放數等等。在這篇文章裏,我會使用 Redis 的三種數據類型,來分別實現計數器的功能。git

請跟隨我一塊兒來看看吧。github

使用字符串鍵

下面代碼演示瞭如何利用 Redis 中的字符串鍵來實現計數器功能。其中,incr() 方法用於累加計數,get_cnt() 方法用於獲取當前的計數值。redis

from redis import Redis

class Counter:
    def __init__(self, client: Redis, key: str):
        self.client = client
        self.key = key

    def incr(self, amount=1):
        """計數累加"""
        self.client.incr(self.key, amount=amount)

    def decr(self, amount=1):
        """計數累減"""
        self.client.decr(self.key, amount=amount)

    def get_cnt(self):
        """獲取當前計數的值"""
        return self.client.get(self.key)


if __name__ == '__main__':
    client = Redis(decode_responses=True)
    counter = Counter(client, 'page_view:12')
    counter.incr()
    counter.incr()
    print(counter.get_cnt())  # 2

複製代碼

假設咱們要統計 page_id 爲 12 的頁面的瀏覽數,那麼咱們能夠設定 key 爲 page_view:12,用戶每一次瀏覽,就調用一次 counter 的 incr() 方法進行計數。網站

使用哈希鍵

在上面的代碼中,咱們須要針對每一個統計項,都單獨設置一個字符串鍵。那麼,下面咱們來看看如何經過 Redis 的哈希鍵,來對關聯的統計項進行統一管理。spa

from redis import Redis

class Counter:
    def __init__(self, client: Redis, key: str, counter: str):
        self.client = client
        self.key = key
        self.counter = counter

    def incr(self, amount=1):
        """計數累加"""
        self.client.hincrby(self.key, self.counter, amount=amount)

    def decr(self, amount=1):
        """計數累減"""
        self.client.hincrby(self.key, self.counter, amount=-amount)

    def get_cnt(self):
        """獲取當前計數的值"""
        return self.client.hget(self.key, self.counter)


if __name__ == '__main__':
    client = Redis(decode_responses=True)
    counter = Counter(client, 'page_view', '66')
    counter.incr()
    counter.incr()
    print(counter.get_cnt())  # 2

複製代碼

若是採用哈希鍵,那麼,咱們對於同一類型的計數,可使用一個相同的 key 來進行存儲。好比,在上面例子中,咱們使用 page_view 來統計頁面的瀏覽數,對於 page_id 爲 66 的頁面,直接添加到 page_view 對應的字段中便可。code

使用集合鍵

在上面兩個例子中,當動做被執行時,程序能夠調用一次 incr() 累加計數的方法。某些場景下,咱們可能須要對特定的動做,僅僅計數一次。什麼叫「僅僅計數一次」?就是說,同一個用戶/IP,屢次訪問某個頁面,計數器只會將計數值增長 1。來看看如下代碼:cdn

from redis import Redis

class Counter:
    def __init__(self, client: Redis, key: str):
        self.client = client
        self.key = key

    def add(self, item: str) -> bool:
        """計數累加,若計數以前item已存在,放回False;不然返回True"""
        return self.client.sadd(self.key, item) == 1

    def get_cnt(self):
        """獲取當前計數的值"""
        return self.client.scard(self.key)


if __name__ == '__main__':
    client = Redis(decode_responses=True)
    counter = Counter(client, 'uv')
    counter.add('user1')
    counter.add('user2')
    counter.add('user1')  # 重複放入
    print(counter.get_cnt())  # 2

複製代碼

在實際應用中,以上代碼須要稍做改動,但基本的思路不變。怎麼樣,你學會了嗎?視頻

歡迎掃碼關注個人公衆號「Doocs開源社區」。字符串

相關文章
相關標籤/搜索