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 协议
随机推荐
- SpringSecurity 3.2入门(7)自定义权限控制介绍
总结Spring Security的使用方法有如下几种: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中. 二种是用户和权限用数据库存储,而资源(url)和权限的对应关系硬编 ...
- 关于EF更新数据库,更新指定字段的设置
1.关于EF跟新数据库更新指定字段的设置 在EF提交到数据库的时候或许某些字段不想更新.或者自己更新一个模型到数据库去! 1.更新数据不更新一些字段 /// <summary> /// 数 ...
- windows下配置nginx环境
一. nginx软件拷贝 拷贝 nginx文件 到对应的服务目录中 如 E:/service/nginx nginx文件地址: 链接: http://pan.baidu.com/s/1c25oq6O ...
- Hadoop-HA(高可用)集群搭建
Hadoop-HA集群搭建 一.基础准备工作 1.准备好5台Linux系统虚拟服务器或物理服务器 我这里演示采用虚拟服务器搭建Hadoop-HA集群,各自功能分配如下: NameNode节点:vt-s ...
- Jupyter Notebook(iPython)
一.Jupyter Notebook介绍 1.什么是Jupyter Notebook Jupyter Notebook是基于网页的用于交互计算的应用程序.其可被应用于全过编码开发.文档编写.运行代码和 ...
- 洛谷P1730 最小密度路径(floyd)
题意 题目链接 Sol zz floyd. 很显然的一个dp方程\(f[i][j][k][l]\)表示从\(i\)到\(j\)经过了\(k\)条边的最小权值 可以证明最优路径的长度一定\(\leqsl ...
- 如何学习Java?学习Java顺序?
Java相对于Asp.Net或Asp.Net MVC来讲,入门是比较困难和烦琐的!它不像.Net哪样有安装开发工具就可以跑程序了,不需要配置复杂的运行环境. 推荐的学习Java的学习顺序如下: 一.J ...
- Tomcat中部署web应用的三种方式
Tomcat中部署web应用的三种方式(静态部署) 第一种,针对war或解压后的war,最为常用的是直接操作webapp目录,将完整的war包或者web应用直接放到webapp目录下.使用 ...
- React学习笔记 - 元素渲染
React Learn Note 3 React学习笔记(三) 标签(空格分隔): React JavaScript 二.元素渲染 元素是构成react应用的最小单位. 元素是普通的对象. 元素是构成 ...
- day6-基础 装饰器,生成器,迭代器
1.装饰器 定义:给其他函数装饰(添加附加功能)的函数 原则:1.不能修改被装饰的函数的源代码. 2.不能修改北庄施的函数的调用方式 实现所需要求:1.函数即便量 2.高阶函数 3.嵌套函 ...