This article was originally written by Yanglbme and originally published in Nuggets. Unauthorized republication is prohibited.

Counters are widely used in many websites, such as the number of likes for articles, page views, website visitors, video plays and so on. In this article, I will use the three data types of Redis to implement counters separately.

Please follow me to find out.

Using string keys

The following code demonstrates how to use the string key in Redis to implement the counter function. The incr() method is used to accumulate the count, and the get_cnt() method is used to get the current count.

from redis import Redis

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

    def incr(self, amount=1):
        """ Count accumulation """
        self.client.incr(self.key, amount=amount)

    def decr(self, amount=1):
        """ Count decay """
        self.client.decr(self.key, amount=amount)

    def get_cnt(self):
        """ Gets the value of the current count """
        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

Copy the code

If we want to count the number of page views with page_id 12, we can set the key to page_view:12 and call the incr() method of counter every time the user visits the page.

Use hash keys

In the above code, we need to set a separate string key for each statistic. So, let’s see how Redis hash keys can be used to unify the management of associated statistics.

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):
        """ Count accumulation """
        self.client.hincrby(self.key, self.counter, amount=amount)

    def decr(self, amount=1):
        """ Count decay """
        self.client.hincrby(self.key, self.counter, amount=-amount)

    def get_cnt(self):
        """ Gets the value of the current count """
        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

Copy the code

If we use hash keys, then we can use the same key for the same type of count. For example, in the above example, we use page_view to count the number of page views, for page_id 66, directly add to the page_view corresponding field.

Using the Set key

In the two examples above, the program can call the incr() summation method once when the action is executed. In some cases, we may need to count only once for a particular action. What do you mean “count only once”? That is, if the same user /IP accesses the same page multiple times, the counter will only increment its value by one. Take a look at the following code:

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:
        "" count summation, if item already exists before count, return False; Otherwise return True"""
        return self.client.sadd(self.key, item) == 1

    def get_cnt(self):
        """ Gets the value of the current count """
        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')  # repeat insert
    print(counter.get_cnt())  # 2

Copy the code

In practice, the above code needs to be modified slightly, but the basic idea remains the same. So, did you get it?

Welcome to follow my wechat public account “Doocs Open Source Community” and push original technical articles as soon as possible.