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 协议
随机推荐
- SVN服务器在Ubuntu16.04下搭建多版本库详细教程
1 介绍 Subversion是一个自由,开源的版本控制系统,这个版本库就像一个普通的文件服务器,不同的是,它可以记录每一次文件和目录的修改情况.这样就可 以很方面恢复到以前的版本,并可以查看数据 ...
- PAT 1062 Talent and Virtue
#include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #i ...
- scss-注释
在scss中有两种注释方式 原生css的注释多行注释: /* * 注释的内容 */ 单行注释:// 注释内容一致延续到行末. 在尽可能的情况下,多行注释会被保留在输出的CSS中,而单行注释会被删除.
- 10th week task -1
1:For each ... inFor...in ExamplesFor...of 对以上的内容进行 Examples和Explanation (1)For...in 以任意顺序遍历一个对象的可枚举 ...
- 【阿里云产品公测】简单粗暴30S完成PTS测试配置附tornado服务器测试结果
作者:阿里云用户morenocjm [阿里云产品公测]简单粗暴 30S完成PTS测试配置(附tornado服务器测试结果) -------------------------------------- ...
- ADO.NET Tips
1. SqlCommand.ExecuteScalar Method Executes the query, and returns the first column of the first row ...
- Java Web 常用在线api汇总(不定时更新)
1.Hibernate API Documentation (3.2.2.ga) http://www.hibernate.org/hib_docs/v3/api/ 2.Spring Framewor ...
- WebLogic配置与部署
一.创建域: 第一步,选择“开始菜单”-> “Oracle WebLogic”-> “WebLogic Server 10gR3” -> “Tools”-> “Configur ...
- php xml字符串转数组
function xmltoarr($path){//xml字符串转数组 $xmlfile = file_get_contents($path);//提取xml文档中的内容以字符串格式赋给变量 $ob ...
- web中的cookie管理
本篇是以JSP为背景介绍,但是在web开发中也是相同的原理. 什么是cookie 由于http是一种无状态的协议,因此服务器收到请求后,只会当做一次新的请求.即便你重复发送了1000次同样的请求,这1 ...