我们在系统设计面试或者在实际工作中,免不了要进行一些估算。之前的文章里讲过一些技巧,今天来个实战。

这是我最近在做的一个工作,将内存中的一个超大的 map[int64]int64 写入到 redis,map 里的元素个数是千万级的。设计方案的时候,需要对 redis 的容量做一个估算。

如果不了解 redis 的话,可能你的答案是用元素个数直接乘以 16B(key 和 value 各占 8B)。我们假设元素个数是 5kw,那估算结果就是:5kw * 16B=50kk * 16B = 800MB。

答案是错的。

为了解决这个问题,需要深入地研究一下 redis 的数据结构。

整个 redis 数据库就是一个大的 map,它容纳了所有的 key,我们都知道 key 都是 string 类型,而 value 则有 string, list, set, hashmap, zset……等类型。

Redis 中的一个 k-v 对用一个 entry 项表示,其中每个 entry 包含 key、value、next 三个指针,共 24 字节。由于 redis 使用 jemalloc 分配内存,因此一个 entry 需要申请 32 字节的内存。这里的 key, value 指针分别指向一个 RedisObject:

redis entry
typedef struct redisObject {unsigned type:4;unsigned encoding:4;unsigned lru:LRU_BITS; int refcount;void *ptr;
} robj;

RedisObject 对应前面提到的各种数据类型,其中最简单的就是 redis 内部的字符串了。它有如下几种编码格式:

SDS 编码(图片来自极客时间-redis 专栏)

图中的元数据包括 type,encoding,lru, refcount,分别表示数据类型,编码类型,最近一次访问的时间戳,引用次数。

当字符串是一个整型时,直接放在 ptr 位置,不用再分配新的内存了,非常高效。

解析一下 44 字节的原因:元数据和 ptr 共占 16 字节,加上 44 字节,再加上字符串末尾的 '\0',共61 字节。因为字符串的长度只有 44,因此 len 和 alloc 各用 1 个字节就够了。再加上 1 个字节的 flags,刚好是 64 字节。超过了这个值,SDS 就需要单独再申请一块内存,导致访问的时候就多了一跳指针。

多提一句,redis 最大支持 512MB 大小的字符串。

回答本文的问题,恰好我们要写入 redis 的 map 中的 key 和 value 都是整数,因此直接将值写入 ptr 处即可。

于是 map 的一个 key 占用的内存大小为:32(entry)+16(value)+16(value)=64B。于是,5kw 个 key 占用的内存大小是 5kw*64B = 50 kk * 64B = 3200MB ≈ 3G。

假如我们在 key 前面加上了前缀,那就会生成 SDS,占用的内存会变大,访问效率也会变差。

总之,我们根据要写入 redis 中的字符串的长度可以很方便地估算占用内存的总大小。如果 key 和 value 恰好都是 int64 类型的,那么尽量不要在 key 前加前缀,这样可以直接使用 key 的个数乘以 64B 就能算出占用内存的大小。

Go map[int64]int64 写入 redis 占用多少内存相关推荐

  1. Redis占用大量内存并且报错 Can‘t save in background: fork: Cannot allocate memory

    Redis Can't save in background: fork: Cannot allocate memory 解决 先说如何解决: echo 'vm.overcommit_memory=1 ...

  2. 面试被问 Go 的map[int64]int64 在 redis 会占多少空间...

    我们在系统设计面试或者在实际工作中,免不了要进行一些估算.之前的文章里讲过一些技巧,今天来个实战. 这是我最近在做的一个工作,将内存中的一个超大的 map[int64]int64 写入到 redis, ...

  3. 使用Java读取 “Python写入redis” 的数据踩坑记录

    https://my.oschina.net/u/2338224/blog/3061507 使用Java读取 "Python写入redis" 的数据踩坑记录 https://seg ...

  4. Redis占用内存过高怎么办

    目录 前言 案例现象 定位问题 内存回收策略 键过期机制 slave的过期策略 解决问题 前言 我们知道,Redis是一个key-value数据库,它的数据是运行在内存中的 其读写效率比将数据存储到磁 ...

  5. ELKStack入门篇(三)之logstash收集日志写入redis

    1.部署Redis 1.1.下载redis [root@linux-node2 ~]# wget http://download.redis.io/releases/redis-4.0.6.tar.g ...

  6. 【Redis系列】面试官:Redis中的数据已经过期,为什么还占用这内存?

    如果有面试官问Redis中的数据已经过期为什么还占用这内存? 它是因为Redis本身的过期策略和缓存淘汰机制所导致的. 说说Redis的过期策略和缓存淘汰机制 先来说说Redis的过期策略,Redis ...

  7. golang 并发demo 写入 redis

    原文链接:golang 并发demo 写入 redis 源代码: package mainimport ("fmt""runtime""strconv ...

  8. redis 内存不足 排查_排查redis占用内存达90%以上

    帮别人排查一个问题,项目还没上线但redis占用内存很高.思路如下: 1.登陆redis控制台,首先用 keys * 获取所有的key > keys * x:x:a x:x:b x:x:c 发现 ...

  9. linux查看redis内存,Linux查看redis占用内存的方法

    redis-cli auth 密码 info # Memory used_memory:13490096 //数据占用了多少内存(字节) used_memory_human:12.87M //数据占用 ...

最新文章

  1. keras bi-lstm_LSTM用于文本生成的应用介绍-使用Keras和启用GPU的Kaggle Kernels
  2. oracle时间戳找回数据库,【备份恢复】 闪回数据库(三) 基于时间戳闪回数据库...
  3. jsx怎么往js里传参数_实践Vue 3.0做JSX(TSX)风格的组件开发
  4. 微信小程序 html css xml,微信小程序 使用towxml解析html流程及踩坑记录
  5. php 进程函数,php多进程函数
  6. 收集Linux常用命令
  7. 从WebRtc学习RTCP协议
  8. Cookie 的规范介绍
  9. android sdk system images,Android SDK下边tools、platform-tools、system-images、sources等目录的作用...
  10. NBA数据分析及可视化BI数据大屏 (Kobe·Bryant)
  11. 维宏控制卡win7 驱动_ncstudio(维宏控制系统)64位下载v5.4.86[百度网盘资源] - 软件学堂...
  12. H5前端框架说明文档
  13. 网站服务器诊断分析,网站SEO优化诊断分析报告范文模板(一)
  14. 重磅!《中华人民共和国个人信息保护法》今日起施行!
  15. Introduction to NLP
  16. erp系统不能连接服务器配置,erp系统云服务器怎么配置
  17. 在UE4中创建新的Shading Model
  18. 树莓派使用pip安装cython
  19. Scala基础语法1
  20. adb连接的2种方式,有线(USB线)和无线

热门文章

  1. 1984年王安微型计算机,王安简:今年中科大少年班最小的学生
  2. 阿里财报:云计算年度营收133亿,季度营收连续12个季度翻番
  3. 从“美屋”到“打扮家”:线下VR家居馆中的科技新体验
  4. sudo with no password
  5. 面试之 listview优化
  6. Android用户界面设计:框架布局
  7. 2021牛客多校10 - Train Wreck(贪心)
  8. 2021牛客多校3 - 24dian(dfs)
  9. CodeForces - 1538G Gift Set(二分)
  10. CodeForces - 571D Campus(数据结构综合)