用redis实现计数器的例子

社交产品业务里有很多统计计数的功能,比如:

用户: 总点赞数,关注数,粉丝数
帖子: 点赞数,评论数,热度
消息: 已读,未读,红点消息数
话题: 阅读数,帖子数,收藏数

统计计数的特点
实时性要求高
写的频率很高
写的性能对MySQL是一个挑战
可以采用redis来优化高频率写入的性能要求。

redis优化方案一

对于每一个实体的计数,设计一个hash结构的counter:
//用户
counter:user:{userID}
                        ->  praiseCnt: 100      //点赞数
                        ->  hostCnt: 200        //热度
                        ->  followCnt: 332      //关注数
                        ->  fansCnt: 123        //粉丝数

//帖子
counter:topic:{topicID}
                        -> praiseCnt: 100       //点赞数
                        -> commentCnt: 322      //评论数

//话题
counter:subject:{subjectID}
                            -> favoCnt: 312     //收藏数
                            -> viewCnt: 321     //阅读数
                            -> searchCnt: 212   //搜索进入次数
                            -> topicCnt: 312    //话题中帖子数

类似这种计数器,随着产品功能的增加,也会越来越多,比如回复数,踩数,转发数什么的。

redis相关的命令

//获取指定userID的所有计数器
HGETALL counter:user:{userID}  

//获取指定userID的指定计数器
HMGET counter:user:{userID}  praiseCnt hostCnt

//指定userID点赞数+1
HINCRBY counter:user:{userID}   praiseCnt

缺点:

这样设计,如果要批量查询多个用户的数据,就比较麻烦,例如一次要查指定20个userID的计数器?只能循环执行 HGETALL counter:user:{userID}。
优点:

以实体聚合数据,方便数据管理

redis优化方案二

方案二是用来解决方案一的缺点的,依然是采用hash,结构设计是这样的:

counter:user:praiseCnt
                        ->  userID_1001: 100
                        ->  userID_1002: 200
                        ->  userID_1003: 332
                        ->  userID_1004: 123
                                .......
                        ->  userID_9999: 213

 

counter:user:hostCnt
                        ->  userID_1001: 10
                        ->  userID_1002: 290
                        ->  userID_1003: 322
                        ->  userID_1004: 143
                                .......
                        ->  userID_9999: 213

counter:user:followCnt
                        ->  userID_1001: 21
                        ->  userID_1002: 10
                        ->  userID_1003: 32
                        ->  userID_1004: 203
                                .......
                        ->  userID_9999: 130

获取多个指定userID的点赞数的命令变成这样了:

HMGET counter:user:praiseCnt userID_1001 userID_1002

上面命令可以批量获取多个用户的点赞数,时间复杂度为O(n),n为指定userID的数量。

优点:

解决了批量操作的问题

缺点:

当要获取多个计数器,比如同时需要praiseCnt,hostCnt时,要读多次,不过要比第一种方案读的次数要少。
一个hash里的字段将会非常宠大,HMGET也许会有性能瓶颈。
用redis管道(Pipelining)来优化方案一

对于第一种方案的缺点,可以通过redis管道来优化,一次性发送多个命令给redis执行:

$userIDArray = array(1001, 1002, 1003, 1009);

$pipe = $redis->multi(Redis::PIPELINE);
foreach ($userIDArray as $userID) {
    $pipe->hGetAll('counter:user:' . $userID);
}

$replies = $pipe->exec();
print_r($replies); 

还有一种方式是在redis上执行lua脚本,前提是你必须要学会写lua。

时间: 2024-07-28 23:13:45

用redis实现计数器的例子的相关文章

PHP制作图型计数器的例子

计数器 以前在奥索看见过很多这样的例子,各各方法复杂,请看如下例子实现图形计数器.在网页中使用请用 <script src="http://文件地址"></script> <? //存放计数的文本文件 $count="count.txt"; //计数器的位数,如果不填则默认为6位 $wei=""; //图像的URL路径 $tu="http://127.0.0.1/tcount/images"; ?

PHP制作图型计数器的例子_php基础

以前在奥索看见过很多这样的例子,各各方法复杂,请看如下例子实现图形计数器.在网页中使用请用 <script src="http://文件地址"></script> <? //存放计数的文本文件 $count="count.txt"; //计数器的位数,如果不填则默认为6位 $wei=""; //图像的URL路径 $tu="http://127.0.0.1/tcount/images"; ?>

php Redis存储Session的例子详解

安装redis服务以及php redis扩展 一:redis安装 Download, extract and compile Redis with: $ wget http://download.redis.io/releases/redis-3.0.4.tar.gz $ tar xzf redis-3.0.4.tar.gz $ cd redis-3.0.4 $ make The binaries that are now compiled are available in the src di

redis 队列操作的例子(php)_php技巧

入队操作 复制代码 代码如下: <?php $redis = new Redis(); $redis->connect('127.0.0.1',6379); while(True){ try{ $value = 'value_'.date('Y-m-d H:i:s'); $redis->LPUSH('key1',$value); sleep(rand()%3); echo $value."\n"; }catch(Exception $e){ echo $e->g

一个图形计数器的例子

import java.io.*; import java.util.*; import com.sun.image.codec.jpeg.*; import javax.servlet.*; import javax.servlet.http.*; import java.awt.*; import java.awt.image.*; public class JPEGServlet extends HttpServlet { private String strFile="c:count.t

Redis(3.2.3)集群部署实战

一.Redis简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis官网地址:http://redis.io/ Redis中文网地址:http://redis.cn Redis中文文档地址:http://redisdoc.com 二.Redis安装 系统环境:CentOS 6.8 mininal 初始化完成       下载,解压,编译: wget http://download.redis.i

《Redis官方文档》Redis集群教程

原文链接 译文链接 译者: tiffany 这篇教程是Redis集群的简要介绍,而非讲解分布式系统的复杂概念.它主要从一个使用者的角度介绍如何搭建.测试和使用Redis集群,至于Redis集群的详细设计将在"Redis集群规范"中进行描述. 本教程以redis使用者的角度,用简单易懂的方式介绍Redis集群的可用性和一致性. 注意: 本教程要求redis3.0或以上的版本. 如果你打算部署redis集群,你可以读一些关于集群的详细设计,当然,这不是必须的.由这篇教程入门,先大概使用一下

Redis数据库的使用场景介绍(避免误用Redis)_Redis

Redis 是目前 NoSQL 领域的当红炸子鸡,它象一把瑞士军刀,小巧.锋利.实用,特别适合解决一些使用传统关系数据库难以解决的问题.但是 Redis 不是银弹,有很多适合它解决的问题,但是也有很多并不适合它解决的问题.另外,Redis 作为内存数据库,如果用在不适合的场合,对内存的消耗是很可观的,甚至会让系统难以承受. 我们可以对系统存储使用的数据以两种角度分类,一种是按数据的大小划分,分成大数据和小数据,另一种是按数据的冷热程度划分,分成冷数据和热数据,热数据是指读或写比较频繁的数据,反之

不用图像组件的ASP图像计数器

计数器 前几天看了netnice和qzsage君的贴子,颇有启发,于是着手编了一个图像计数器,这个图像计数器没有用图像组件,也不是以前那样用几张图片拼起来,而是用了*.xbm的图片格式.这种格式可能只能在Windows+IE下才能显示.具体的思路是这样:图片用点阵的形式表示,比如2: 00111100 0011为3 1100为C 即0x3c01100110 0110为6 0110为6 0x6601100000 ....... 0x表示十六进制数.01100000 依此类推00110000 这是用