redis 高性能应用
- redis可达到512M/per key
- 512M=512*1024KB=512*1024*1000B=512*1024*1000*8bit=40亿+
- 化整为零40亿,也就是说一位代表一个用户,40亿可以代表40亿个用户!
- 但是int 有符号整型取值范围 20亿+,所以bitmap位数只能到20亿个
- bitmap适用于那些记录性别或者状态值,枚举于0、1的字段!
Bitmap(即Bitset)
Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR以及其它位操作。
位图计数(Population Count)
位图计数统计的是bitmap中值为1的位的个数。位图计数的效率很高,例如,一个bitmap包含10亿个位,90%的位都置为1,在一台MacBook Pro上对其做位图计数需要21.1ms。SSE4甚至有对整形(integer)做位图计数的硬件指令。
为了统计今日登录的用户数,我们建立了一个bitmap,每一位标识一个用户ID。当某个用户访问我们的网页或执行了某个操作,就在bitmap中把标识此用户的位置为1。在Redis中获取此bitmap的key值是通过用户执行操作的类型和时间戳获得的。
这个简单的例子中,每次用户登录时会执行一次redis.setbit(daily_active_users, user_id, 1)。将bitmap中对应位置的位置为1,时间复杂度是O(1)。统计bitmap结果显示有今天有9个用户登录。Bitmap的key是daily_active_users,它的值是1011110100100101。
因为日活跃用户每天都变化,所以需要每天创建一个新的bitmap。我们简单地把日期添加到key后面,实现了这个功能。例如,要统计某一天有多少个用户至少听了一个音乐app中的一首歌曲,可以把这个bitmap的redis key设计为play:yyyy-mm-dd-hh。当用户听了一首歌曲,我们只是简单地在bitmap中把标识这个用户的位置为1,时间复杂度是O(1)。
[java]
- Redis.setbit(play:yyyy-mm-dd, user_id, 1)
Redis.setbit(play:yyyy-mm-dd, user_id, 1)
今天听过歌曲的用户就是key是play:yyyy-mm-dd的bitmap的位图计数。如果要按周或月统计,只要对这周或这个月的所有bitmap求并集,得出新的bitmap,在对它做位图计数。
利用这些bitmap做其它复杂的统计也非常容易。例如,统计11月听过歌曲的高级用户(premium user):
(play:2011-11-01∪ play:2011-11-02∪ … ∪ play:2011-11-30)∩premium:2011-11
下面的表格显示了在1亿2千8百万用户上完成的时间粒度为1天,一周,一个月的用户统计的时间消耗比较。
Period | Time(ms) |
Daily | 50.2 |
Weekly | 392.0 |
Monthly | 1624.8 |
前面的例子中,我们把日统计,周统计,月统计缓存到Redis,以加快统计速度。
下面的Java代码用来统计某个用户操作在某天的活跃用户。
[java]
- import redis.clients.jedis.Jedis;
- import java.util.BitSet;
- ...
- Jedis redis = new Jedis("localhost");
- ...
- public int uniqueCount(String action, String date) {
- String key = action + ":" + date;
- BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
- return users.cardinality();
- }
import redis.clients.jedis.Jedis;import java.util.BitSet;... Jedis redis = new Jedis("localhost"); ... public int uniqueCount(String action, String date) { String key = action + ":" + date; BitSet users = BitSet.valueOf(redis.get(key.getBytes())); return users.cardinality(); }
下面的Java代码用来统计某个用户操作在一个指定多个日期的活跃用户。
[java]
- import redis.clients.jedis.Jedis;
- import java.util.BitSet;
- ...
- Jedis redis = new Jedis("localhost");
- ...
- public int uniqueCount(String action, String... dates) {
- BitSet all = new BitSet();
- for (String date : dates) {
- String key = action + ":" + date;
- BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
- all.or(users);
- }
- return all.cardinality();
- }
import redis.clients.jedis.Jedis;import java.util.BitSet;... Jedis redis = new Jedis("localhost"); ... public int uniqueCount(String action, String... dates) { BitSet all = new BitSet(); for (String date : dates) { String key = action + ":" + date; BitSet users = BitSet.valueOf(redis.get(key.getBytes())); all.or(users); } return all.cardinality(); }
redis 高性能应用的更多相关文章
- 基于nginx+lua+redis高性能api应用实践
基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...
- 知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路
本文来自知乎官方技术团队的“知乎技术专栏”,感谢原作者陈鹏的无私分享. 1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动 ...
- 使用Nginx Lua实现redis高性能http接口
使用Nginx Lua实现redis高性能http接口 时间 -- :: 峰云就她了 原文 http://xiaorui.cc/2015/01/27/使用nginx-lua实现redis高性能http ...
- 发布一个参考ssdb,使用go类似的实现redis高性能nosql:ledisdb
起因 ledisdb是一个參考ssdb.採用go实现,底层基于leveldb,相似redis的高性能nosql数据库,提供了kv,list,hash以及zset数据结构的支持. 我们如今的应用极大的依 ...
- 从单机到2000万 QPS 并发的 Redis 高性能缓存实践之路
1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动化运维服务体系,提供很多强大的功能.本文作者陈鹏是该系统的负责人,本次文 ...
- 从网络通信的演进过程彻底搞懂Redis高性能通信的原理(全网最详细,建议收藏)
我们一直说Redis的性能很快,那为什么快?Redis为了达到性能最大化,做了哪些方面的优化呢? 在深度解析Redis的数据结构 这篇文章中,其实从数据结构上分析了Redis性能高的一方面原因. 在目 ...
- redis高性能客户端 - redissdk
我们首先在我们自己的工程下放置redis.properties,内容如下: #redis地址 server=192.168.0.8 #redis端口 port=6379 auth=admin max_ ...
- ELK Redis高性能加速
1.下载redis并安装好 wget http://download.redis.io/releases/redis-2.8.13.tar.gz tar zxf redis-.tar.gz cd re ...
- redis 高性能的原因
1. redis 数据存储在内存中: 2. redis 是单线程: 3. redis 多路复用: 指令先放到队列里 4.redis 使用resp 协议
随机推荐
- 网站部署中遇到的问题-编译器错误信息: CS0016
问题描述: 访问站点出现错误win7 x64+iis7.5 配置错误:CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\ ...
- 希尔排序——Java实现
一.排序思想 希尔排序(Shell’s Sort)是插入排序的一种,是直接插入排序算法的一种更高版本的改进版本. 把记录按步长gap分组,对每组记录采用直接插入排序方法进行排序: 随着步长逐渐减小,所 ...
- scss-@at-root
@at-root指令可以使一个或多个规则被限定输出在文档的根层级上,而不是被嵌套在其父选择器下. 下面就通过scss代码实例介绍一下它的作用: 没有使用@at-root命令的默认情况. .parent ...
- 中值滤波C语言优化
中值滤波C语言优化 图像平滑是图像预处理的基本操作,本文首先用不同的方法对一张图片做预处理比较它们效果的不同,然后针对中值滤波,实现了一种快速实现.(其实是copy的opencv实现,呵呵).因为op ...
- 【阿里云产品公测】小白对OTS两点小建议
作者:阿里云用户荷包蛋 我是大一的新生,作为一个爱技术爱学习爱折腾的熊孩子,我在暑假申请了ECS,学到了很多东西.现在阿里巴巴又开放了很多免费测试,我抱着学习和围观的心态申请了测试,其中有OTS这个高 ...
- Android 自定义View之自绘控件
首先要提前声明一下,我对于自定义View的理解并不是很深,最近啃了几天guolin博主写的关于自定义View的博客,讲的非常棒,只不过涉及到源码和底层的一些东西,我自己就懵逼了,目前只是会了关于自定义 ...
- 性能优化小Tips
Performance Tips 这篇文章主要是介绍了一些小细节的优化技巧,当这些小技巧综合使用起来的时候,对于整个App的性能提升还是有作用的,只是不能较大幅度的提升性能而已.选择合适的算法与数据结 ...
- 【起航计划ObjC 002】印第安老斑鸠ObjC的幻想 ---- Ubuntu下安装并使用MAC虚拟机
本文介绍如何在Ubuntu下安装Mac OS X Mavericks系统.具体如下: 1)安装前准备工作 下载Mac OS X Mavericks系统,地址:http://pan.baidu.com/ ...
- 《3D打印:从想象到现实》:基本没发现独到之处
本书汇总了3D打印的相关咨询:原理.可能的或已经实现的应用.商业模式等等.由于3D打印是最近媒体上比较热的信息,对我来说书中的大部分内容都没有独到之处,都是已知的.
- webpack前言:前端模块系统的演进
前端开发和其他开发工作的主要区别,首先是前端是基于多语言.多层次的编码和组织工作,其次前端产品的交付是基于浏览器,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源 ...