1、常用内存优化手段与参数
通过我们上面的一些实现上的分析可以看出redis实际上的内存管理成本非常高,即占用了过多的内存,作者对这点也非常清楚,所以提供了一系列的参数和手段来控制和节省内存,我们分别来讨论下。
首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本也非常的高,并且我们后续会分析此种持久化策略并不成熟,所以要关闭VM功能,请检查你的redis.conf文件中 vm-enabled 为 no。
其次最好设置下redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。
另外Redis为不同数据类型分别提供了一组参数来控制内存使用,我们在前面详细分析过Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
hash-max-zipmap-entries
含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个以下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap。
hash-max-zipmap-value 含义是当 value这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。
以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是不是设置的越大越好呢,答案当然是否定的,HashMap的优势就是查找和操作的时间复杂度都是O(1)的,而放弃Hash采用一维存储则是O(n)的时间复杂度,如果
成员数量很少,则影响不大,否则会严重影响性能,所以要权衡好这个值的设置,总体上还是最根本的时间成本和空间成本上的权衡。
同样类似的参数还有:
list-max-ziplist-entries 512说明:list数据类型多少节点以下会采用去指针的紧凑存储格式。
list-max-ziplist-value 64 说明:list数据类型节点值大小小于多少字节会采用紧凑存储格式。
set-max-intset-entries 512 说明:set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
最后想说的是Redis内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,不过大多数情况下这个不会成为Redis的性能瓶颈,不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能,这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,可以根据自己的需要进行修改,修改后重新编译就可以了。
2、Redis持久化磁盘IO方式及其带来的问题
有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持久化的fork系统调用造成内存占用加倍而导致的,这种观点是不准确的,因为fork 调用的copy-on-write机制是基于操作系统页这个单位的,也就是只有有写入的脏页会被复制,但是一般你的系统不会在短时间内所有的页都发生了写入而导致复制,那么是什么原因导致Redis崩溃的呢?
答案是Redis的持久化使用了Buffer IO造成的,所谓Buffer IO是指Redis对持久化文件的写入和读取操作都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache,而当Redis的持久化文件过大(尤其是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内存中作为操作系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会做Page Cache的剔除工作,但内核很可能认为某块Page Cache更重要,而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。我们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。
3、总结:
1.根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数。
2.当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量。
3.如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。
4.不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。
分享到:
相关推荐
### Redis 使用总结 #### 一、Redis 概述与特性 Redis 是一款开源的高性能键值(Key-Value)存储系统,常被用作数据库、缓存和消息中间件。其默认端口为 6379。Redis 支持多种数据结构如字符串(Strings)、列表(Lists...
Redis 是一款高性能的键值对...了解并熟练掌握 Redis 的使用,对于优化系统性能、提高数据处理效率具有重要意义。在实际应用中,可以根据业务需求选择合适的数据类型、持久化策略以及运行模式,以实现最佳的系统设计。
redis笔记总结redis笔记总结redis笔记总结redis笔记总结redis笔记总结redis笔记总结
### 实用手册:Redis全面总结 #### 一、Redis简介 **Redis**(Remote Dictionary Server)是一种开源的、高性能的键值(Key-Value)存储系统。它支持多种数据结构,如字符串(strings)、散列(hashes)、列表...
Redis 使用教程详解 Redis 是一个高性能的 NoSQL 键值存储数据库,广泛应用于缓存、任务列表、网站访问统计数据、过期处理、应用排行榜、分布式集群架构中的 session 分离等领域。下面是 Redis 的详细使用教程。 ...
Redis是一个开源的高性能键值存储数据库,它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等,使用内存存储,同时提供持久化选项,支持通过...
Redis中间件面试总结
连接Redis服务器可以使用`redis-cli`,并可通过`select`命令切换数据库。例如,`./bin/redis-cli -h localhost -p 6379`命令连接到本地的6379端口。 Redis提供了丰富的键操作命令,例如`del`可以删除一个或多个键,...
总结一下,Redis是一个强大的内存数据库,具备高速读写、丰富的数据结构、持久化机制以及消息队列等功能,广泛应用于缓存、数据库、消息中间件等多个领域。学习并熟练掌握Redis的使用,对于提升系统的性能和稳定性...
1. **数据存储**:考虑到Redis使用内存作为存储介质,因此应关注如何在有限的内存空间中存储更多的数据。可以通过优化键名、压缩大文本等方式来减少内存占用。 2. **数据查询**:合理利用连接池技术来管理Redis连接...
Redis技术栈 xmind格式 很适合新手上手看一下。 笔者自己总结
在个人总结中,我们可以看到Redis主要使用了五种数据结构,分别是String、List、Set、Hash和ZSet,每种都有其独特的特性和用途。 1. String(字符串,数值) String是最基础的数据类型,可以存储简单的键值对,值...
总结来说,C#中使用Redis需要安装Redis服务和StackExchange.Redis库,通过封装类可以简化代码,提高复用性。通过单例模式确保连接资源的高效利用,同时WpfRedis示例提供了在WPF应用中的实际使用场景。理解并掌握这些...
本试用总结将深入探讨 Redis 的基本概念、主要特性和在Windows环境下的配置,以及如何利用Jedis Java客户端进行交互。 一、Redis 基本概念 Redis (Remote Dictionary Server) 是一个开源的,基于内存的数据结构存储...
总结起来,C++与Redis的集成使得开发者能够方便地利用Redis的强大功能。通过选择合适的客户端库,如cpp-redis,可以轻松地实现数据的存取、发布订阅以及其他高级特性。在项目实践中,理解这些基本操作并熟练运用,将...
redis个人总结面试复习题集
redis五中数据类型;使用jedis操作redis;redis和springboot整合
默认情况下,Redis 使用配置文件`redis.conf`进行启动,可以通过指定配置文件路径来覆盖默认设置。 在Java环境中,可以使用JRedis这样的客户端库来连接和操作Redis。例如,创建一个Java程序,导入JRedis库,设置...
总结了java开发和数据分析中,涉及到的redis的诸多方面,面向理论,注重实践,适用于中高级开发工程师和DBA等。