本文由 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開源社區」。字符串