用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。

redis实现计数器的更多相关文章

  1. Redis原子计数器incr

    一.前言在一些对高并发请求有限制的系统或者功能里,比如说秒杀活动,或者一些网站返回的当前用户过多,请稍后尝试.这些都是通过对同一时刻请求数量进行了限制,一般用作对后台系统的保护,防止系统因为过大的流量 ...

  2. Redis原子计数器incr,防止并发请求

    转自:https://blog.csdn.net/Roy_70/article/details/78260826 一.前言在一些对高并发请求有限制的系统或者功能里,比如说秒杀活动,或者一些网站返回的当 ...

  3. Redis的使用模式之计数器模式实例

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/123.html?1455853785 Redis 是目前 NoSQL 领域 ...

  4. Redis非关系型数据库

    1.简介 Redis是一个基于内存的Key-Value非关系型数据库,由C语言进行编写. Redis一般作为分布式缓存框架.分布式下的SESSION分离.分布式锁的实现等等. Redis速度快的原因: ...

  5. redis实战笔记(5)-第5章 使用 Redis构建支持程序

    本章主要内容 1.使用Redis记录日 志 2.使用Redis实现计数器并进行数据统计 3.查询IP地址所属的城市与国家 4.服务的发现与配置   这一章将介绍如何使用Redis来帮助和支持系统的其他 ...

  6. Redis集群入门

    官方文章: https://redis.io/topics/cluster-tutorial#redis-cluster-configuration-parameters 本文永久地址: https: ...

  7. redis(7)LRU缓存

    一.LRU简介 LRU是Least Recently Used的缩写,即:最近最少使用. 它是内存管理中的一种页面置换算法,对于在内存中但是又不用的数据块,操作系统会根据哪些数据属于LRU而将其移除内 ...

  8. redis之进阶

    redis之进阶   redis redis介绍 redis的功能特性 1,高速读写 2,数据类型丰富 3,支持持久化 4,多种内存分配及回收策略 5,支持事务 6,消息队列.redis用的多的还是发 ...

  9. Redis基础知识、命令以及java操作Redis

    1 nosql的概念 sql:操作(关系型)数据库的标准查询语言 关系型数据库(rdbms):以关系(由行和列组成的二维表)模型为核心数据库,有表的储存系统.(mysql.oracle.sqlserv ...

随机推荐

  1. eclipse及idea使用问题记录

    使用eclipse或idea的时候会遇到各式各样的小问题,解决方案其实网上也大都搜得到,但是下次遇到的时候总是想不起来如何解决,还要花费时间再次查资料.所以以后把遇到的问题都记录一下. Eclipse ...

  2. 百钱百鸡小游戏PHP代码

    <?php // 计算小鸡的数量 $count=[]; // 第一个for循环计算公鸡 for ($gj=1;$gj<(100/5);$gj++){ // 第二个for循环计算母鸡 for ...

  3. Hive日期、时间转换:YYYY-MM-DD与YYYYMMDD;hh.mm.ss与hhmmss的相互转换

    思路 YYYY-MM-DD与YYYYMMDD:hh-mm-ss与hhmmss的相互转换有两种办法,第一种是利用UNIX时间戳函数,第二种是利用字符串拼接函数. YYYY-MM-DD与YYYYMMDD相 ...

  4. Lombok插件有望被Intellij IDEA收编以改善兼容性问题

    1. 前言 最近两个版本的Intellij IDEA没有办法使用lombok插件了,这种问题已经出现了多次,导致胖哥依然使用2020.1的旧版本.其实很多人和我一样也回滚到了旧版本.我一直认为是lom ...

  5. 报错:ER_NO_DEFAULT_FOR_FIELD: Field 'status' doesn't have a default value

    小白入门级错误,数据库插入数据时报错;ER_NO_DEFAULT_FOR_FIELD: Field 'status' doesn't have a default value  百度说是my.ini文 ...

  6. include标签—引用文件路径

    今天给大家讲解的是include标签,在打代码的时候总会出现一些重复的样式,这个时候就可以用include标签来减少打代码的次数. 文件名index.html,代码: {% from 'macros/ ...

  7. rtmp规范1.0全面指南

    RTMP(real time messaging protocol)协议 本文为Adobe rtmp规范1.0的中文介绍,其中内容大部分都是翻译自rtmp官方文档rtmp_specification_ ...

  8. 用 Java 拿下 HTML 分分钟写个小爬虫

    本文适合有 Java 基础知识的人群 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>系列,今天给大家带来一款开源 Java 版一款网页元素解析框架- ...

  9. php高效读取和写入

    /** * 删除非空目录里面所有文件和子目录 * @param string $dir * @return boolean */ function fn_rmdir($dir) { //先删除目录下的 ...

  10. 在Spring中拦截器的使用

    Filter Filter是Servlet容器实现的,并不是由Spring 实现的 下面是一个例子 import java.io.IOException; import javax.servlet.F ...