]> git.saurik.com Git - redis.git/blob - doc/VirtualMemoryUserGuide.html
smarter swapout policy on AOF too
[redis.git] / doc / VirtualMemoryUserGuide.html
1
2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
3 <html>
4 <head>
5 <link type="text/css" rel="stylesheet" href="style.css" />
6 </head>
7 <body>
8 <div id="page">
9
10 <div id='header'>
11 <a href="index.html">
12 <img style="border:none" alt="Redis Documentation" src="redis.png">
13 </a>
14 </div>
15
16 <div id="pagecontent">
17 <div class="index">
18 <!-- This is a (PRE) block. Make sure it's left aligned or your toc title will be off. -->
19 <b>VirtualMemoryUserGuide: Contents</b><br>&nbsp;&nbsp;<a href="#Virtual Memory User Guide">Virtual Memory User Guide</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Virtual Memory explained in simple words">Virtual Memory explained in simple words</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#When using Virtual Memory is a good idea">When using Virtual Memory is a good idea</a><br>&nbsp;&nbsp;<a href="#VM Configuration">VM Configuration</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#The vm-max-memory setting">The vm-max-memory setting</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Configuring the swap file">Configuring the swap file</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Threaded VM vs Blocking VM">Threaded VM vs Blocking VM</a><br>&nbsp;&nbsp;<a href="#Random things to know">Random things to know</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#A good place for the swap file">A good place for the swap file</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Monitoring the VM">Monitoring the VM</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Redis with VM enabled: better .rdb files or Append Only File?">Redis with VM enabled: better .rdb files or Append Only File?</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Using as little memory as possible">Using as little memory as possible</a><br>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#VM Stability">VM Stability</a>
20 </div>
21
22 <h1 class="wikiname">VirtualMemoryUserGuide</h1>
23
24 <div class="summary">
25
26 </div>
27
28 <div class="narrow">
29 &iuml;&raquo;&iquest;#sidebar <a href="RedisGuides.html">RedisGuides</a><h1><a name="Virtual Memory User Guide">Virtual Memory User Guide</a></h1>Redis Virtual Memory is a feature that will appear for the first time in a stable Redis distribution in Redis 2.0. However Virtual Memory (called VM starting from now) is already available and stable enough to be tests in the unstable branch of Redis available <a href="http://github.com/antirez/redis" target="_blank">on Git</a>.<h2><a name="Virtual Memory explained in simple words">Virtual Memory explained in simple words</a></h2>Redis follows a Key-Value model. You have keys associated with some values.
30 Usually Redis takes both Keys and associated Values in memory. Sometimes this is not the best option, and while Keys <b>must</b> be taken in memory for the way Redis is designed (and in order to ensure fast lookups), Values can be swapped out to disk when they are rarely used.<br/><br/>In practical terms this means that if you have a dataset of 100,000 keys in memory, but only 10% of this keys are often used, Redis with Virtual Memory enabled will try to transfer the values associated to the rarely used keys on disk.<br/><br/>When this values are requested, as a result of a command issued by a client, the values are loaded back from the swap file to the main memory.<h2><a name="When using Virtual Memory is a good idea">When using Virtual Memory is a good idea</a></h2>Before using VM you should ask yourself if you really need it. Redis is a disk backed, in memory database. The right way to use Redis is almost always to have enough RAM to fit all the data in memory. Still there are a scenarios where to hold all the data in memory is not possible:
31 <ul><li> Data access is very biased. Only a small percentage of keys (for instance related to active users in your web site) gets the vast majority of accesses. At the same time there is too much data per key to take everything in memory.</li><li> There is simply not enough memory available to hold all the data in memory, regardless of the data access pattern, and values are large. In this configuration Redis can be used as an on-disk DB where keys are in memory, so the key lookup is fast, but the access to the actual values require accessing the (slower) disk.</li></ul>
32 An important concept to take in mind is that Redis <b>is not able to swap the keys</b>, so if your memory problems are related to the fact you have too much keys with very small values, VM is not the solution.<br/><br/>Instead if a good amount of memory is used because values are pretty large (for example large strings, lists, sets or hashes with many elements), then VM can be a good idea.<br/><br/>Sometimes you can turn your &quot;many keys with small values&quot; problem into a &quot;less keys but with very large values&quot; one just using Hashes in order to group related data into fields of a single key. For instance instead of having a key for every attribute of your object you have a single key per object where Hash fields represent the different attributes.<h1><a name="VM Configuration">VM Configuration</a></h1>Configuring the VM is not hard but requires some care to set the best parameters accordingly to the requirements.<br/><br/>The VM is enabled and configured editing redis.conf, the first step is switching it on with:<br/><br/><pre class="codeblock python" name="code">
33 vm-enabled yes
34 </pre>Many other configuration options are able to change the behavior of VM. The rule is that you don't want to run with the default configuration, as every problem and dataset requires some tuning in order to get the maximum advantages.<h2><a name="The vm-max-memory setting">The vm-max-memory setting</a></h2>The <b>vm-max-memory</b> setting specifies how much memory Redis is free to use before starting swapping values on disk.<br/><br/>Basically if this memory limit is still not reached, no object will be swapped, Redis will work all in memory as usually. Once this limit is hit, enough objects are swapped out in order to return just under the limit.<br/><br/>The swapped objects are the one with the highest &quot;age&quot; (that is, the number of seconds since they are not used in any way) mainly, but the &quot;swappability&quot; of an object is also proportional to the logarithm of it's size in memory. So basically older objects are preferred, but when they are about the same size, bigger objects are preferred.<br/><br/><b>WARNING:</b> Because keys can't be swapped out, Redis will not be able to honour the <b>vm-max-memory</b> setting if the keys alone are using more space than the limit.<br/><br/>The best value for this setting is enough RAM in order to hold the &quot;working set&quot; of data. In practical terms, just give Redis as much memory as you can, and swapping will work better.<h2><a name="Configuring the swap file">Configuring the swap file</a></h2>In order to transfer data from memory to disk, Redis uses a swap file. The swap file has nothing to do with durability of data, and can be removed when a Redis instance is terminated. Still the swap file should not be moved, deleted, or altered in any other way while Redis is running.<br/><br/>Because the Redis swap file is used mostly in a random access fashion, to put the swap file into a Solid State Disk will lead to better performances.<br/><br/>The swap file is divided into &quot;pages&quot;. A value can be swapped into one or multiple pages, but a single page can't hold more than a value.<br/><br/>There is no direct way to tell Redis how much bytes of swap file it should be using. Instead two different values are configured, that multiplied together will produce the total number of bytes used. This two values are the number of pages inside the swap file, and the page size. It is possible to configure this two parameters in redis.conf.<br/><br/><ul><li> The <b>vm-pages</b> configuration directive is used to set the total number of pages in the swap file.</li><li> the <b>vm-page-size</b> configuration directive is used in order to set the page size in bytes.</li></ul>
35 So for instance if the page size is set to the value of 32 bytes, and the total number of pages is set to 10000000 (10 millions), the swap file can hold a total of 320 MB of data.<br/><br/>Because a single page can't be used to hold more than a value (but a value can be stored into multiple pages), care must be taken in setting this parameters.
36 Usually the best idea is setting the page size so that the majority of the values can be swapped using a few pages.<h2><a name="Threaded VM vs Blocking VM">Threaded VM vs Blocking VM</a></h2>Another very important configuration parameter is <b>vm-max-threads</b>:<br/><br/><pre class="codeblock python python" name="code">
37 # The default vm-max-threads configuration
38 vm-max-threads 4
39 </pre>This is the maximum number of threads used in order to perform I/O from/to the swap file. A good value is just to match the number of cores in your system.<br/><br/>However the special value of &quot;0&quot; will enable blocking VM. When VM is configured to be blocking it performs the I/O in a synchronous blocking way. This is what you can expect from blocking VM:
40 <ul><li> Clients accessing swapped out keys will block other clients while reading from disk, so the latency experimented by clients can be larger, especially if the disk is slow or busy and/or if there are big values swapped on disk.</li><li> The blocking VM performances are <b>overall</b> better, as there is no time lost in synchronization, spawning of threads, resuming blocked clients waiting for values.</li></ul>So if you are willing to accept an higher latency from time to time, blocking VM can be a good pick, especially if swapping happens rarely as most of your often accessed data happens to fit in your memory.<br/><br/>If instead you have a lot of swap in and swap out operations and you have many cores that you want to exploit, and in general when you don't want that clients dealing with swapped values will block other clients for a few milliseconds (or more if the swapped value is very big), then it's better to use threaded VM.<br/><br/>To experiment with your dataset and different configurations is warmly encouraged...<h1><a name="Random things to know">Random things to know</a></h1>
41 <h2><a name="A good place for the swap file">A good place for the swap file</a></h2>In many configurations the swap file can be fairly large, even 40GB or more.
42 Not all the kind of file systems are able to deal with large files in a good way, especially Mac OS X file system tends to be really lame about it.<br/><br/>The suggestion is to use Linux ext3 file system, or any other file system with good support for <b>sparse files</b>. What are sparse files?<br/><br/>Sparse files are files where a lot of the content happen to be empty. Advanced file systems like ext2, ext3, ext4, RaiserFS, Raiser4, and many others, are able to encode this files in a more efficient way and will allocate more space for the file when needed, that is, when more actual blocks of the file will be used.<br/><br/>The swap file is obviously pretty sparse, especially if the server is running since little time or it is much bigger compared to the amount of data swapped out. A file system not supporting sparse files can at some point block the Redis process while creating a very big file at once.<br/><br/>For a list of file systems supporting spare files <a href="http://en.wikipedia.org/wiki/Comparison_of_file_systems" target="_blank">check this Wikipedia page comparing different files systems</a>.<h2><a name="Monitoring the VM">Monitoring the VM</a></h2>Once you have a Redis system with VM enabled up and running, you may be very interested in knowing how it's working: how many objects are swapped in total, the number of objects swapped and loaded every second, and so forth.<br/><br/>There is an utility that is very handy in checking how the VM is working, that is part of <a href="http://code.google.com/p/redis-tools" target="_blank">Redis Tools</a>. This tool is called redis-stat, and using it is pretty straightforward:<br/><br/><pre class="codeblock python python python" name="code">
43 $ ./redis-stat vmstat
44 --------------- objects --------------- ------ pages ------ ----- memory -----
45 load-in swap-out swapped delta used delta used delta
46 138837 1078936 800402 +800402 807620 +807620 209.50M +209.50M
47 4277 38011 829802 +29400 837441 +29821 206.47M -3.03M
48 3347 39508 862619 +32817 870340 +32899 202.96M -3.51M
49 4445 36943 890646 +28027 897925 +27585 199.92M -3.04M
50 10391 16902 886783 -3863 894104 -3821 200.22M +309.56K
51 8888 19507 888371 +1588 895678 +1574 200.05M -171.81K
52 8377 20082 891664 +3293 899850 +4172 200.10M +53.55K
53 9671 20210 892586 +922 899917 +67 199.82M -285.30K
54 10861 16723 887638 -4948 895003 -4914 200.13M +312.35K
55 9541 21945 890618 +2980 898004 +3001 199.94M -197.11K
56 9689 17257 888345 -2273 896405 -1599 200.27M +337.77K
57 10087 18784 886771 -1574 894577 -1828 200.36M +91.60K
58 9330 19350 887411 +640 894817 +240 200.17M -189.72K
59 </pre>The above output is about a redis-server with VM enable, around 1 million of keys inside, and a lot of simulated load using the redis-load utility.<br/><br/>As you can see from the output a number of load-in and swap-out operations are happening every second. Note that the first line reports the actual values since the server was started, while the next lines are differences compared to the previous reading.<br/><br/>If you assigned enough memory to hold your working set of data, probably you should see a lot less dramatic swapping happening, so redis-stat can be a really valuable tool in order to understand if you need to shop for RAM ;)<h2><a name="Redis with VM enabled: better .rdb files or Append Only File?">Redis with VM enabled: better .rdb files or Append Only File?</a></h2>When VM is enabled, saving and loading the database are <b>much slower</b> operations. A DB that usually loads in 2 seconds takes 13 seconds with VM enabled if the server is configured to use the smallest memory possible (that is, vm-max-memory set to 0).<br/><br/>So you probably want to switch to a configuration using the Append Only File for persistence, so that you can perform the BGREWRITEAOF from time to time.<br/><br/>It is important to note that while a BGSAVE or BGREWRITEAOF is in progress Redis does <b>not</b> swap new values on disk. The VM will be read-only while there is another child accessing it. So if you have a lot of writes while there is a child working, the memory usage may grow.<h2><a name="Using as little memory as possible">Using as little memory as possible</a></h2>An interesting setup to turn Redis into an on-disk DB with just keys in memory is setting vm-max-memory to 0. If you don't mind some latency more and poorer performances but want to use very little memory for very big values, this is a good setup.<br/><br/>In this setup you should first try setting the VM as blocking (vm-max-threads 0) as with this configuration and high traffic the number of swap in and swap out operations will be huge, and threading will consume a lot of resources compared to a simple blocking implementation.<h2><a name="VM Stability">VM Stability</a></h2>VM is still experimental code, but in the latest weeks it was tested in many ways in development environments, and even in some production environment. No bugs were noticed during this testing period. Still the more obscure bugs may happen in non controlled environments where there are setups that we are not able to reproduce for some reason.<br/><br/>In this stage you are encouraged to try VM in your development environment, and even in production if your DB is not mission critical, but for instance just a big persistent cache of data that may go away without too much problems.<br/><br/>Please report any problem you will notice to the Redis Google Group or by IRC joining the #redis IRC channel on freenode.
60
61 </div>
62
63 </div>
64 </div>
65 </body>
66 </html>
67