服务器

服务器基本操作


4.虚拟内存

<h1>虚拟内存介绍</h1> <pre><code>首先说明下redis的虚拟内存与操作系统虚拟内存不是一码事, 但是思路和目的都是相同的。 就是暂时把不经常访问的数据从内存交换到磁盘中, 从而腾出宝贵的内存空间。 对于 redis这样的内存数据库,内存总是不够用的。 除了可以将数据分割到多个redis 服务器以外。 另外的能够提高数据库容量的办法就是使用虚拟内存技术把那些不经常访问的数据交换到磁盘上。 如果我们存储的数据总是有少部分数据被经常访问, 大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。 当少量数据被经常访问时,使用虚拟内存不但能提高单台redis数据库服务器的容量, 而且也不会对性能造成太多影响。 redis没有使用操作系统提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内存机制。 主要的理由有以下两点,操作系统的虚拟内存是以4k/页为最小单位进行交换的。 而redis的大多数对象都远小于4k,所以一个操作系统页上可能有多个redis对象。 另外redis的集合对象类型如 list,set可能存在于多个操作系统页上。 最终可能造成只有10%的key被经常访问,但是所有操作系统页都会被操作系统认为是活跃的, 这样只有内存真正耗尽时操作系统才会进行页的交换。相比操作系统的交换方式。 redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。 一般压缩后的对象会比内存中的对象小 10倍。 这样redis的虚拟内存会比操作系统的虚拟内存少做很多IO操作。</code></pre> <h1>一、虚拟内存相关设置</h1> <h3>1. VM相关配置</h3> <h6>通过在redis的redis.conf文件里,设置VM的相关参数来实现数据在内存和磁盘之间换入和换出操作。 相关配置如下:</h6> <pre><code> #开启vm功能 vm-enabled yes #交换出来的value保存的文件路径 vm-swap-file /tmp/redis.swap #设置当内存消耗达到上限时开始将value交换出来 vm-max-memory 268435456 #设置单个页面的大小,单位是字节 redis使用的最大内存上限(256MB)超过上限后 redis开始交换value到磁盘swap文件中 vm-page-size 32 #设置最多能交换保存多少个页到磁盘 每个redis页的大小32个字节 #另一个文档 // 最多在文件中使用多少个页,交换文件的大小 =(vm-page-size* vm-pages)4 GB vm-pages 13417728 #设置完成交换动作的工作线程数,设置为0表示不使用工作线程而使用主线程,这会以阻塞的方式来运行。建议设置成CPU核个数 vm-max-threads 4</code></pre> <h3>2. 配置说明</h3> <pre><code>redis规定同一个数据页面只能保存一个对象,但一个对象可以保存在多个数据页面中。 在redis使用的内存没超过vm-max-memory时,是不会交换任何value到磁盘上的。 当超过最大内存限制后,redis会选择较老的对象(如果两个对象一样老会优先交换比较大的对象)将它从内存中移除,这样会更加节约内存。 对于Redis来说,一个数据页面只会保存一个对象,也就是一个Value值, 所以应该将vm-page-size设置成大多数value可以保存进去。 如果设置太小,一个value对象就会占用几个数据页面,如果设置太大,就会造成页面空闲空间浪费。</code></pre> <h1>二、 VM的工作机制</h1> <h4>redis的VM的工作机制分为两种:一种是vm-max-threads=0,一种是vm-max-threads&gt;0。</h4> <h6>1. 第一种:vm-max-threads = 0</h6> <pre><code>数据换出:主线程定期检查使用的内存大小,如果发现内存超出最大上限,会直接以阻塞的方式,将选中的对象换出到磁盘上(保存到文件中), 并释放对象占用的内存,此过程会一直重复直到下面条件满足任意一条才结束: 1.内存使用降到最大限制以下。 2.设置的交换文件数量达到上限。 3.几乎全部的对象都被交换到磁盘了。 数据换入:当有client请求key对应的value已被换出到磁盘中时,主线程会以阻塞的方式从换出文件中加载对应的value对象, 加载时此时会阻塞所有client,然后再处理client的请求。这种方式会阻塞所有的client。</code></pre> <h6>2. 第二种:vm-max-threads &gt; 0</h6> <pre><code>数据换出:当主线程检测到使用内存超过最大上限,会将选中的要交换的数据放到一个队列中交由工作线程后台处理,主线程会继续处理client请求。 数据换入:当有client请求key的对应的value已被换出到磁盘中时,主线程先阻塞当前client,然后将加载对象的信息放到一个队列中, 让工作线程去加载,此时进主线程继续处理其他client请求。加载完毕后工作线程通知主线程, 主线程再执行被阻塞的client的命令。这种方式只阻塞单个client。 总的来说blocking vm的方式总的性能会好一些,因为不需要线程同步,创建线程和恢复被阻塞的client等开销。 但是也相应的牺牲了响应性。threaded vm的方式主线程不会阻塞在磁盘io上,所以响应性更好。如果我们的应用不太经常发生换入换出, 而且也不太在意有点延迟的话则推荐使用blocking vm的方式。关于redis vm的更详细介绍可以参考下面链接 总结:Redis直接自己构建了VM 机制 ,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求,而Redis不存在。 这也是Redis能够那么快的一个原因。 redis没有使用os提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内存机制的原因有如下: 1.os 的虚拟内存是以4k页面为最小单位进行交换的。 而redis的大多数对象都远小于4k, 所以一个os页面上可能有多个redis对象。 另外redis的集合对象类型如list,set可能存在与多个os页面上。 最终可能造成只有10%key被经常访问,但是所有os页面都会被os认为是活跃的, 这样只有内存真正耗尽时os才会交换页面。 2.相比于os的交换方式。 redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。 一般压缩后的对象会比内存中的对象小10倍。 这样redis的vm会比os vm能少做很多io操作。 </code></pre> <h4>摘选自</h4> <p><a href="https://blog.csdn.net/qq_42410605/article/details/122849629">https://blog.csdn.net/qq_42410605/article/details/122849629</a></p>

页面列表

ITEM_HTML