导读
redis 是一个基于内存的 key-value 数据库, 相对关系型数据库支持的数据结构更丰富, 而且操作封装的非常简单易用 redis 也支持主从分布式数据持久化等特性
redis 在业务系统中经常用作缓存系统, 即把热点数据或高频数据存到 Redis, 降低底层数据库负载提高应用吞吐率; redis 灵活的数据结构也能解决特定大数据统计中的痛点, 这里结合实际项目, 举些典型应用场景, 以及个人的理解, 当然也是蜻蜓点水, 泛泛而谈, 希望大方向上能对大家有所帮助, 当然有不正之处也请不吝赐教
Sets
集合的最主要特征是成员唯一性, 最常用场景是一些涉及到去重的计算, 比如 UV 计算 (去重用户数): 每次当用户活跃时简单的调用 SADD 命令向集合添加 UID, 然后实时的用 SCARD 获取元素个数还支持多个集合之间的交集(SINTER) 差集 (SDIFF) 和并集 ( SUNION) 运算, 交集操作可以很便捷的计算留存率:(今日集合昨日集合)/ 昨日集合集合是通过哈希表实现的, 所以添加删除查找的复杂度都是 O(1), 即复杂度和元素个数无关
Sorted sets
有序集合相比集合每个成员多了分数属性, 成员会按照分数自动从小到大排序, 当然和集合类似, 成员也是唯一不重复的常用查询方法: 排名在指定范围的成员分数在指定范围内的成员应用场景:
1TOPN 排名, 商品浏览量作为排名指标, 实时查询 TOPN 的商品列表, 其实现过程是: 商品每次被访问时, 用 ZINCRBY 增加商品浏览量, 实时用 ZREVRANGE key 0 N-1 返回集合中 TOPN 的商品
230 分钟在线用户数, APPweb 都有统计最近在线用户数的需求, 是衡量产品当前活跃度的重要指标, 有序集合也可以很容易实现: 以登录时间戳作为用户分数, 每次登录时更新用户分数, ZADD key 登录时间戳 UID, 然后用 ZCOUNT key 30 分钟前时间戳 now 时间戳命令查询最近登录用户数
有序集合是通过跳表和散列表两个数据结构实现的, 添加删除元素都会执行 O(log(N))的操作 (N 是集合的元素个数) 有序集合的关键是在对分数这个属性的理解上, 从合适的角度看问题, 会达到事半功倍的效果
Bitmaps
Redis 允许使用二进制的数据作为 Key(binary keys) 和二进制的数据作为 Value(binary values),bitmap 就是用二进制的数据作为 valuebitmap 不是一个新的数据类型, 而是在 String 类型上进行的扩展, 相关的命令有 setbitgetbitbitcount 等
SETBIT key offset value: 设置 key 在第 offset 处的 bit 值(只能是 0 或 1)
GETBIT key offset: 对 key 所存储的值, 获取指定 offset 位置的 bit 位(结果是 0 或 1)
BITCOUNT key: 计算 key 所存储的值, 被设置为 1 的 bit 位数量
上面提到集合统计 UV 的例子, 如果是大数据量的统计, 会占用很大内存空间, 如一个上亿用户量的网站, 消耗的内存也很恐怖 bitmap 也同样可以实现 UV 统计: 当有用户活跃时, 只需设置该用户所在 bit 位为 1, 而计算 UV 数就是统计所有 bit 位为 1 的数量比如用户 10086 的用户活跃: SETBIT key 10086 1, 获取某天的 DAU:GETBIT key
bitmap 处理大数据的排序查询效率非常高而且能节省极大内存空间, 最大 1 亿的偏移量大约占用 12M 内存, 但也有几个显而易见缺点: 1 元素是否能简单的映射为偏移量, 就是待统计的元素是否能映射为 Long 类型 2 消耗的空间取决于最大偏移量, 和基数无关
HyperLogLog
不像 SET 和 Bitmaps 是精确统计的, HyperLogLog(HLL)是一个概率数据结构, 用于估计一个集合内的基数(元素个数), 又叫基数统计其统计是有误差的, 可能会比实际稍微多一些或者稍微少一些, 但会控制在合理的范围内, 如果对误差是可接受的, HyperLogLog 是一个最佳选择假设是 UV 计算, 每次用户活跃时, 用 PFADD 添加元素到 HLL, 随时用 PFCOUNT 查看集合的基数, 就可以实时统计 UV 因为不会将元素真正添加到 HLL, 所以不能判断一个元素是否在 HLL 里存在
Hashes
一个 Hash 类型有多个字段(属性), 很像一个对象, 但 Hashes 字段数量是没有限制的一般是把一类数据放到一个 key 里, 然后通过字段表示不同含义
常用命令: HMGET: 一次获取多个 hash 字段的值
HINCYBY: 增加 hash 字段的值, 用于计数
原子操作
redis 单个命令都是原子操作, 比如 INCY, 多客户端对同一个 key 进行 INCY 操作的情况下, 不会发生客户端 1 读取 key 值 1, 客户端 2 同时读取 key 值 1, 然后客户端 1 和客户端 2 都对 key 进行加一操作, 设置 key 的值为 2; 比如 MSET, 给多个 key 赋值, 要么都设置成功, 要么都设置失败, 不会存在一部分 key 设置成功, 一部分可以设置失败的情况
总结
在大数据分析架构里, 一般是 sparkstorm 作为计算框架, 计算后的结果存到 redis 要对 redis 的数据结构有清晰认识, 理解各自优缺点实用场景, redis 价值才能最大化
来源: http://www.jianshu.com/p/61bdd7cad42c