Redis 内存容量的预估和优化

Oracle GoldenGate (OGG) 实战:从安装到故障排查的完整避坑指南 本文提供了一份详尽的Oracle GoldenGate实战指南,涵盖从环境准备、核心进程配置到性能调优与故障排查的全过程。重点解析了OGG安装与部署中的常见陷阱,并分享了确保数据同步链路稳定运行的高级运维技巧与常见故障处理方法,帮助技术人员高效避坑。 阅读详情

Redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预估和节约内存的方法.


先说说jemalloc,传说中解决firefox内存问题freebsd的默认malloc分配器,area,thread-cache功能和tmalloc非常的相识.在2.4版本被Redis引入,在antirez的博文中 提到内节约30%的内存使用.相比glibc的malloc需要在每个内存外附加一个额外的4字节内存块,jemalloc可以通过 je_malloc_usable_size函数获得指针实际指向的内存大小,这样Redis里的每个key或者value都可以节约4个字节,不少阿.

下面是jemalloc size class categories,左边是用户申请内存范围,右边是实际申请的内存大小.这张表后面会用到.

1     - 4     size class:4
5     - 8     size class:8
9     - 16    size class:16
17    - 32    size class:32
33    - 48    size class:48
49    - 64    size class:64
65    - 80    size class:80
81    - 96    size class:96
97    - 112   size class:112
113   - 128   size class:128
129   - 192   size class:192
193   - 256   size class:256
257   - 320   size class:320
321   - 384   size class:384
385   - 448   size class:448
449   - 512   size class:512
513   - 768   size class:768
769   - 1024  size class:1024
1025  - 1280  size class:1280
1281  - 1536  size class:1536
1537  - 1792  size class:1792
1793  - 2048  size class:2048
2049  - 2304  size class:2304
2305  - 2560  size class:2560string
string类型看似简单,但还是有几个可优化的点.先来看一个简单的set命令所添加的数据结构.

 

一个set hello world命令最终(中间会malloc,free的我们不考虑)会产生4个对象,一个dictEntry(12字节),一个sds用于存储key,还有 一个redisObject(12字节),还有一个存储string的sds.sds对象除了包含字符串本生之外,还有一个sds header和额外的一个字节作为字符串结尾共9个字节.

sds.c
========
 51 sds sdsnewlen(const void *init, size_t initlen) {
 52     struct sdshdr *sh;
 53
 54     sh = zmalloc(sizeof(struct sdshdr)+initlen+1);

sds.h
=======
 39 struct sdshdr {
 40     int len;
 41     int free;
 42     char buf[];
 43
};根据jemalloc size class那张表,这个命令最终申请的内存为16(dictEtnry) + 16 (redisObject) + 16(“hello”) + 16(“world”),一共64字节.注意如果key或者value的字符串长度+9字节超过16字节,则实际申请的内存大小32字节.

提一下string常见的优化方法

尽量使value为纯数字
这样字符串会转化成int类型减少内存的使用.

redis.c
=========
37 void setCommand(redisClient *c) {
38   c->argv[2] = tryObjectEncoding(c->argv[2]);
39   setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
40 }
object.c =======
275   o->encoding = REDIS_ENCODING_INT;
276   sdsfree(o->ptr);
277   o->ptr = (void*) value;可以看到sds被释放了,数字被存储在指针位上,所以对于set hello 1111111就只需要48字节的内存.

调整REDIS_SHARED_INTEGERS
如果value数字小于宏REDIS_SHARED_INTEGERS(默认10000),则这个redisObject也都节省了,使用redis Server启动时的share Object.

object.c
=======
269 if (server.maxmemory == 0 && value >= 0 && value < REDIS_SHARED_INTEGERS &&
270   pthread_equal(pthread_self(),server.mainthread)) {
271   decrRefCount(o);
272   incrRefCount(shared.integers[value]);
273   return shared.integers[value];
274 }这样一个set hello 111就只需要32字节,连redisObject也省了.所以对于value都是小数字的应用,适当调大REDIS_SHARED_INTEGERS这个宏可以很好的节约内存.

出去kv之外,dict的bucket逐渐变大也需要消耗内存,bucket的元素是个指针(dictEntry**), 而bucket的大小是超过key个数向上求整的2的n次方,对于1w个key如果rehash过后就需要16384个bucket.

开始string类型的容量预估测试, 脚本如下

#! /bin/bash

redis-cli info|grep used_memory:

for (( start = 10000; start < 30000; start++ ))
do
    redis-cli set a$start baaaaaaaa$start > /dev/null
done

redis-cli info|grep used_memory:根据上面的总结我们得出string公式

string类型的内存大小 = 键值个数 * (dictEntry大小 + redisObject大小 + 包含key的sds大小 + 包含value的sds大小) + bucket个数 * 4

下面是我们的预估值

>>> 20000 * (16 + 16 + 16 + 32) + 32768 * 4
1731072运行一下测试脚本

hoterran@~/Projects/redis-2.4.1$ bash redis-mem-test.sh
used_memory:564352
used_memory:2295424计算一下差值

>>> 2295424 - 564352
1731072都是1731072,说明预估非常的准确, ^_^

zipmap
这篇文章已经解释zipmap的 效果,可以大量的节约内存的使用.对于一个普通的subkey和value,只需要额外的3个字节(keylen,valuelen,freelen)来 存储,另外的hash key也只需要额外的2个字节(zm头尾)来存储subkey的个数和结束符.

 

zipmap类型的内存大小 = hashkey个数 * (dictEntry大小 + redisObject大小 + 包含key的sds大小 + subkey的总大小) + bucket个数 * 4

开始容量预估测试,100个hashkey,其中每个hashkey里包含300个subkey, 这里key+value的长度为5字节

#! /bin/bash

redis-cli info|grep used_memory:

for (( start = 100; start < 200; start++ ))
do
    for (( start2 = 100; start2 < 400; start2++ ))
    do
         redis-cli hset test$start a$start2 "1" > /dev/null
    done
done

redis-cli info|grep used_memory:这里subkey是同时申请的的,大小是300 * (5 + 3) + 2 =2402字节,根据上面jemalloc size class可以看出实际申请的内存为2560.另外100hashkey的bucket是128.所以总的预估大小为

>>> 100 * (16 + 16 + 16 + 2560) + 128 * 4
261312运行一下上面的脚本

hoterran@~/Projects/redis-2.4.1$ bash redis-mem-test-zipmap.sh
used_memory:555916
used_memory:817228计算一下差值

>>> 817228 - 555916
261312是的完全一样,预估很准确.

另外扯扯zipmap的一个缺陷,zipmap用于记录subkey个数的zmlen只有一个字节,超过254个subkey后则无法记录,需要遍 历整个zipmap才能获得subkey的个数.而我们现在常把hash_max_zipmap_entries设置为1000,这样超过254个 subkey之后每次hset效率都很差.

354     if (zm[0] < ZIPMAP_BIGLEN) {
355         len = zm[0];                       //小于254,直接返回结果
356     } else {
357         unsigned char *p = zipmapRewind(zm);   //遍历zipmap
358         while((p = zipmapNext(p,NULL,NULL,NULL,NULL)) != NULL) len++;
359
360         /* Re-store length if small enough */
361         if (len < ZIPMAP_BIGLEN) zm[0] = len;
362     }简单把zmlen设置为2个字节(可以存储65534个subkey)可以解决这个问题,今天和antirez聊了一下,这会破坏rdb的兼容性,这个功能改进推迟到3.0版本,另外这个缺陷可能是weibo的Redis机器cpu消耗过高的原因之一.

文章出处:http://blog.nosqlfan.com/html/3430.html

git连接华为软件开发云 我用的是github客户端的git shell 连接。用git bash也可以github客户端下载地址:https://desktop.github.com/1.在华为软件开发云上创建代码仓库2.在本地创建密钥SSH密钥帮助文档公钥是代码托管服务(CodeHub)识别您的用户身份的一种认证方式,通过公钥,您可以将本地git项目与代码托管服务(CodeHub)建立联系, 然后您就可以很方便的将本地... 阅读详情

相关推荐

LabVIEW QMH模板实战:从创建到错误处理的完整指南

本文提供LabVIEW QMH模板从创建到错误处理的完整实战指南。详细解析了队列消息处理器(QMH)作为LabVIEW核心设计模式如何实现任务解耦与异步通信,涵盖事件处理循环、消息处理循环的搭建、用户事件创建、队列引用管理、消息优先级控制以及健壮的错误处理机制,帮助开发者构建稳定、可维护的复杂应用程序。

white的博客 725

深入了解一下Redis的内存模型!

跳跃表是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。除了跳跃表,实现有序数据结构的另一种典型实现是平衡树;大多数情况下,跳跃表的效率可以和平衡树媲美,且跳跃表实现比平衡树简单很多,因此redis中选用跳跃表代替平衡树。跳跃表支持平均O(logN)、最坏O(N)的复杂点进行节点查找,并支持顺序操作。Redis的跳跃表实现由zskiplist和zskipl...

weixin_34060299的博客 289

Python爬虫实战:用Selenium+ChromeDriver批量抓取政府网站政策文件(附完整代码)

本文详细介绍了使用Python的Selenium和ChromeDriver进行政府网站政策文件批量抓取的实战技巧。从环境配置、动态页面元素定位到分页机制破解和反爬虫策略,提供了完整的解决方案和代码示例,帮助开发者高效获取结构化政策数据。

weixin_42531710的博客 266

Redis容量评估

一.Redis常用的数据结构 在进行Redis的容量评估之前,有必要了解一下Redis常用的数据结构。 1.SDS   redis没有直接使用c语言传统的字符串(以空字符为结尾的字符数组),而是自己创建了一种名为SDS(简单动态字符串)的抽象类型,用作redis默认的字符串。 //SDS的定义如下(sds.h/sdshdr): struct sdshdr { int le...

根号三 2万+

树莓派4B保姆级教程:从零配置Python虚拟环境到PySide2开发全流程(含避坑指南)

本文提供树莓派4B上配置Python虚拟环境及PySide2 GUI开发的完整教程。针对armv7l架构的特殊性,详细讲解了从系统准备、虚拟环境创建到PySide2安装的避坑指南,并重点解决了跨平台UI文件处理等常见难题,帮助开发者构建稳定高效的开发环境。

9q8w7e6r5的博客 822

Netron显示自定义属性,按属性设置不同节点的颜色

本文介绍了一种让Netron显示自定义颜色的方法,可根据某些属性,调整节点的颜色 需求背景: 在分析AI模型精度误差时,用不同等级的红色,表示误差的大小.可以直观地看到误差的传递关系

Hi20240217的博客 1513

Redis容量评估模型

Redis容量评估模型 2017-04-26 19:43 一、redis常用数据结构 做容量评估之前,有必要对redis常用数据结构有大概了解。 1、SDS redis没有直接使用c语言传统的字符串(以空字符为结尾的字符数组),而是自己创建了一种名为SDS(简单动态字符串)的抽象类型,用作redis默认的字符串。 SDS的定义如下( sds.h

天生我才必有用! 1万+

STM32 烧录报错Invalid ROM Table

STM32 烧录报错Invalid ROM Table

热爱科技,物联,程序开发等 1733

Redis内存容量的预估和优化

Redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预估和节约内存的方法. 先说说jemalloc,传说中解决firefox内存问题freebsd的默认malloc分配器,area,thread-cache功能和tmalloc非

wx_mdq的专栏 1329

Python 爬虫实战:Boss直聘 Python 岗位招聘数据爬取

本文介绍了一个Python爬虫项目,用于抓取Boss直聘平台的Python岗位招聘数据并进行可视化分析。项目采用requests库发送POST请求,通过抓包分析获取JSON接口,绕过HTML解析直接获取结构化数据。主要内容包括: 接口分析:找到关键POST接口,解析请求头和JSON参数格式 环境准备:安装requests/pandas/matplotlib/pyecharts等依赖库 核心实现: 手动获取登录Cookie 构建请求头和城市代码映射 实现分页抓取职位列表数据 项目特色在于直接解析JSON接口而

u014481728的博客 297

Java开源海外跨境电商购物商城源码,TikToK商城系统源码,外贸商城在线交易

最近很火的一款商城源码,朋友分享给我的,完整版,java开源代码,带有非常详细的搭建教程,文件都一个多G,喜欢的可以下载来研究研究!3、创建mall 数据库并导入数据,数据库名用户名为:mall 数据库密码保持为:XXKytcACPX3GbdsH。8、进入cd /data/deploy/mall-tool/目录执行./build.sh脚本。7、宝塔ssh进入cd /data/deploy/mall/ 执行./build.sh脚本。2、安装宝塔环境:安装 Redis、MySQL5.7、Ngin1.2。

百创科技 2821

redis面试:内存占用优化

优化内存占用 了解redis的内存模型,对优化redis内存占用有很大帮助。下面介绍几种优化场景。 利用jemalloc特性进行优化 由于jemalloc分配内存时数值是不连续的,因此key/value字符串变化一个字节,可能会引起占用内存很大的变动,在设计时可以利用这一点。 例如,如果key的长度如果是8个字节,则SDS为17字节,jemalloc分配32字节;此时将key长度缩减为7个字节,则SDS为16字节,jemalloc分配16字节;则每个key所占用的空间都可以缩小一半。 使用整型/长整型

OceanStar的博客 687

通信算法之264: DJI O2 协议物理层逆向工程解析

对于 DroneID,标志之间的间隙由循环前缀 (CP) 填充:每个标志末尾的副本附加在相应标志的开头。有了关于确切标志开始的信息,可以使用 FFT 将标志转移到频域 - 来自时域的 1024 个样本导致频域中的 1024 个子载波。使用比特流的解扰和涡轮解码,并将生成的数据映射到如上的DroneID 结构,通过逆向工程在无人机的固件中找到了它。注意到一些无人机(Mavic 2 和更早的 OcuSync 无人机)不发送第一个标志(标志 1),这导致更短的帧持续时间为 576 µs。//产品型号数字代号。

leegang12的专栏 3946

redis内存容量的预估和优化

redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预估和节约内存的方法.     先说说jemalloc,传说中解决firefox内存问题freebsd的默认malloc分配器,area,thread-cache功能和tmalloc非常的相识

shengxiaweizhi的专栏 3145

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

REDIS内存容量的预估和优化

redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预估和节约内存的方法.   先说说jemalloc,传说中解决firefox内存问题freebsd的默认malloc分配器,area,thread-cache功能和tmalloc非常的相识

陆多多的专栏 2576

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Redis内存空间预估与内存优化策略:保障数据安全与性能的架构实践

在现代软件架构中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、会话存储和消息队列等场景。然而,Redis的内存占用问题一直是开发者关注的焦点。本文将介绍如何准确预估Redis所占内存空间,并提供一些内存优化策略,以避免内存占用过多导致数据丢失的风险。同时,我们还将给出相关代码示例,帮助读者更好地理解和实践这些技术。正文:一、Redis内存空间预估方法准确预估Redis所占内存空间是保障系统稳定性的重要一环。下面我们介绍一些常用的方法来预估Redis的内存占用。

赵KK的博客 887

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Redis内存空间预估与内存优化策略:保障数据安全与性能的架构实践AIGC/AI绘画/chatGPT/SD/MJ

在现代软件架构中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、会话存储和消息队列等场景。然而,Redis的内存占用问题一直是开发者关注的焦点。本文将介绍如何准确预估Redis所占内存空间,并提供一些内存优化策略,以避免内存占用过多导致数据丢失的风险。同时,我们还将给出相关代码示例,帮助读者更好地理解和实践这些技术。正文:一、Redis内存空间预估方法准确预估Redis所占内存空间是保障系统稳定性的重要一环。下面我们介绍一些常用的方法来预估Redis的内存占用。

赵KK的博客 1062

终极Node-Redis容量规划指南:存储需求预估与性能优化全攻略

在现代应用开发中,Redis作为高性能的内存数据库,其容量规划直接影响系统稳定性与成本控制。本文将为你提供一套完整的Node-Redis存储需求预估方法和优化策略,帮助新手开发者轻松掌握Redis资源配置的核心要点。 ## 1. 为什么Node-Redis容量规划至关重要? Redis作为内存数据库,其存储容量直接受限于服务器内存大小。不合理的容量规划可能导致: - **内存溢出**:数据量超

gitblog_00648的博客 981

Redis 性能优化策略

Redis 性能优化策略

2300

Redis学习资料汇总

1.Redis是什么? ·        十五分钟介绍 Redis数据结构 ·        Redis系统性介绍 ·        一个很棒的Redis介绍PPT ·        强烈推荐!非同一般的Redis介绍 ·        Redis之七种武器 ·        锋利的Redis ·        redis 适用场景与实现 2.Redis内部实现 ·

小地盘的诺克萨斯 2507

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

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34202952的博客 485

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

https://my.oschina.net/nalenwind/blog/897744 使用hashmap优化压缩Redis内存使用 背景 近来公司内部dsp架构升级,需要能够根据请求中的设备id实时的获取到该设备的用户画像相关信息,于是选用每天使用离线任务把用户数据灌入redis里面,供线上服务实时查询。 需求评估 需求是筛选出最近一个月活跃的设备,将其用户画像属性灌入redis中。...

tianjinsong的专栏 4982

Redis资料汇总专题

转载自:http://blog.nosqlfan.com/html/3537.html 很多朋友反映,说NoSQLFan上的资料不少,但是要找到自己实用的太难,于是萌生做这样一个专题的想法。通过将不同NoSQL产品从入门到精通的各种资料进行汇总,希望能够让大家更快的找到适合自己的教程或文章进行阅读。 最后更新时间:2013-04-22 1.Redis是什么? 十五分钟介绍 R...

acjxe44224的专栏 174
上一篇: zookeeper 3.3.3 C 编译的问题及解决
下一篇: win7(64)plsql连接的时候提示‘ORA-12154:TNS:无法解析指定的连接标志符’;的解决方法
Falcon2000
博客等级 码龄26年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值