﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-阿二的梦想船-随笔分类-redis</title><link>http://www.cppblog.com/richbirdandy/category/18254.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 30 Nov 2011 14:11:43 GMT</lastBuildDate><pubDate>Wed, 30 Nov 2011 14:11:43 GMT</pubDate><ttl>60</ttl><item><title>redis如何删除过期数据</title><link>http://www.cppblog.com/richbirdandy/archive/2011/11/29/161184.html</link><dc:creator>阿二</dc:creator><author>阿二</author><pubDate>Tue, 29 Nov 2011 11:57:00 GMT</pubDate><guid>http://www.cppblog.com/richbirdandy/archive/2011/11/29/161184.html</guid><wfw:comment>http://www.cppblog.com/richbirdandy/comments/161184.html</wfw:comment><comments>http://www.cppblog.com/richbirdandy/archive/2011/11/29/161184.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/richbirdandy/comments/commentRss/161184.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richbirdandy/services/trackbacks/161184.html</trackback:ping><description><![CDATA[<div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span class="Apple-style-span" style="font-size: 14px; "><span style="font-family: 宋体; font-size: 12pt; ">随着</span><span style="font-size: 12pt; ">nosql</span><span style="font-family: 宋体; font-size: 12pt; ">风潮兴起，</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">作为当中一个耀眼的明星，也越来越多的被关注和使用，我在工作中也广泛的用到了</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">来充当</span><span style="font-size: 12pt; ">cache</span><span style="font-family: 宋体; font-size: 12pt; ">和</span><span style="font-size: 12pt; ">key-value DB</span><span style="font-family: 宋体; font-size: 12pt; ">，但当大家发现数据越来越多时</span><span style="font-family: 宋体; font-size: 12pt; ">，不禁有些担心，</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">能撑的住吗，虽然官方已经有漂亮的</span><span style="font-size: 12pt; ">benchmark</span><span style="font-family: 宋体; font-size: 12pt; ">，自己也可以做做压力测试，但是看看源码，也是确认问题最直接的办法之一。比如目前我们要确认的一个问题是，</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">是如何删除过期数据的？</span></span></div>  <p><span style="font-family: 宋体; font-size: 12pt; ">用一个可以</span><span style="font-size: 12pt; ">"find reference"</span><span style="font-family: 宋体; font-size: 12pt; ">的</span><span style="font-size: 12pt; ">IDE,</span><span style="font-family: 宋体; font-size: 12pt; ">沿着</span><span style="font-size: 12pt; ">setex(</span><span style="color: maroon; font-size: 12pt; ">Set the value and expiration of a key</span><span style="color: maroon; font-size: 12pt; ">)</span><span style="font-family: 宋体; font-size: 12pt; ">命令一窥究竟：</span></p>  <p style="text-autospace:none"><font class="Apple-style-span" color="#0000FF" size="4"></font></p><font class="Apple-style-span" color="#0000FF" size="4"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;setexCommand(redisClient&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">c)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tryObjectEncoding(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;setGenericCommand(c,</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]);<br />}</span></div></font>  <p><span style="color: black; font-size: 12pt; ">setGenericCommand</span><span style="font-family: 宋体; font-size: 12pt; ">是一个实现</span><span style="font-size: 12pt; ">set,setnx,setex</span><span style="font-family: 宋体; font-size: 12pt; ">的通用函数，参数设置不同而已。</span></p>  <p style="text-autospace:none"><font class="Apple-style-span" color="#0000FF" size="4"></font></p><font class="Apple-style-span" color="#0000FF" size="4"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;setCommand(redisClient&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">c)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tryObjectEncoding(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;setGenericCommand(c,</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">],NULL);<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;setnxCommand(redisClient&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">c)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tryObjectEncoding(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;setGenericCommand(c,</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">],NULL);<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;setexCommand(redisClient&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">c)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tryObjectEncoding(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;setGenericCommand(c,</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">],c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">argv[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]);<br />}</span></div></font>  <p><span style="font-family: 宋体; color: black; font-size: 12pt; ">再看</span><span style="color: black; font-size: 12pt; ">setGenericCommand</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;setGenericCommand(redisClient&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">c,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nx,&nbsp;robj&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">key,&nbsp;robj&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">val,&nbsp;robj&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">expire)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;seconds&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;initialized&nbsp;to&nbsp;avoid&nbsp;an&nbsp;harmness&nbsp;warning&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(expire)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(getLongFromObjectOrReply(c,&nbsp;expire,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">seconds,&nbsp;NULL)&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;REDIS_OK)<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(seconds&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addReplyError(c,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">invalid&nbsp;expire&nbsp;time&nbsp;in&nbsp;SETEX</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(lookupKeyWrite(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">db,key)&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;nx)&nbsp;{<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addReply(c,shared.czero);<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;setKey(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">db,key,val);<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;server.dirty</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(expire)&nbsp;setExpire(c</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">db,key,time(NULL)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">seconds);&nbsp;<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;addReply(c,&nbsp;nx&nbsp;</span><span style="color: #000000; ">?</span><span style="color: #000000; ">&nbsp;shared.cone&nbsp;:&nbsp;shared.ok);<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">22</span>&nbsp;</div>  <p><span style="font-size: 12pt; ">13</span><span style="font-family: 宋体; font-size: 12pt; ">行处理</span><span style="color: maroon; font-size: 12pt; ">"Set the value of a key, only if the key does not exist"</span><span style="font-family: 宋体; color: maroon; font-size: 12pt; ">的场景，</span><span style="font-size: 12pt; ">17</span><span style="font-family: 宋体; font-size: 12pt; ">行插入这个</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">，</span><span style="font-size: 12pt; ">19</span><span style="font-family: 宋体; font-size: 12pt; ">行设置它的超时，注意时间戳已经被设置成了到期时间。这里要看一下</span><span style="color: black; font-size: 12pt; ">redisDb</span><span style="font-size: 12pt; ">(</span><span style="font-family: 宋体; font-size: 12pt; ">即</span><span style="color: black; font-size: 12pt; ">c</span><span style="font-size: 12pt; ">-&gt;<span style="color: black; font-size: 12pt; ">db</span></span><span style="color: black; font-size: 12pt; ">)</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的定义：</span></p>  <p style="text-autospace:none"><font class="Apple-style-span" color="#0000FF" size="4"></font></p><font class="Apple-style-span" color="#0000FF" size="4"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">typedef&nbsp;</span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;redisDb&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;dict&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">dict;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;The&nbsp;keyspace&nbsp;for&nbsp;this&nbsp;DB&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;dict&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">expires;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Timeout&nbsp;of&nbsp;keys&nbsp;with&nbsp;a&nbsp;timeout&nbsp;set&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;dict&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">blocking_keys;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Keys&nbsp;with&nbsp;clients&nbsp;waiting&nbsp;for&nbsp;data&nbsp;(BLPOP)&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;dict&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">io_keys;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Keys&nbsp;with&nbsp;clients&nbsp;waiting&nbsp;for&nbsp;VM&nbsp;I/O&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;dict&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">watched_keys;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;WATCHED&nbsp;keys&nbsp;for&nbsp;MULTI/EXEC&nbsp;CAS&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;id;<br />}&nbsp;redisDb;</span></div></font>  <p><span style="font-family: 宋体; font-size: 12pt; ">仅关注</span><span style="color: black; font-size: 12pt; ">dict</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">和</span><span style="color: black; font-size: 12pt; ">expires</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，分别来存</span><span style="color: black; font-size: 12pt; ">key-value</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">和它的超时，也就是说如果一个</span><span style="color: black; font-size: 12pt; ">key-value</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">是有超时的，那么它会存在</span><span style="color: black; font-size: 12pt; ">dict</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">里，同时也存到</span><span style="color: black; font-size: 12pt; ">expires</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">里，类似这样的形式：</span><span style="color: black; font-size: 12pt; ">dict[key]:value,expires[key]:timeout.</span></p>  <p><span style="font-family: 宋体; font-size: 12pt; ">当然</span><span style="font-size: 12pt; ">key-value</span><span style="font-family: 宋体; font-size: 12pt; ">没有超时，</span><span style="font-size: 12pt; ">expires</span><span style="font-family: 宋体; font-size: 12pt; ">里就不存在这个</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">。</span><span style="font-family: 宋体; font-size: 12pt; ">剩下</span><span style="color: black; font-size: 12pt; ">setKey</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">和</span><span style="color: black; font-size: 12pt; ">setExpire</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">两个函数无非是插数据到两个字典里，这里不再详述。</span></p>  <p><br /></p>  <p><span style="font-family: 宋体; color: black; font-size: 12pt; ">那么</span><span style="color: black; font-size: 12pt; ">redis</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">是如何删除过期</span><span style="color: black; font-size: 12pt; ">key</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的呢。</span></p>  <p><span style="font-family: 宋体; color: black; font-size: 12pt; ">通过查看</span><span style="color: black; font-size: 12pt; ">dbDelete</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的调用者，</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">首先注意到这一个函数，是用来删除过期</span><span style="color: black; font-size: 12pt; ">key</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的。</span></p>  <p style="margin-left:21.25pt;text-indent:-21.25pt;text-autospace:none"><font class="Apple-style-span" size="4"><span class="Apple-style-span" style="font-size: 16px;"></span></font></p><font class="Apple-style-span" size="4"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;expireIfNeeded(redisDb&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">db,&nbsp;robj&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">key)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;when&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;getExpire(db,key);<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(when&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;No&nbsp;expire&nbsp;for&nbsp;this&nbsp;key&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Don't&nbsp;expire&nbsp;anything&nbsp;while&nbsp;loading.&nbsp;It&nbsp;will&nbsp;be&nbsp;done&nbsp;later.&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(server.loading)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;If&nbsp;we&nbsp;are&nbsp;running&nbsp;in&nbsp;the&nbsp;context&nbsp;of&nbsp;a&nbsp;slave,&nbsp;return&nbsp;ASAP:<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;slave&nbsp;key&nbsp;expiration&nbsp;is&nbsp;controlled&nbsp;by&nbsp;the&nbsp;master&nbsp;that&nbsp;will<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;send&nbsp;us&nbsp;synthesized&nbsp;DEL&nbsp;operations&nbsp;for&nbsp;expired&nbsp;keys.<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Still&nbsp;we&nbsp;try&nbsp;to&nbsp;return&nbsp;the&nbsp;right&nbsp;information&nbsp;to&nbsp;the&nbsp;caller,&nbsp;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;that&nbsp;is,&nbsp;0&nbsp;if&nbsp;we&nbsp;think&nbsp;the&nbsp;key&nbsp;should&nbsp;be&nbsp;still&nbsp;valid,&nbsp;1&nbsp;if<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;we&nbsp;think&nbsp;the&nbsp;key&nbsp;is&nbsp;expired&nbsp;at&nbsp;this&nbsp;time.&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(server.masterhost&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;time(NULL)&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;when;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Return&nbsp;when&nbsp;this&nbsp;key&nbsp;has&nbsp;not&nbsp;expired&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(time(NULL)&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;when)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Delete&nbsp;the&nbsp;key&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;server.stat_expiredkeys</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;propagateExpire(db,key);<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;dbDelete(db,key);<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">28</span>&nbsp;</div></font>  <p><span style="font-size: 12pt; ">ifNeed</span><span style="font-family: 宋体; font-size: 12pt; ">表示能删则删，所以</span><span style="font-size: 12pt; ">4</span><span style="font-family: 宋体; font-size: 12pt; ">行没有设置超时不删，</span><span style="font-size: 12pt; ">7</span><span style="font-family: 宋体; font-size: 12pt; ">行在</span><span style="font-size: 12pt; ">"loading"</span><span style="font-family: 宋体; font-size: 12pt; ">时不删，</span><span style="font-size: 12pt; ">16</span><span style="font-family: 宋体; font-size: 12pt; ">行非主库不删，</span><span style="font-size: 12pt; ">21</span><span style="font-family: 宋体; font-size: 12pt; ">行未到期不删。</span><span style="font-size: 12pt; ">25</span><span style="font-family: 宋体; font-size: 12pt; ">行同步从库和文件。</span></p>  <p><span style="font-family: 宋体; color: black; font-size: 12pt; ">再看看哪些函数调用了</span><span style="color: black; font-size: 12pt; ">expireIfNeeded</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，有</span><span style="color: black; font-size: 12pt; ">lookupKeyRead</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，</span><span style="color: black; font-size: 12pt; ">lookupKeyWrite</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，</span><span style="color: black; font-size: 12pt; ">dbRandomKey</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，</span><span style="color: black; font-size: 12pt; ">existsCommand</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，</span><span style="color: black; font-size: 12pt; ">keysCommand</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">。通过这些函数命名可以看出，只要访问了某一个</span><span style="color: black; font-size: 12pt; ">key</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">，顺带做的事情就是尝试查看过期并删除，这就保证了用户不可能访问到过期的</span><span style="color: black; font-size: 12pt; ">key</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">。但是如果有大量的</span><span style="color: black; font-size: 12pt; ">key</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">过期，并且没有被访问到，那么就浪费了许多内存。</span><span style="color: black; font-size: 12pt; ">Redis</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">是如何处理这个问题的呢。</span></p>  <p><br /></p>  <p><span style="color: black; font-size: 12pt; ">dbDelete</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的调用者里还发现这样一个函数：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Try&nbsp;to&nbsp;expire&nbsp;a&nbsp;few&nbsp;timed&nbsp;out&nbsp;keys.&nbsp;The&nbsp;algorithm&nbsp;used&nbsp;is&nbsp;adaptive&nbsp;and<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;will&nbsp;use&nbsp;few&nbsp;CPU&nbsp;cycles&nbsp;if&nbsp;there&nbsp;are&nbsp;few&nbsp;expiring&nbsp;keys,&nbsp;otherwise<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;it&nbsp;will&nbsp;get&nbsp;more&nbsp;aggressive&nbsp;to&nbsp;avoid&nbsp;that&nbsp;too&nbsp;much&nbsp;memory&nbsp;is&nbsp;used&nbsp;by<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;keys&nbsp;that&nbsp;can&nbsp;be&nbsp;removed&nbsp;from&nbsp;the&nbsp;keyspace.&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;activeExpireCycle(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;j;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(j&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;j&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;server.dbnum;&nbsp;j</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;expired;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redisDb&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">db&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;server.db</span><span style="color: #000000; ">+</span><span style="color: #000000; ">j;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Continue&nbsp;to&nbsp;expire&nbsp;if&nbsp;at&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;cycle&nbsp;more&nbsp;than&nbsp;25%<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;of&nbsp;the&nbsp;keys&nbsp;were&nbsp;expired.&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">do</span><span style="color: #000000; ">&nbsp;{<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;num&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;dictSize(db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">expires);<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;now&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;time(NULL);<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expired&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(num&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;REDIS_EXPIRELOOKUPS_PER_CRON)<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;REDIS_EXPIRELOOKUPS_PER_CRON;<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(num</span><span style="color: #000000; ">--</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dictEntry&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">de;<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;t;<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;((de&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;dictGetRandomKey(db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">expires))&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(time_t)&nbsp;dictGetEntryVal(de);<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(now&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t)&nbsp;{<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sds&nbsp;key&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;dictGetEntryKey(de);<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;robj&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">keyobj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;createStringObject(key,sdslen(key));<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;propagateExpire(db,keyobj);<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dbDelete(db,keyobj);<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decrRefCount(keyobj);<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expired</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server.stat_expiredkeys</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(expired&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;REDIS_EXPIRELOOKUPS_PER_CRON</span><span style="color: #000000; ">/</span><span style="color: #000000; ">4</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">41</span>&nbsp;</div>  <p><span style="font-family: 宋体; font-size: 12pt; ">这个函数的意图已经有说明：</span><span style="font-family: 宋体; font-size: 12pt; ">删一点点过期</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">，如果过期</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">较少，那也只用一点点</span><span style="font-size: 12pt; ">cpu</span><span style="font-family: 宋体; font-size: 12pt; ">。</span><span style="font-size: 12pt; ">25</span><span style="font-family: 宋体; font-size: 12pt; ">行随机取一个</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">，</span><span style="font-size: 12pt; ">38</span><span style="font-family: 宋体; font-size: 12pt; ">行删</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">成功的概率较低就退出。这个函数被放在一个</span><span style="font-size: 12pt; ">cron</span><span style="font-family: 宋体; font-size: 12pt; ">里，每毫秒被调用一次。这个算法保证每次会删除一定比例的</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">，但是如果</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">总量很大，而这个比例控制的太大，就需要更多次的循环，浪费</span><span style="font-size: 12pt; ">cpu</span><span style="font-family: 宋体; font-size: 12pt; ">，控制的太小，过期的</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">就会变多，浪费内存&#8212;&#8212;这就是时空权衡了。</span></p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; color: black; font-size: 12pt; ">最后在</span><span style="color: black; font-size: 12pt; ">dbDelete</span><span style="font-family: 宋体; color: black; font-size: 12pt; ">的调用者里还发现这样一个函数：</span></p>  <p style="text-autospace:none"><font class="Apple-style-span" color="#008000" size="4"><span class="Apple-style-span" style="font-size: 16px;"></span></font></p><font class="Apple-style-span" color="#008000" size="4"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;This&nbsp;function&nbsp;gets&nbsp;called&nbsp;when&nbsp;'maxmemory'&nbsp;is&nbsp;set&nbsp;on&nbsp;the&nbsp;config&nbsp;file&nbsp;to&nbsp;limit<br />&nbsp;*&nbsp;the&nbsp;max&nbsp;memory&nbsp;used&nbsp;by&nbsp;the&nbsp;server,&nbsp;and&nbsp;we&nbsp;are&nbsp;out&nbsp;of&nbsp;memory.<br />&nbsp;*&nbsp;This&nbsp;function&nbsp;will&nbsp;try&nbsp;to,&nbsp;in&nbsp;order:<br />&nbsp;*<br />&nbsp;*&nbsp;-&nbsp;Free&nbsp;objects&nbsp;from&nbsp;the&nbsp;free&nbsp;list<br />&nbsp;*&nbsp;-&nbsp;Try&nbsp;to&nbsp;remove&nbsp;keys&nbsp;with&nbsp;an&nbsp;EXPIRE&nbsp;set<br />&nbsp;*<br />&nbsp;*&nbsp;It&nbsp;is&nbsp;not&nbsp;possible&nbsp;to&nbsp;free&nbsp;enough&nbsp;memory&nbsp;to&nbsp;reach&nbsp;used-memory&nbsp;&lt;&nbsp;maxmemory<br />&nbsp;*&nbsp;the&nbsp;server&nbsp;will&nbsp;start&nbsp;refusing&nbsp;commands&nbsp;that&nbsp;will&nbsp;enlarge&nbsp;even&nbsp;more&nbsp;the<br />&nbsp;*&nbsp;memory&nbsp;usage.<br />&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;freeMemoryIfNeeded(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)</span></div></font>  <p><span style="font-family: 宋体; font-size: 12pt; ">这个函数太长就不再详述了，注释部分说明只有在配置文件中设置了最大内存时候才会调用这个函数，而设置这个参数的意义是，你把</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">当做一个内存</span><span style="font-size: 12pt; ">cache</span><span style="font-family: 宋体; font-size: 12pt; ">而不是</span><span style="font-size: 12pt; ">key-value</span><span style="font-family: 宋体; font-size: 12pt; ">数据库。</span></p>  <p><br /></p>  <p><span style="font-family: 宋体; font-size: 12pt; ">以上</span><span style="font-size: 12pt; ">3</span><span style="font-family: 宋体; font-size: 12pt; ">种删除过期</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">的途径，第二种定期删除一定比例的</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">是主要的删除途径，第一种&#8220;读时删除&#8221;保证过期</span><span style="font-size: 12pt; ">key</span><span style="font-family: 宋体; font-size: 12pt; ">不会被访问到，第三种是一个当内存超出设定时的暴力手段。由此也能看出</span><span style="font-size: 12pt; ">redis</span><span style="font-family: 宋体; font-size: 12pt; ">设计的巧妙之处，</span></p></div><img src ="http://www.cppblog.com/richbirdandy/aggbug/161184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richbirdandy/" target="_blank">阿二</a> 2011-11-29 19:57 <a href="http://www.cppblog.com/richbirdandy/archive/2011/11/29/161184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>