文档章节

使用hashmap优化压缩Redis内存使用

纳兰清风
 纳兰清风
发布于 2017/05/11 17:50
字数 945
阅读 848
收藏 1

使用hashmap优化压缩Redis内存使用


背景

近来公司内部dsp架构升级,需要能够根据请求中的设备id实时的获取到该设备的用户画像相关信息,于是选用每天使用离线任务把用户数据灌入redis里面,供线上服务实时查询。

需求评估

需求是筛选出最近一个月活跃的设备,将其用户画像属性灌入redis中。于是筛选出30天的活跃设备总量有24亿。这么大的量如果直接使用设备id作为key直接写入redis,按value占用16字节来算,大概要用230G内存的redis集群,这成本还是比较可观的。

内存使用评估方法

为了评估我们设计的方法具体将占用多大的内存,上网查了写资料,发现跟redis内存容量使用和优化相关的只有这一篇文章《REDIS内存容量的预估和优化》,其他都是相互转载的,虽然不知道作者是谁,但是向作者致敬。

方案设计

大家知道Hash表空间大小和Key的个数决定了冲突率(或者用负载因子衡量),再合理的范围内,key越多自然hash表空间越大,消耗的内存自然也会很大。再加上大量指针本身是长整型,所以内存存储的膨胀十分可观。所以主要优化思路是考虑如何把key的个数减少。

在网上搜了下相关的博客,发现了这篇文章《Redis百亿级Key存储方案》,同样也是相互转载的特别多,已不知出处,里面bucket的思路启发了我,这里深深感谢作者。

原文的意思是设计一个映射函数,将设备id经过变换,映射到一个桶id上,桶的数量比原始数据的数量小2-3个数量级,而映射函数的作用是能够尽可能平均的将key映射到桶id上,使用桶id作为redis中的key,value使用hashmap结构,原始数据中的key和value作为hashmap中的subkey和value。这样能够大幅减少redis中全局key的数量。所以这里这个映射函数是一个比较核心的东西,要设计一个好的映射函数是很困难的。这里我经过多次尝试,方案如下:

选用CRC32算法对设备id做映射,再将结果对$2^{26}$取模作为桶id。这样能够将桶的数量控制在$2^{26}$ 这个数量上,同时使桶内的subkey分布尽可能均匀,减少数据倾斜的情况出现。同时使用BKDRHash算法对作为subkey的device id进行变换和压缩,从36字节变为4字节。

但是我们使用引用的第一篇文章中的公式来算一下: 首先我们有24亿条数据,这里桶的个数定为$2^{26}$个,平均每个桶里有35个子key。为了存储这$2^{26}$个key,我们需要key的长度为4个字节。 key字节数为4 + 9 ~ 16字节 subkey字节数为4字节 value字节数为16字节 则单个hashmap的大小为

35 × (4 + 16 + 3) + 2 = 807 字节 ~ 1024

总内存大小为

2 ^ 26 × (16 + 16 + 16 + 1024) + 2 ^ 26 × 4 = 67 G

可以看到总内存只使用了67G

总结

1.经过了上面的优化,从230G的内存占用到67G,内存使用减少了3.5倍,满满的成就感啊。 2.利用redis的hashmap可以极大的减少key的数量,和减少内存使用。

© 著作权归作者所有

纳兰清风

纳兰清风

粉丝 32
博文 36
码字总数 37100
作品 0
朝阳
程序员
私信 提问
Redis内存使用优化与存储

Redis内存使用优化与存储:上一篇Redis文章对其适用场景与特点进行了一个概括的分析,本文将对Redis的常见数据类型的使用场景以及在内存优化方面和性能优化方面做一些详细的分析。 Redis常用数...

oldgril
2017/03/01
0
0
Redis 内存使用优化与存储

原文出处:Frank Redis 常用数据类型 Redis 最为常用的数据类型主要有以下五种: • String • Hash • List • Set • Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下 ...

Frank
2016/10/09
0
0
Redis专题(2):Redis数据结构底层探秘

前言 上篇文章 Redis闲谈(1):构建知识图谱介绍了redis的基本概念、优缺点以及它的内存淘汰机制,相信大家对redis有了初步的认识。互联网的很多应用场景都有着Redis的身影,它能做的事情远...

宜信技术学院
06/11
287
0
Redis学习笔记之基本数据结构

Redis基础数据结构 Redis有5种基本数据结构:String(字符串)、list(列表)、set(集合)、hash(哈希)、zset(有序集合) 字符串string 字符串类型是Redis的value最简单的数据结构,类似与Java语言...

smileNicky
2018/09/26
0
0
Redis内存使用优化与存储

Redis常用数据类型 Redis最为常用的数据类型主要有以下五种: String Hash List Set Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部内存管理中是如何描述这些不...

stefanzhlg
2014/12/18
228
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
6
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
1K
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部