Redis处理的速度很快,因为它是基于内存的。在内存能够足够容纳数据的时候,所有的数据都存放在内存。这个时候不论是读取数据还是写入数据都是非常快的。但是如果数据量很大,大到内存已经无法全部容纳的时候,我想对存储有一定了解的人都在想,这个时候redis是怎么处理的呢?处理速度是否会直线下降?
幸亏,答案是否定的。Redis使用到了VM,在redis.conf设置vm-enabled yes 即开启VM功能。 通过VM功能可以实现冷热数据分离。使热数据仍在内存中,冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。在这里,需要特别提到的是,Redis并没有使用OS提供的Swap,而是自己实现。作者在自己的blog说明了原因:
1:OS是基于page(4K)来做的,它的粒度对于Redis来说太大。而redis的大多数对象都远小于4k,所以一个OS页面上可能有多个redis对象。另外redis的集合对象类型如list,set可能存在与多个OS页面上。最终可能造成只有10%的key被经常访问,但是所有OS页面都会被OS认为是活跃的,这样只有内存真正耗尽时OS才会交换页面。
2:相比于OS的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后对象会比内存中对象小10倍。这样redis的vm会比OS vm能少做很多io操作。
3:OS交换的时候,是会阻塞线程的,而Redis可以设置让工作线程来完成,主线程仍可以继续接收client的请求。
开启VM功能后,还有其他几个设置需要设置vm-swap-file:设置被交换出的值保存到磁盘的位置。vm-max-memory:设置当内存消耗达到上限时开始将value交换出来。vm-page-size:设置单个页面的大小,单位是字节。vm-pages:设置最多能交换保存多少个页到磁盘。可以算出可以交换出来的最大大小为vm-page-size * vm-pages。vm-max-threads:设置完成交换动作的工作线程数,设置为0表示不使用工作线程而使用主线程,这会以阻塞的方式来运行。建议设置成CPU核个数。
Redis为了保证查找的速度,只会将value交换出去,而在内存中保留所有的Key。所以它非常适合Key很小,Value很大的存储结构。如果Key很大,value很小,那么vm可能还是无法满足需求。redis规定同一个页面只能保存一个对象。但是一个对象可以保存在多个页面中。在redis使用的内存没超过vm-max-memory之前是不会交换任何value的。当超过最大内存限制后,redis会选择较老的对象。如果两个对象一样老会优先交换比较大的对象,将它从内存中移除,这样会更加节约内存。精确的公式swappability = age*log(size_in_memory)。
既然对于Redis来说,一个页面只会保存一个对象,也就是一个Value值,所以应该将vm-page-size设置成大多数value可以保存进去。如果设置太小,一个value对象就会占用几个页面,如果设置太大,就会造成页面空闲空间浪费。每个页面,Redis都会在内存中使用1比特(bit)长度来保存页面的空闲状态。如果设置的vm-pages非常大,那么光用来保存页面状态就会花费很大的内存。
VM的工作机制:分为两种
第一种:vm-max-threads = 0
换出
主线程定期检查使用的内存大小,如果发现内存超出最大上限,会直接以阻塞的方式,将选中的对象保存到换出文件中,并释放对象占用的内存,此过程会一直重复直到下面条件满足:
1.内存使用降到最大限制以下,2. 设置的交换文件数量达到上限,3. 几乎全部的对象都被交换到磁盘了
换入
当有client请求的value之前已被换出时,主线程会以阻塞的方式从换出文件中加载对应的value对象,加载时此时会阻塞所有client,然后再处理client的请求。
第二种:vm-max-threads > 0
换出
当主线程检测到使用内存超过最大上限,会将选中的要交换的对象信息放到一个队列中交由工作线程后台处理,主线程会继续处理client请求。
换入
如果有client请求value之前已被换出时,主线程先阻塞当个client,然后将加载对象的信息放到一个队列中,让工作线程去加载,此进主线程继续处理其他client请求。加载完毕后工作线程通知主线程。主线程再执行被阻塞的client的命令。这种方式只阻塞单个client。
注:
当前VM的坏处: slow restart 重启太慢 slow saving 保存数据太慢 slow replication 上面两条导致 replication 太慢 complex code 代码过于复杂
有可能被废弃哦,具体见:
https://yq.aliyun.com/ziliao/553403
参考链接:
https://www.cnblogs.com/xuegang/archive/2011/11/16/2250920.html
相关推荐
Redis的内存管理机制是通过redisDb结构体来实现的,该结构体包含了dict、expires两个成员变量,其中dict用于存储key-value数据,expires用于存储key的过期时间。 在Redis中,freeMemoryIfNeeded()函数用于释放不...
为了确保内存的有效利用与系统的稳定性,Redis设计了一套高效的内存管理机制,其中包括了针对键过期处理的策略。本文将详细介绍Redis中的内存过期策略,包括其基本原理、工作方式以及相关的配置选项。 #### 二、...
在Redis内存分布分析中,涉及到的核心知识点包括Redis的数据结构存储、数据类型操作、内存管理机制以及命令执行过程解析。 首先,我们来了解Redis的数据结构存储。Redis作为一个高性能的键值存储系统,其内部通过...
### Redis内存存储结构分析 #### 一、Redis内存存储总体结构概述 ...通过对Redis内存存储结构的深入理解以及采取适当的优化措施,可以在保持高性能的同时有效管理内存资源,提高系统的整体效率。
在本文中,我们将深入探讨Redis的缓存机制,主要包括数据持久化、内存管理、缓存淘汰策略以及如何在实际应用中优化缓存性能。 首先,Redis的数据持久化是确保数据安全的重要手段。主要有两种方式:RDB(Redis ...
Redis以键值对的形式存储数据,且所有操作都在内存中进行,速度非常快,常用于缓存和实时数据处理场景。 2. **数据类型**: - **字符串(Strings)**:最基础的数据类型,可存储任意二进制数据。 - **哈希...
1. **精细化监控**:增强对Redis内存使用情况、Rehash过程和网络状况的监控,以便尽早发现并解决问题。 2. **优化Rehash策略**:调整Rehash的触发条件和执行步骤,使得在高负载期间更加谨慎地进行Rehash,降低对服务...
4. **主从复制**:Redis可以通过复制机制实现数据备份和负载均衡,一个主服务器可以有多个从服务器。 5. **网络模型**:Redis采用单线程模型处理客户端请求,但由于是内存存储,所以性能非常高。 6. **发布订阅**...
#### 五、内存管理 ##### 1. 配置 - **active-rehashing**: 控制Redis在rehash过程中是否主动释放内存。 - **数据结构限制**: 通过调整特定数据结构的最大占用量来减少内存使用。 - `hash-max-zipmap-entries` - ...
- 考虑到Windows的内存管理机制,可能会影响Redis的性能,生产环境推荐使用Linux系统。 - 注意Redis的内存占用,避免数据量过大导致系统资源紧张。 综上所述,"redis64 for windows"为Windows用户提供了在本地...
在IT行业中,尤其是在数据库管理和数据分析领域,有效地管理内存资源至关重要。本示例涉及的是使用Go语言来分析Redis数据库的内存占用情况,特别是针对特定Key前缀的键值对。Go语言因其高效、并发性强和丰富的库支持...
Redis是世界上最受欢迎的开源内存数据结构存储系统,它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。Redis集群(Redis Cluster)是Redis提供的分布式解决方案,允许用户在多台服务器上分布数据,以...
5. 并发控制:在高并发场景下,使用乐观锁或者Redis的事务机制来保证数据一致性。 在实际项目中,Redis还可以用于实现消息队列,例如使用发布/订阅模型实现广播消息,或者使用列表、队列数据结构进行工作队列处理。...
通过cpp-RCT,你可以得到关于Redis数据的详细信息,包括键的类型、过期时间、占用的内存大小等,这对于优化Redis的性能和内存管理至关重要。 在cpp-RCT中,有以下几个核心功能: 1. **RDB文件解析**:cpp-RCT能够...
**Redis**作为一个内存数据库,具有快速读写能力。在学生管理系统中,它可以存储常用的学生信息,如热门查询结果,从而提高查询效率。Redis支持多种数据结构,如字符串、哈希、列表、集合和有序集合,这些数据结构...
hiredis库提供了一些内建的内存管理机制,例如`redisFree`用于释放`redisContext`,`freeReplyObject`用于释放`redisReply`。 8. **RedisDemo.sln和RedisDemo**: 提供的`RedisDemo.sln`是Visual Studio的解决...
8. **内存管理**:Redis 默认在内存中存储所有数据,但可以通过 LRU(Least Recently Used)或 LFU(Least Frequently Used)策略进行淘汰,以控制内存使用。 9. **连接池**:客户端应用通常会使用连接池来管理与 ...