计数器在很多网站中都进行了广泛的应用,比如文章的点赞数、页面的浏览数、网站的访客数、视频的播放数等等。在这篇文章里,我会使用 Redis 的三种数据类型,来分别实现计数器的功能。
请跟随我一起来看看吧。
下面代码演示了如何利用 Redis 中的字符串键来实现计数器功能。其中,incr() 方法用于累加计数,get_cnt() 方法用于获取当前的计数值。
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 的哈希键,来对关联的统计项进行统一管理。
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 对应的字段中即可。
在上面两个例子中,当动作被执行时,程序可以调用一次 incr() 累加计数的方法。某些场景下,我们可能需要对特定的动作,仅仅计数一次。什么叫“仅仅计数一次”?就是说,同一个用户/IP,多次访问某个页面,计数器只会将计数值增加 1。来看看以下代码:
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
在实际应用中,以上代码需要稍作改动,但基本的思路不变。怎么样,你学会了吗?
前段时间基础架构组、DBA还有云盘团队一起推广了phpredis的RedisCluster的线上使用,目前线上业务已经稳定,单业务的规模水平是:Qps平均15W,数据量在700G左右。现对这段时间的工作和所遇到的一些常见问题进行简单总结
redis常用数据结构strig、list、hash、set、zset,这是最常用的5中redis数据结构,其实还有些不太常用的数据结构比如:HyperLogLog、GeoHash、PubSub等
redis 是当前非常流行的缓存数据库,得益于其简单的 key-value 模式的数据存储和丰富的数据类型与事件机制使得 redis 成为当前后端开发中不可或缺的利器。下面推荐一些好用的 redis 的管理工具
前段时间组内有个投票的产品,上线前考虑欠缺,导致被刷票严重。后来,通过研究,发现可以通过 redis lua 脚本实现限流,这里将 redis lua 脚本相关的知识分享出来,讲的不到位的地方还望斧正。
Redis在Php项目中的实际应用场景:商品维度计数、用户维度计数、存储社交关系、用作缓存代替memcached、反spam系统、用户Timeline/Feeds、最新列表&排行榜、消息通知、将Redis用作消息队列
php调用redis进去读写操作,大并发下会出现:读取key1,没有内容则写入内容,但是大并发下会出现同时多个php进程写入的情况,这个时候需要加一个锁,即获取锁的php进程有权限写。
Redis配置成主从模式,主库(Master)只负责写数据,从库(Slave)只负责读数据。一个主库可以拥有多个从库,但一个从库只能隶属于一个主库。
连接操作命令,持久化,远程服务控制,对value操作的命令,String,List,Set,Hash,Redis 发布订阅命令,Redis 事务命令,查看keys个数,清空数据库
目前有很多成熟的缓存产品,包括Redis,memcached等。这里以Redis为例来分析下使用缓存实现分布式锁的方案。主要的实现方式是使用Jedis.setNX方法来实现。以上实现方式同样存在几个问题:
说到分布式缓存,可能大多数人脑海浮现的就是redis了,为什么redis能够在竞争激烈的缓存大战中脱颖而出呢?原因无非有一下几点:性能好,丰富的特性跟数据结构,api操作简单。但是用的人多了,就会出现很多不规范或者疏忽的地方,严重的时候甚至会导致生产事故
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!