重点提示:
Redis 的虚拟内存(VM) 目前不被提倡使用,Redis 2.4将是有虚拟内存特性的最新版本(但它同样提示不鼓励使用虚拟内存)。我们发现使用虚拟内存会有一些不足和问题。对于Redis的未来,至少目前在不考虑支持比RAM更大的数据库时,我们希望能提供最好的内存数据库(持久化仍然在磁盘上)。我们随后的成果将关注提供脚本,集群以及更好的持久化方面。
虚拟内存
Redis 虚拟内存这一特性将首次出现在Redis 2.0的一个稳定发布版中。目前Git上Redis 不稳定分支的虚拟内存(从现在起称之为VM)已经可以使用,并且经试验证明足够稳定。
简介
Redis遵循 key-value模型。同时key和value通常都存储在内存中。然而有时这并不是一个最好的选择,所以在设计过程中我们要求key必须存储在内存中(为了保证快速查找),而value在很少使用时,可以从内存被交换出至磁盘上。
实际应用中,如果内存中有一个10万条记录的key值数据集,而只有10%被经常使用,那么开启虚拟内存的Redis将把与较少使用的key相对应的value转移至磁盘上。当客户端请求获取这些value时,他们被将从swap 文件中读回,并载入到内存中。
何时使用虚拟内存
在确定使用VM之前,请首先确认是否真的需要使用这一特性。Redis是一个磁盘备份,内存型数据库。使用Redis 的正确方法通常是使用足够大的RAM去装载所有数据。然而,有些场景下是无法做到这样的:
- 数据访问不均匀。只有很少部分的key被大量访问,而每一个key又有大量的数据要放入内存。
- 在不考虑数据读取方式以及value存储空间大小的前提下,仅由于没有足够的空间将所有数据放入内存。这种场景下,Redis可以被配置为在内存中存储key,在磁盘中存储value。此时key的查询操作较快,而value的读取则相对较慢。
VM 配置
VM的配置相对简单,可以根据需求设置最佳参数。通过编辑redis.conf来开启并配置VM。首先开启VM:
vm-enabled yes
很多配置项可以改变VM的行为。事实上,为了获取最佳性能,你常常需要对配置做微调,而非使用默认参数。
vm-max-memory设置
vm-max-memory 指 Redis 在将value交换至磁盘(进行swap操作)之前有多大内存可使用。 通常,如果未达到内存上限,则不需要进行磁盘交换,Redis将所有对象放在内存中操作。然而一旦到达上限,将会有大量的对象被交换出内存至磁盘,以释放内存空间,直到低于限制。 交换过程(swap操作)中,首先被交换的对象是那些有着较大“年龄”(指未被访问的时长)的对象,同时一个对象的“交换能力”(”swappability”)与它在内存中大小的对数成正(swappability = age*log(size_in_memory))。当两个对象有着相同的“年龄”时,占用空间较大的对象将会首先被交换出去。 提醒:由于key不能被交换出内存,所以当仅由于key占用空间较多而达到内存上限时, Redis是不能通过改变 vm-max-memory 来解决问题的。 最好将该值设置到可以用RAM装载整个数据的工作集(working set)。实际中,当Redis有足够的内存时,交换操作(swap)也将进行的更加顺利。配置swap文件
Redis利用swap文件将数据从内存转移到磁盘。swap文件并不对数据的存储时间做处理,当一个Redis应用结束时,swap文件可以被清除。然而,当Redis运行时不能以任何形式移动,删除或改变 swap文件。由于Redis的swap文件通常以随机读取的方式被使用,所以用ssd(固态硬盘)存储swap文件性能将更好。 swap文件按“页”(page)切分。 一个值可以被交换(swap)到一个或多个页中,但是一个页最多只能存储一个值。 没有直接的方式可以获取Redis的swap文件将有多少字节被使用。然而,可以利用两个不同的配置参数,将其做乘积计算出使用的字节总数。这两个参数分别表示交换文件的页数和页大小,它们可以在redis.conf文件中配置:- vm-pages 用于配置swap文件中页的总数
- vm-page-size 用于配置页的字节数
线程式虚拟内存 vs 阻塞式虚拟内存
另一个重要的配置参数是 vm-max-threads: # The default vm-max-threads configuration vm-max-threads 4
该参数用于设置Redis与swap文件进行I/O的最大线程数。
通常令其等于系统的cpu核数。
当该参数设置为“0”时,将开启阻塞式虚拟内存。此时,它将以同步阻塞的方式进行I/0. 阻塞式虚拟内存有如下特性:
- 当客户端从磁盘上读取被交换出去的key时,将阻塞其他客户端,所以该方式经历时延较长,尤其当磁盘较慢或者有大存储的数据发生交换时。
- 总体说来,由于在进行同步、增加线程和恢复由于等待value而阻塞的客户端时没有时间损耗,阻塞式虚拟内存表现更好一些。所以如果你能接受偶尔较高的时延,阻塞式虚拟内存将是一个好的选择。尤其在发生交换较少,同时大部分你经常访问的数据恰好可以放入内存时。
要知道的一些事情
swap文件的存放
在很多配置中swap文件可以很大,达到40GB或者更大。然而并不是所有的文件系统都可以很好的处理大文件,尤其是Mac OS X的文件系统,常常会显得异常蹩脚。 建议使用 linux ext3文件系统,或者其他可以很好支持稀疏文件的文件系统。 什么是稀疏文件? 稀疏文件指有大量内容为空的文件。高级一些的文件系统例如ext2, ext3, ext4,ReiserFS, Reiser4和其他一些文件 可以用一种更高效的方式编码这些文件,同时当文件有更多的块(block)需要被使用时,则为该文件分配更多的空间。 swap文件很稀疏的。当一次创建一个很大的文件时,不支持稀疏文件的文件系统可能会阻塞Redis进程。 参考 wikepedia page 了解支持稀疏文件的文件系统。 虚拟内存的监控 一旦使用了开启虚拟内存的Redis,你可能很感兴趣它是怎样工作的:总共多少个对象被交换,每秒交换与载入的对象量等等。 下面是一个用于检查VM是如何工作的工具( 见此处 )。作为Redis 工具的一部分,redis-stat简单易用:
$ ./redis-stat vmstat
--------------- objects --------------- ------ pages ------ ----- memory -----
load-in swap-out swapped delta used delta used delta
138837 1078936 800402 +800402 807620 +807620 209.50M +209.50M
4277 38011 829802 +29400 837441 +29821 206.47M -3.03M
3347 39508 862619 +32817 870340 +32899 202.96M -3.51M
4445 36943 890646 +28027 897925 +27585 199.92M -3.04M
10391 16902 886783 -3863 894104 -3821 200.22M +309.56K
8888 19507 888371 +1588 895678 +1574 200.05M -171.81K
8377 20082 891664 +3293 899850 +4172 200.10M +53.55K
9671 20210 892586 +922 899917 +67 199.82M -285.30K
10861 16723 887638 -4948 895003 -4914 200.13M +312.35K
9541 21945 890618 +2980 898004 +3001 199.94M -197.11K
9689 17257 888345 -2273 896405 -1599 200.27M +337.77K
10087 18784 886771 -1574 894577 -1828 200.36M +91.60K
9330 19350 887411 +640 894817 +240 200.17M -189.72K
上面是一个redis-server 在虚拟内存开启,内部含有大约 1千万条key,同时利用redis-load 工具做大量仿真负载时的输出结果。从输出中你可以看到每秒有大量的“载入”和“交换”操作。请注意第一行显示从服务器开启时到现在的实际数值,下面几行不同于之前读取的数值。
如果你分配了足够的内存,可能会看到很多不太明显的交换,而redis-stat 是一个非常有用的工具,可以帮你判断是否需要更换RAM了。
开启虚拟内存的Redis :.rdb文件还是 AOF(Append Only File)文件更合适 ?
当虚拟内存开启时,保存和读取数据库操作都将变慢。当服务器被配置为用最少的内存时(即vm-max-memory 被设置为0),一个通常2s载入一次的DB操作,在开启虚拟内存时耗时将长达13s,所以你可能希望切换使用AOF的配置来实现持久化,以便可以进行BGREWRITEAOF操作。
请注意 当进程进行 BGSAVE 或者 BGREWRITEAOF 操作时,Redis不会在磁盘上交换新的value.
当有子进程访问虚拟内存时,虚拟内存将是只读的。所以,当有一个子进程有大量的写操作时,内存使用将增加。
减少使用内存
将 vm-max-memory设置为0,可以使Redis转为仅有key在内存中的磁盘数据库。当你希望使用尽可能少的内存存储大容量数值, 同时不介意时延或者相对糟糕的性能时,这是不错的选择。
该设置中你应该首先尝试着将虚拟内存设置为阻塞式(vm-max-threads 0)的。大量的交换入和交换出操作将带来巨大的开销,与单线程阻塞式虚拟内存相比,线程式虚拟内存将消耗大量的资源 。
虚拟内存的稳定性
虚拟内存仍处于试验阶段,但在过去的数周里,它已经以各种方式被应用到开发环境中,甚至一些产品中。目前,在测试阶段并没有发现bug,然而更多不确定的bug可能会在日后某些不可控的环境中发生,而这些环境常常由于一些原因而无法复现。
当前阶段,我们鼓励你在开发过程中尝试使用虚拟内存,甚至在产品中,如果你的db不是至关重要的话。
请报告任何你注意到的问题到the Redis Google Group,或者通过IRC加入 #redis IRC。
原文:https://ifeve.com/redis-mem/
![89cb928e2f6c429a4f180afe2b4f335f.png](https://i-blog.csdnimg.cn/blog_migrate/3be3d626937590178847bd3f07416db6.png)
![c6cd8b5efe65d72de49fc03df330ecd1.gif](https://i-blog.csdnimg.cn/blog_migrate/238f7d7003dae03cc16af98f97a3d061.gif)
![6ef275f315620fa8438d0f12a02c6831.png](https://i-blog.csdnimg.cn/blog_migrate/398ba056c4d74d0e84977890018796c3.png)
想要获取学习实战、高并发、架构 、笔试面试资料请扫码咨询+薇薇微信