计数场景的优化

前言

社交网络信息爆发,如何衡量你在社交舆论上的影响力?计数!

计数是应用最方便、简单实现的数据挖掘应用,拿Facebook举例,你的Feed被评论多少次,转发多少次,赞多少次,被浏览多少次,你有多少个好友等等。可以说计数得多少的价值可能超过你本身或者你发布的内容本身。

今天着重介绍下Redis在计数器场景上的应用。

正文

对于计数器大家肯定还有或多或少的疑问。

Q1:计数从哪里来?

通常我们发布的社交内容会存储在数据库中,最常见的如MySQL:

更新索引:insert into user_message(uid,messageid) values(‘xx’,’xx’)

更新内容:insert into message_2013_05(messageid,message) values(‘xx’,‘xx’);

为什么要进行索引和内容区分我这里就不多熬述了,这时要计算我有发送了多少个message,再mysql库中select count(messageid) where uid=xxx 就可以获得我们想要得计数,也就说大多数情况它源于我们的索引数据

Q2:计数和其他数据相比有什么特点?

1.单key读写频繁,总体读取量我们认为可能比内容模块还要频繁,索引的增删改查都会导致计数器的频繁增减。尤其当某篇twitter,feed,weibo非常火爆时,单key的更新将更加火爆。

2.需要持久化,所有用户都可能需啊知道自己的计数,这个数据和内容本身一样重要。

从上面这两个需求来看选用Redis就是水到渠成了,而应对hotkey从Mysql update count+1 & Memcache 替换成Redis incr更是优雅很多。减少了很多数据一致性的风险。

优化的思路:

  • 单独维护计数,从获取更新复杂度O(n)到O(1)

我们知道随着单个uid->message的个数越来越多,而count(message_id)的逻辑复杂度是O(n),获取这个计数的成本是越来越大。如何让其获取变为O(1)?其实很简单,我们只要单独维护一下这个计数就可以了。举一个简单的例子来说明:

假设我们有个字段,我们需要频繁的获取和更新这个字段的长度,引用Redisbook(http://www.redisbook.com/)中的一段对于redis 用于存储key value的sds的描述好像能简单的叙述这件事情。

比如说, hello world 在 C 语言中就可以表示为 "hello world\0" 。

这种简单的字符串表示在大多数情况下都能满足要求,但是,它并不能高效地支持长度计算和追加(append)这两种操作:

  • 每次计算字符串长度(strlen(s))的复杂度为 θ(N) 。
  • 对字符串进行 N 次追加,必定需要对字符串进行 N 次内存重分配(realloc)。

struct sdshdr {

len = 11;

free = 0;

buf = “hello world\0″; // buf 的实际长度为 len + 1

};

通过 len 属性, sdshdr 可以实现复杂度为 θ(1) 的长度计算操作。

  • 前端还是后端维护计数,哪个更优?

前端维护:当发生message_id的增减时,client端进行一次transaction提交,索引更新及计数更新。优点是逻辑比较简单,就是原来单次写入变成了多次写入,缺点是易引起数据不一致。

后端维护:当数据库接收到message索引增减后,会产生相应的操作log,对于MySQL来说就是Binlog,我们根据mysql insert及delete 对索引计数进行增减操作。

不推荐MySQL及MySQL 触发器更新的原因有如下几个:

1.Mysql本身可能成为更新瓶颈。mysql update其实是一种重更新,在buffer pool未命中的情况下,需要把where id=xxx的page从磁盘加载到内存中,在大并发的hot key更新时,这点很有可能成为瓶颈。

2.Mysql Replication的效率问题。Mysql Replication在如上写入更新频繁的情况下,也会成为瓶颈,当你的发了一篇feed,却发现过了一分钟计数才更新,这个肯定是不能容忍的。

3.Mysql trigger相关bug比较多:

如下是我们线上环境遇到的一个trigger引发的同步中断问题:http://bugs.mysql.com/bug.php?id=53079

后端维护的思路

详细可见 @jackbillow http://www.programmer.com.cn/14577/ 中使用Redis方法

其实选择前端维护还是后端维护实际应该取决于你们公司前端及后端技术成熟程度,如果后端技术足够成熟,那么放在后端维护节省的就是大量的开发时间和降低数据一致性的风险,反之,可以放在前端进行维护。

  • Redis内存容量优化

Redis kv数据结构如下:

对于简单的k-v场景来说,最好的优化思路就是将图中Redis本身为了通用性创建的dict(16字节)及Redis Object(16字节)去除,sds的额外字节去除,这样假设你的key占用10字节,value 采用int占用4字节:

那么去除之前可能占用的内存是:

string类型的内存大小 = 键值个数 * (dictEntry大小16字节 + redisObject大小16字节 + 包含key的sds大小 + 包含value的sds大小) + bucket个数 * 4

去除之后:

string类型的内存大小 =键值个数 * (key的大小10字节 + value的4字节)+bucket个数 * 4

当你有数亿个key的时候,节省的内容容量将会是相当可观的,当然实际优化的场景肯定会比现在列几个公式复杂,有得必有失。

  • 未来计数场景畅想

Redis数据不能将老数据平滑过度到磁盘,无法应用到现SSD等高性能设备是硬伤。

http://nosql.mypopescu.com/post/3745773666/redis-and-hbase-for-mozilla-grouperfish-storage 这篇文章给了不错的思考方向。

计数场景的优化,布布扣,bubuko.com

时间: 2024-10-11 17:54:33

计数场景的优化的相关文章

阿里价值“千万”的秒杀场景参数优化

秒杀最早来自天猫双11各种商品的促销活动中,现在已经有很多业务场景在使用,比如抢红包,抢票等.其特点有三高:瞬时并发高,数据一致性高,热点更新频度高.这样三高的场景下往往给数据库造成极大的压力,大量更新数据库中的同一行,这样必然会产生锁等待,导致数据库的性能急剧下降的问题,很容易出现雪崩效应.笔者记得有一年春节,一个电视台定时在整点发放红包,结果由于压力太高,导致更新数据库红包数额的请求全部堆积,业务全部挂掉,面对这样的情况我们当时也束手无策. 面对秒杀业务的场景,数据库成为了底层系统中最重要的

特殊场景Sql优化

一.大表的大数据量修改 问题: 1.大量的行级锁,长时间阻塞   2.主从延时,大批数据不一致 解决方法: 分批次修改 二.大表的表结构修改 问题:长时间锁表 解决方法: 1.从库修改,主从切换,主库修改 (主从切换有风险) 2.建新表: 旧表数据导入到新表:旧表加触发器把新数据同步到新表:旧表加排他锁,新表重命名: 删除旧表 (使用工具, pt-online-schema-change) 三.优化not in/<> 子查询 not in + 子查询, 变换成 join 四.使用汇总表 例子:

详解 Redis 应用场景及应用实例

Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMware主持. 1. MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题: 1.MySQL需要不断进行拆库拆表,Memc

详解 Redis 应用场景及原理

本文转自https://blog.csdn.net/niucsd/article/details/50966733,描述了redis实现原理和应用场景,篇幅较长,有意学习redis的同学可耐心阅读. Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMware主持. 1. MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过M

国内外三个领域巨头告诉你Redis怎么用

随着数据体积的激增,MySQL+memcache已经满足不了大型互联网类应用的需求,许多机构也纷纷选择Redis作为其架构上的补充.这里我们将为大家分享社交巨头新浪微博.传媒巨头Viacom及图片分享领域佼佼者Pinterest带来的Redis实践. 新浪微博:史上最大的Redis集群 Tape is Dead,Disk is Tape,Flash is Disk,RAM Locality is King. — Jim Gray Redis不是比较成熟的memcache或者Mysql的替代品,是

Netty in Action (十四) 第五章节 第三部分 ByteBufHolder,ByteBuf分配,计数引用

5.4 Interface ByteBufHolder 我们经常在ByteBuf中存储一些正常数据之外,我们有时候还需要增加一些各式各样的属性值,一个Http响应体就是一个很好的例子,除了按照字节传输过来的主体内容,还有状态码,cookie等信息 Netty提供了ByteBufHolder来处理这些常用的用户案例,ByteBufHolder还提供了Netty一些其他的先进特性,例如缓存池,缓存池可以是ByteBuf中直接"借出"获取,如果有需要,"借出"的ByteB

手机短视频应用 --用户行为分析和优化指南

根据趣拍云的数据统计分析,日前所有接入趣拍短视频SDK的App用户每天的鉴权请求平均在1300万次左右,见下图: 趣拍云目前监测到的App短视频拍摄应用,日均启动次数在131133次,日均拍摄完成次数40608次.见下图: 视频拍摄的应用比例大概为开启App次数的1%和0.3%.拍摄完成率大约为30%. 由于趣拍云并非监测所有接入的App的拍摄应用记录,因此实际的日均启动次数和完成拍摄次数会高于上面的数值.所以实际的短视频拍摄应用比例实际会超过1%和0.3%.   根据趣拍云监测的用户拍摄行为具

移动直播技术秒开优化经验

现今移动直播技术上的挑战要远远难于传统设备或电脑直播,其完整的处理环节包括但不限于:音视频采集.美颜/滤镜/特效处理.编码.封包.推流.转码.分发.解码/渲染/播放等. 直播常见的问题包括 主播在不稳定的网络环境下如何稳定推流? 偏远地区的观众如何高清流畅观看直播? 直播卡顿时如何智能切换线路? 如何精确度量直播质量指标并实时调整? 移动设备上不同的芯片平台如何高性能编码和渲染视频? 美颜等滤镜特效处理怎么做? 如何实现播放秒开? 如何保障直播持续播放流畅不卡顿? 视频.直播等基础知识什么是视频

iOS 滑动性能优化

iOS 滑动性能优化 目录 一. 减少图层的Blend操作 1. UIView的背景色避免使用clearColor 2. 控件贴图避免使用带alpha的图片 3. UIImageView 使用时避免半透明 二.适当使用Rasterize 三.避免图片资源的重采样 总结 更多参考资料 一. 减少图层的Blend操作 展示半透明的view,设备会把当前图层和背景图层进行alpha叠加,这是一项很耗性能的一件事.如果动画中每一帧都做叠加,性能的损耗是很严重. 1. UIView的背景色避免使用clea