{"id":201609,"date":"2025-05-10T12:01:36","date_gmt":"2025-05-10T04:01:36","guid":{"rendered":"https:\/\/server.hk\/cnblog\/201609\/"},"modified":"2025-05-10T12:01:36","modified_gmt":"2025-05-10T04:01:36","slug":"%e4%b8%80%e7%af%87%e6%96%87%e7%ab%a0%e5%b8%a6%e4%bd%a0%e5%bc%84%e6%b8%85%e6%a5%9aredis%e7%9a%84%e7%b2%be%e9%ab%93","status":"publish","type":"post","link":"https:\/\/server.hk\/cnblog\/201609\/","title":{"rendered":"\u4e00\u7bc7\u6587\u7ae0\u5e26\u4f60\u5f04\u6e05\u695aRedis\u7684\u7cbe\u9ad3"},"content":{"rendered":"<p><b><\/b> <\/p>\n<h1>\u4e00\u7bc7\u6587\u7ae0\u5e26\u4f60\u5f04\u6e05\u695aRedis\u7684\u7cbe\u9ad3<\/h1>\n<p><span style=\"cursor: pointer\"><i><\/i>\u6536\u85cf<\/span> <\/p>\n<p>\u4eca\u65e5\u4e0d\u80af\u57cb\u5934\uff0c\u660e\u65e5\u4f55\u4ee5\u62ac\u5934\uff01\u6bcf\u65e5\u4e00\u53e5\u52aa\u529b\u81ea\u5df1\u7684\u8bdd\u54c8\u54c8~\u54c8\u55bd\uff0c\u4eca\u5929\u6211\u5c06\u7ed9\u5927\u5bb6\u5e26\u6765\u4e00\u7bc7<span style=\"color: #FF6600;font-family:\">\u300a\u4e00\u7bc7\u6587\u7ae0\u5e26\u4f60\u5f04\u6e05\u695aRedis\u7684\u7cbe\u9ad3\u300b<\/span>\uff0c\u4e3b\u8981\u5185\u5bb9\u662f\u8bb2\u89e3<span style=\"color: #FF6600;font-family:\">Redis<\/span>\u7b49\u7b49\uff0c\u611f\u5174\u8da3\u7684\u670b\u53cb\u53ef\u4ee5\u6536\u85cf\u6216\u8005\u6709\u66f4\u597d\u7684\u5efa\u8bae\u5728\u8bc4\u8bba\u63d0\u51fa\uff0c\u6211\u90fd\u4f1a\u8ba4\u771f\u770b\u7684\uff01\u5927\u5bb6\u4e00\u8d77\u8fdb\u6b65\uff0c\u4e00\u8d77\u5b66\u4e60\uff01<\/p>\n<h2>\u4e00\u3001Redis\u7684\u7279\u6027<\/h2>\n<h3>1.1 Redis\u4e3a\u4ec0\u4e48\u5feb\uff1f<\/h3>\n<ul>\n<li>\u57fa\u4e8e\u5185\u5b58\u64cd\u4f5c\uff0c\u64cd\u4f5c\u4e0d\u9700\u8981\u8ddf\u78c1\u76d8\u4ea4\u4e92\uff0c\u5355\u6b21\u6267\u884c\u5f88\u5feb<\/li>\n<li>\u547d\u4ee4\u6267\u884c\u662f\u5355\u7ebf\u7a0b\uff0c\u56e0\u4e3a\u662f\u57fa\u4e8e\u5185\u5b58\u64cd\u4f5c\uff0c\u5355\u6b21\u6267\u884c\u7684\u65f6\u95f4\u5feb\u4e8e\u7ebf\u7a0b\u5207\u6362\u65f6\u95f4\uff0c\u540c\u65f6\u901a\u4fe1\u91c7\u7528\u591a\u8def\u590d\u7528<\/li>\n<li>Redis\u672c\u8eab\u5c31\u662f\u4e00\u4e2ak-v\u7ed3\u6784\uff0c\u7c7b\u4f3c\u4e8ehashMap\uff0c\u6240\u4ee5\u67e5\u8be2\u6027\u80fd\u63a5\u8fd1\u4e8eO(1)<\/li>\n<li>\u540c\u65f6redis\u81ea\u5df1\u5e95\u5c42\u6570\u636e\u7ed3\u6784\u652f\u6301\uff0c\u6bd4\u5982\u8df3\u8868\u3001SDS<\/li>\n<li>lO\u591a\u8def\u590d\u7528\uff0c\u5355\u4e2a\u7ebf\u7a0b\u4e2d\u901a\u8fc7\u8bb0\u5f55\u8ddf\u8e2a\u6bcf\u4e00\u4e2asock\uff08I\/O\u6d41\uff09\u7684\u72b6\u6001\u6765\u7ba1\u7406\u591a\u4e2aI\/O\u6d41<\/li>\n<\/ul>\n<h3>1.2 Redis\u5176\u4ed6\u7279\u6027<\/h3>\n<ul>\n<li>\u66f4\u4e30\u5bcc\u7684\u6570\u636e\u7c7b\u578b\uff0c\u867d\u7136\u90fd\u662fk\u3001v\u7ed3\u6784\uff0cvalue\u53ef\u4ee5\u5b58\u50a8\u5f88\u591a\u7684\u6570\u636e\u7c7b\u578b<\/li>\n<li>\u5b8c\u5584\u7684\u5185\u5b58\u7ba1\u7406\u673a\u5236\u3001\u4fdd\u8bc1\u6570\u636e\u4e00\u81f4\u6027\uff1a\u6301\u4e45\u5316\u673a\u5236\u3001\u8fc7\u671f\u7b56\u7565<\/li>\n<li>\u652f\u6301\u591a\u79cd\u7f16\u7a0b\u8bed\u8a00<\/li>\n<li>\u9ad8\u53ef\u7528\uff0c\u96c6\u7fa4\u3001\u4fdd\u8bc1\u9ad8\u53ef\u7528<\/li>\n<\/ul>\n<h3>1.3 Redis\u9ad8\u53ef\u7528<\/h3>\n<ul>\n<li>\u5f88\u5b8c\u5584\u7684\u5185\u5b58\u7ba1\u7406\u673a\u5236\uff0c\u8fc7\u671f\u3001\u6dd8\u6c70\u3001\u6301\u4e45\u5316<\/li>\n<li>\u96c6\u7fa4\u6a21\u5f0f\uff0c\u4e3b\u4ece\u3001\u54e8\u5175\u3001cluster\u96c6\u7fa4<\/li>\n<\/ul>\n<h2>\u4e8c\u3001Redis\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u4f7f\u7528\u573a\u666f<\/h2>\n<p>Redis\u7684\u6570\u636e\u7c7b\u578b\u6709String\u3001Hash\u3001Set\u3001List\u3001Zset\u3001bitMap\uff08\u57fa\u4e8eString\u7c7b\u578b\uff09\u3001 Hyperloglog\uff08\u57fa\u4e8eString\u7c7b\u578b\uff09\u3001Geo\uff08\u5730\u7406\u4f4d\u7f6e\uff09\u3001Streams\u6d41\u3002<\/p>\n<h3>2.1 String<\/h3>\n<h4>2.1.1 \u57fa\u672c\u6307\u4ee4<\/h4>\n<pre>\/\/ \u6279\u91cf\u8bbe\u7f6e\n&gt; mset key1 value1 key2 value2\n\/\/ \u6279\u91cf\u83b7\u53d6\n&gt; mget key1 key2\n\/\/ \u83b7\u53d6\u957f\u5ea6\n&gt; strlen key  \n\/\/  \u5b57\u7b26\u4e32\u8ffd\u52a0\u5185\u5bb9\n&gt; append key xxx\n\/\/ \u83b7\u53d6\u6307\u5b9a\u533a\u95f4\u7684\u5b57\u7b26\n&gt; getrange key 0 5\n\/\/ \u6574\u6570\u503c\u9012\u589e (\u9012\u589e\u6307\u5b9a\u7684\u503c)\n&gt; incr intkey (incrby intkey 10)\n\/\/ \u5f53key \u5b58\u5728\u65f6\u5c06\u8986\u76d6\n&gt; SETEX key seconds value\n\/\/ \u5c06 key \u7684\u503c\u8bbe\u4e3a value \uff0c\u5f53\u4e14\u4ec5\u5f53 key \u4e0d\u5b58\u5728\u3002\n&gt; SETNX key value<\/pre>\n<h4>2.1.2 \u5e94\u7528\u573a\u666f<\/h4>\n<ol>\n<li>\u7f13\u5b58\u76f8\u5173\u573a\u666f \u7f13\u5b58\u3001 token\uff08\u8ddf\u8fc7\u671f\u5c5e\u6027\u5b8c\u7f8e\u5951\u5408\uff09<\/li>\n<li>\u7ebf\u7a0b\u5b89\u5168\u7684\u8ba1\u6570\u573a\u666f \uff08\u8f6f\u9650\u6d41\u3001\u5206\u5e03\u5f0fID\u7b49\uff09<\/li>\n<\/ol>\n<h3>2.2 Hash<\/h3>\n<h4>2.2.1 \u57fa\u672c\u6307\u4ee4<\/h4>\n<pre>\/\/ \u5c06\u54c8\u5e0c\u8868 key \u4e2d\u7684\u57df field \u7684\u503c\u8bbe\u4e3a value \u3002\n&gt; HSET key field value\n\/\/ \u8fd4\u56de\u54c8\u5e0c\u8868 key \u4e2d\u7ed9\u5b9a\u57df field \u7684\u503c\u3002\n&gt;  HGET key field\n\/\/ \u8fd4\u56de\u54c8\u5e0c\u8868 key \u4e2d\u7684\u6240\u6709\u57df\u3002\n&gt; HKEYS key\n\/\/ \u8fd4\u56de\u54c8\u5e0c\u8868 key \u4e2d\u6240\u6709\u57df\u7684\u503c\u3002\n&gt;  HVALS key\n\/\/ \u4e3a\u54c8\u5e0c\u8868 key \u4e2d\u7684\u57df field \u7684\u503c\u52a0\u4e0a\u589e\u91cf increment \u3002\n&gt; HINCRBY key field increment\n\/\/ \u67e5\u770b\u54c8\u5e0c\u8868 key \u4e2d\uff0c\u7ed9\u5b9a\u57df field \u662f\u5426\u5b58\u5728\u3002\n&gt; HEXISTS key field<\/pre>\n<h4>2.2.2 \u5e94\u7528\u573a\u666f<\/h4>\n<ol>\n<li>\u5b58\u50a8\u5bf9\u8c61\u7c7b\u7684\u6570\u636e(\u5b98\u7f51\u8bf4\u7684\uff09\u6bd4\u5982\u4e00\u4e2a\u5bf9\u8c61\u4e0b\u6709\u591a\u4e2a\u5b57\u6bb5<\/li>\n<li>\u7edf\u8ba1\u7c7b\u7684\u6570\u636e\uff0c\u53ef\u4ee5\u5bf9\u5355\u4e2a\u7edf\u8ba1\u6570\u636e\u8fdb\u884c\u5355\u72ec\u64cd\u4f5c<\/li>\n<\/ol>\n<h3>2.3 List<\/h3>\n<p>\u5b58\u50a8\u6709\u5e8f\u7684\u5b57\u7b26\u4e32\u5217\u8868\uff0c\u5143\u7d20\u53ef\u4ee5\u91cd\u590d\u3002\u5217\u8868\u7684\u6700\u5927\u957f\u5ea6\u4e3a 2^32 &#8211; 1 \u4e2a\u5143\u7d20\uff084294967295\uff0c\u6bcf\u4e2a\u5217\u8868\u8d85\u8fc7 40 \u4ebf\u4e2a\u5143\u7d20\uff09\u3002<\/p>\n<h4>2.3.1 \u57fa\u672c\u6307\u4ee4<\/h4>\n<pre>\/\/ \u5c06\u4e00\u4e2a\u6216\u591a\u4e2a\u503c value \u63d2\u5165\u5230\u5217\u8868 key \u7684\u8868\u5934\n&gt; LPUSH key value [value ...]\n\/\/ \u5c06\u4e00\u4e2a\u6216\u591a\u4e2a\u503c value \u63d2\u5165\u5230\u5217\u8868 key \u7684\u8868\u5c3e(\u6700\u53f3\u8fb9)\u3002\n&gt; RPUSH key value [value ...]\n\/\/ \u79fb\u9664\u5e76\u8fd4\u56de\u5217\u8868 key \u7684\u5934\u5143\u7d20\u3002\n&gt; LPOP key\n\/\/ \u79fb\u9664\u5e76\u8fd4\u56de\u5217\u8868 key \u7684\u5c3e\u5143\u7d20\u3002\n&gt; RPOP key\n\/\/ BLPOP \u662f\u5217\u8868\u7684\u963b\u585e\u5f0f(blocking)\u5f39\u51fa\u539f\u8bed\u3002\n&gt; BLPOP key [key ...] timeout\n\/\/ BRPOP \u662f\u5217\u8868\u7684\u963b\u585e\u5f0f(blocking)\u5f39\u51fa\u539f\u8bed\u3002\n&gt; BRPOP key [key ...] timeout\n\/\/ \u83b7\u53d6\u6307\u70b9\u4f4d\u7f6e\u5143\u7d20\n&gt; LINDEX key index<\/pre>\n<h4>2.3.2 \u5e94\u7528\u573a\u666f<\/h4>\n<ol>\n<li>\u7528\u6237\u6d88\u606f\u65f6\u95f4\u7ebf<\/li>\n<\/ol>\n<p>\u56e0\u4e3alist\u662f\u6709\u5e8f\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u5148\u8fdb\u5148\u51fa\uff0c\u5148\u8fdb\u540e\u51fa\u7684\u5217\u8868\u90fd\u53ef\u4ee5\u505a<\/p>\n<h3>2.4 Set<\/h3>\n<h4>2.4.1 \u57fa\u672c\u6307\u4ee4<\/h4>\n<pre>\/\/ \u5c06\u4e00\u4e2a\u6216\u591a\u4e2a member \u5143\u7d20\u52a0\u5165\u5230\u96c6\u5408 key \u5f53\u4e2d\uff0c\u5df2\u7ecf\u5b58\u5728\u4e8e\u96c6\u5408\u7684 member \u5143\u7d20\u5c06\u88ab\u5ffd\u7565\u3002\n&gt; SADD key member [member ...]\n\/\/ \u8fd4\u56de\u96c6\u5408 key \u4e2d\u7684\u6240\u6709\u6210\u5458\u3002\n&gt; SMEMBERS key\n\/\/ \u8fd4\u56de\u96c6\u5408 key \u7684\u57fa\u6570(\u96c6\u5408\u4e2d\u5143\u7d20\u7684\u6570\u91cf)\u3002\n&gt; SCARD key\n\/\/ \u5982\u679c\u547d\u4ee4\u6267\u884c\u65f6\uff0c\u53ea\u63d0\u4f9b\u4e86 key \u53c2\u6570\uff0c\u90a3\u4e48\u8fd4\u56de\u96c6\u5408\u4e2d\u7684\u4e00\u4e2a\u968f\u673a\u5143\u7d20\u3002\n&gt; SRANDMEMBER key [count]\n\/\/ \u79fb\u9664\u5e76\u8fd4\u56de\u96c6\u5408\u4e2d\u7684\u4e00\u4e2a\u968f\u673a\u5143\u7d20\u3002\n&gt; SPOP key\n\/\/ \u79fb\u9664\u96c6\u5408 key \u4e2d\u7684\u4e00\u4e2a\u6216\u591a\u4e2a member \u5143\u7d20\uff0c\u4e0d\u5b58\u5728\u7684 member \u5143\u7d20\u4f1a\u88ab\u5ffd\u7565\u3002\n&gt; SREM key member [member ...]\n\/\/ \u5224\u65ad member \u5143\u7d20\u662f\u5426\u96c6\u5408 key \u7684\u6210\u5458\u3002\n&gt; SISMEMBER key member\n\/\/ \u83b7\u53d6\u524d\u4e00\u4e2a\u96c6\u5408\u6709\u800c\u540e\u97621\u4e2a\u96c6\u5408\u6ca1\u6709\u7684\n&gt; sdiff huihuiset huihuiset1\n\/\/ \u83b7\u53d6\u4ea4\u96c6\n&gt; sinter huihuiset huihuiset1\n\/\/ \u83b7\u53d6\u5e76\u96c6\n&gt; sunion huihuiset huihuiset1<\/pre>\n<h4>2.4.2 \u5e94\u7528\u573a\u666f<\/h4>\n<ol>\n<li>\u62bd\u5956 spop\u8ddfsrandmember\u968f\u673a\u5f39\u51fa\u6216\u8005\u83b7\u53d6\u5143\u7d20<\/li>\n<li>\u70b9\u8d5e\u3001\u7b7e\u5230\u7b49\uff0csadd\u96c6\u5408\u5b58\u50a8<\/li>\n<li>\u4ea4\u96c6\u5e76\u96c6 \u5173\u6ce8\u7b49\u573a\u666f<\/li>\n<\/ol>\n<h3>2.5 ZSet(SortedSet)<\/h3>\n<p>sorted set\uff0c\u6709\u5e8f\u7684set\uff0c\u6bcf\u4e2a\u5143\u7d20\u6709\u4e2ascore\u3002<\/p>\n<p>score\u76f8\u540c\u65f6\uff0c\u6309\u7167key\u7684ASCII\u7801\u6392\u5e8f\u3002<\/p>\n<h4>2.5.1 \u57fa\u672c\u6307\u4ee4<\/h4>\n<pre>\/\/\u5c06\u4e00\u4e2a\u6216\u591a\u4e2a member \u5143\u7d20\u53ca\u5176 score \u503c\u52a0\u5165\u5230\u6709\u5e8f\u96c6 key \u5f53\u4e2d\u3002\n&gt; ZADD key score member [[score member] [score member] ...]\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u4e2d\uff0c\u6307\u5b9a\u533a\u95f4\u5185\u7684\u6210\u5458\u3002\u5176\u4e2d\u6210\u5458\u7684\u4f4d\u7f6e\u6309 score \u503c\u9012\u589e(\u4ece\u5c0f\u5230\u5927)\u6765\u6392\u5e8f\n&gt; ZRANGE key start stop [WITHSCORES]\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u4e2d\uff0c\u6307\u5b9a\u533a\u95f4\u5185\u7684\u6210\u5458\u3002\u5176\u4e2d\u6210\u5458\u7684\u4f4d\u7f6e\u6309 score \u503c\u9012\u51cf(\u4ece\u5927\u5230\u5c0f)\u6765\u6392\u5217\u3002\n&gt; ZREVRANGE key start stop [WITHSCORES]\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u4e2d\uff0c\u6240\u6709 score \u503c\u4ecb\u4e8e min \u548c max \u4e4b\u95f4(\u5305\u62ec\u7b49\u4e8e min \u6216 max )\u7684\u6210\u5458\u3002\u6709\u5e8f\u96c6\u6210\u5458\u6309 score \u503c\u9012\u589e(\u4ece\u5c0f\u5230\u5927)\u6b21\u5e8f\u6392\u5217\u3002\n&gt;  ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]\n\/\/ \u79fb\u9664\u6709\u5e8f\u96c6 key \u4e2d\u7684\u4e00\u4e2a\u6216\u591a\u4e2a\u6210\u5458\uff0c\u4e0d\u5b58\u5728\u7684\u6210\u5458\u5c06\u88ab\u5ffd\u7565\u3002\n&gt; ZREM key member [member ...]\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u7684\u57fa\u6570\u3002\n&gt; ZCARD key\n\/\/ \u4e3a\u6709\u5e8f\u96c6 key \u7684\u6210\u5458 member \u7684 score \u503c\u52a0\u4e0a\u589e\u91cf increment \u3002\n&gt; ZINCRBY key increment member\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u4e2d\uff0c score \u503c\u5728 min \u548c max \u4e4b\u95f4(\u9ed8\u8ba4\u5305\u62ec score \u503c\u7b49\u4e8e min \u6216 max )\u7684\u6210\u5458\u7684\u6570\u91cf\u3002\n&gt; ZCOUNT key min max\n\/\/ \u8fd4\u56de\u6709\u5e8f\u96c6 key \u4e2d\u6210\u5458 member \u7684\u6392\u540d\u3002\u5176\u4e2d\u6709\u5e8f\u96c6\u6210\u5458\u6309 score \u503c\u9012\u589e(\u4ece\u5c0f\u5230\u5927)\u987a\u5e8f\u6392\u5217\u3002\n&gt; ZRANK key member<\/pre>\n<h4>2.5.2 \u5e94\u7528\u573a\u666f<\/h4>\n<ol>\n<li>\u6392\u884c\u699c<\/li>\n<\/ol>\n<h2>\u4e09\u3001Redis\u7684\u4e8b\u52a1<\/h2>\n<h3>3.1 \u4e8b\u52a1\u57fa\u672c\u64cd\u4f5c<\/h3>\n<pre>\/\/ 1. multi\u547d\u4ee4\u5f00\u542f\u4e8b\u52a1\uff0cexec\u547d\u4ee4\u63d0\u4ea4\u4e8b\u52a1\n127.0.0.1:6379&gt; multi\nOK\n127.0.0.1:6379(TX)&gt; set k1 v1\nQUEUED\n127.0.0.1:6379(TX)&gt; set k2 v2\nQUEUED\n127.0.0.1:6379(TX)&gt; exec\n1) OK\n2) OK\n\/\/ 2. \u7ec4\u961f\u7684\u8fc7\u7a0b\u4e2d\u53ef\u4ee5\u901a\u8fc7discard\u6765\u653e\u5f03\u7ec4\u961f\u3002\n 127.0.0.1:6379&gt; multi\nOK\n 127.0.0.1:6379(TX)&gt; set k3 v3\nQUEUED\n 127.0.0.1:6379(TX)&gt; set k4 v4\nQUEUED\n 127.0.0.1:6379(TX)&gt; discard\nOK<\/pre>\n<h3>3.2 Redis\u4e8b\u52a1\u7279\u6027<\/h3>\n<ol>\n<li>\u5355\u72ec\u7684\u9694\u79bb\u64cd\u4f5c<\/li>\n<\/ol>\n<p>\u4e8b\u52a1\u4e2d\u7684\u6240\u6709\u547d\u4ee4\u90fd\u4f1a\u5e8f\u5217\u5316\u3001\u6309\u987a\u5e8f\u5730\u6267\u884c\u3002<\/p>\n<p>\u4e8b\u52a1\u5728\u6267\u884c\u8fc7\u7a0b\u4e2d\uff0c\u4e0d\u4f1a\u88ab\u5176\u4ed6\u5ba2\u6237\u7aef\u53d1\u9001\u6765\u7684\u547d\u4ee4\u8bf7\u6c42\u6240\u6253\u65ad\u3002<\/p>\n<ol>\n<li>\u6ca1\u6709\u9694\u79bb\u7ea7\u522b\u7684\u6982\u5ff5<\/li>\n<\/ol>\n<p>\u961f\u5217\u4e2d\u7684\u547d\u4ee4\u6ca1\u6709\u63d0\u4ea4\u4e4b\u524d\uff0c\u90fd\u4e0d\u4f1a\u88ab\u5b9e\u9645\u5730\u6267\u884c\uff0c\u56e0\u4e3a\u4e8b\u52a1\u63d0\u4ea4\u4e4b\u524d\u4efb\u4f55\u6307\u4ee4\u90fd\u4e0d\u4f1a\u88ab\u5b9e\u9645\u6267\u884c\uff0c\u4e5f\u5c31\u4e0d\u5b58\u5728\u201c\u4e8b\u52a1\u5185\u7684\u67e5\u8be2\u8981\u770b\u5230\u4e8b\u52a1\u91cc\u7684\u66f4\u65b0\uff0c\u5728\u4e8b\u52a1\u5916\u67e5\u8be2\u4e0d\u80fd\u770b\u5230\u201d\u8fd9\u4e2a\u8ba9\u4eba\u4e07\u5206\u5934\u75bc\u7684\u95ee\u9898\u3002<\/p>\n<ol>\n<li>\u4e0d\u4fdd\u8bc1\u539f\u5b50\u6027<\/li>\n<\/ol>\n<p>Redis\u540c\u4e00\u4e2a\u4e8b\u52a1\u4e2d\u5982\u679c\u6709\u4e00\u6761\u547d\u4ee4\u6267\u884c\u5931\u8d25\uff0c\u5176\u540e\u7684\u547d\u4ee4\u4ecd\u7136\u4f1a\u88ab\u6267\u884c\uff0c\u6ca1\u6709\u56de\u6eda\u3002<\/p>\n<h2>\u56db\u3001Redis \u5206\u5e03\u5f0f\u9501<\/h2>\n<h3>4.1 Lua \u5b9e\u73b0\u5206\u5e03\u5f0f\u9501<\/h3>\n<pre>local lockSet = redis.call('exists', KEYS[1])\nif lockSet == 0 \n  then\n    redis.call('set', KEYS[1], ARG[1])\n    redis.call('expire', KEYS[1], ARG[2])\n  end\nreturn lockSet<\/pre>\n<h3>5.1 Redis dict\u5b57\u5178<\/h3>\n<h4>5.1.1 RedisDb\u6570\u636e\u63a5\u53e3\uff08server.h\u6587\u4ef6\uff09<\/h4>\n<p>\u6570\u636e\u6700\u5916\u5c42\u7684\u7ed3\u6784\u4e3aRedisDb<\/p>\n<pre>typedef struct redisDb {\n    dict *dict; \/* The keyspace for this DB *\/ \/\/\u6570\u636e\u5e93\u7684\u952e\n    dict *expires; \/* Timeout of keys with a timeout set *\/ \/\/\u8bbe\u7f6e\u4e86\u8d85\u65f6\u65f6\u95f4\u7684\u952e\n    dict *blocking_keys; \/* Keys with clients waiting for data (BLPOP)*\/ \/\/\u5ba2\u6237\u7aef\u7b49\u5f85\u7684keys\n    dict *ready_keys; \/* Blocked keys that received a PUSH *\/\n    dict *watched_keys; \/* WATCHED keys for MULTI\/EXEC CAS *\/\n    int id; \/* Database ID *\/ \/\/\u6240\u5728\u6570 \u636e\u5e93ID\n    long long avg_ttl; \/* Average TTL, just for tats *\/ \/\/\u5e73\u5747TTL\uff0c\u4ec5\u7528\u4e8e\u7edf\u8ba1\n    unsigned long expires_cursor; \/* Cursor of the active expire cycle. *\/\n    list *defrag_later; \/* List of key names to attempt to defrag one by one, gradually. *\/\n} redisDb;<\/pre>\n<h4>5.1.2 dict\u6570\u636e\u7ed3\u6784\uff08dict.h\u6587\u4ef6\uff09<\/h4>\n<p>\u6211\u4eec\u53d1\u73b0\u6570\u636e\u5b58\u50a8\u5728dict\u4e2d<\/p>\n<pre>typedef struct dict {\n    dictType *type; \/\/\u7406\u89e3\u4e3a\u9762\u5411\u5bf9\u8c61\u601d\u60f3\uff0c\u4e3a\u652f\u6301\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\u5bf9\u5e94dictType\u62bd\u8c61\u65b9\u6cd5\uff0c\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\u53ef\u4ee5\u4e0d\u540c\u5b9e\u73b0\n    void *privdata; \/\/\u4e5f\u53ef\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\u76f8\u5173\uff0c\u4e0d\u540c\u7c7b\u578b\u7279\u5b9a\u51fd\u6570\u7684\u53ef\u9009\u53c2\u6570\u3002\n    dictht ht[2]; \/\/2\u4e2ahash\u8868\uff0c\u7528\u6765\u6570\u636e\u5b58\u50a8 2\u4e2adictht\n    long rehashidx; \/* rehashing not in progress if rehashidx == -1 *\/ \/\/ rehash\u6807\u8bb0 -1\u4ee3\u8868\u4e0d\u518drehash\n    unsigned long iterators; \/* number of iterators currently running *\/\n} dict;<\/pre>\n<h4>5.1.3 dictht\u7ed3\u6784\uff08dict.h\u6587\u4ef6\uff09<\/h4>\n<pre>typedef struct dictht {\n    dictEntry **table; \/\/dictEntry \u6570\u7ec4\n    unsigned long size; \/\/\u6570\u7ec4\u5927\u5c0f \u9ed8\u8ba4\u4e3a4 #define DICT_HT_INITIAL_SIZE 4\n    unsigned long sizemask; \/\/size-1 \u7528\u6765\u53d6\u6a21\u5f97\u5230\u6570\u636e\u7684\u4e0b\u6807\u503c\n    unsigned long used; \/\/\u6539hash\u8868\u4e2d\u5df2\u6709\u7684\u8282\u70b9\u6570\u636e\n} dictht;<\/pre>\n<h4>5.1.4 dictEntry\u8282\u70b9\u7ed3\u6784\uff08dict.h\u6587\u4ef6\uff09<\/h4>\n<pre>typedef struct dictEntry {\n    void *key; \/\/key\n    union {\n        void *val;\n        uint64_t u64;\n        int64_t s64;\n        double d;\n    } v; \/\/value\n    struct dictEntry *next; \/\/\u6307\u5411\u4e0b\u4e00\u4e2a\u8282\u70b9\n} dictEntry;<\/pre>\n<\/p>\n<pre>\/* Objects encoding. Some kind of objects like Strings and\nHashes can be\n* internally represented in multiple ways. The 'encoding'\nfield of the object\n* is set to one of this fields for this object. *\/\n#define OBJ_ENCODING_RAW 0 \/* Raw representation *\/\n#define OBJ_ENCODING_INT 1 \/* Encoded as integer *\/\n#define OBJ_ENCODING_HT 2 \/* Encoded as hash table *\/\n#define OBJ_ENCODING_ZIPMAP 3 \/* Encoded as zipmap *\/\n#define OBJ_ENCODING_LINKEDLIST 4 \/* No longer used: old\nlist encoding. *\/\n#define OBJ_ENCODING_ZIPLIST 5 \/* Encoded as ziplist *\/\n#define OBJ_ENCODING_INTSET 6 \/* Encoded as intset *\/\n#define OBJ_ENCODING_SKIPLIST 7 \/* Encoded as skiplist *\/\n#define OBJ_ENCODING_EMBSTR 8 \/* Embedded sds string\nencoding *\/\n#define OBJ_ENCODING_QUICKLIST 9 \/* Encoded as linked list\nof ziplists *\/\n#define OBJ_ENCODING_STREAM 10 \/* Encoded as a radix tree\nof listpacks *\/\n#define LRU_BITS 24\n#define LRU_CLOCK_MAX ((1lru *\/\n#define LRU_CLOCK_RESOLUTION 1000 \/* LRU clock resolution\nin ms *\/\n#define OBJ_SHARED_REFCOUNT INT_MAX \/* Global object\nnever destroyed. *\/\n#define OBJ_STATIC_REFCOUNT (INT_MAX-1) \/* Object\nallocated in the stack. *\/\n#define OBJ_FIRST_SPECIAL_REFCOUNT OBJ_STATIC_REFCOUNT\ntypedef struct redisObject {\nunsigned type:4; \/\/\u6570\u636e\u7c7b\u578b string hash list\nunsigned encoding:4; \/\/\u5e95\u5c42\u7684\u6570\u636e\u7ed3\u6784 \u8df3\u8868\nunsigned lru:LRU_BITS; \/* LRU time (relative to global\nlru_clock) or\n* LFU data (least significant\n8 bits frequency\n* and most significant 16 bits\naccess time). *\/\nint refcount; \/\/\u7528\u4e8e\u56de\u6536\uff0c\u5f15\u7528\u8ba1\u6570\u6cd5\nvoid *ptr; \/\/\u6307\u5411\u5177\u4f53\u7684\u6570\u636e\u7ed3\u6784\u7684\u5185\u5b58\u5730\u5740 \u6bd4\u5982 \u8df3\u8868\u3001\u538b\u7f29\u5217\u8868\n} robj;<\/pre>\n<h3>5.2 Redis\u6570\u636e\u7ed3\u6784\u56fe<\/h3>\n<p style=\"text-align:center\"><img decoding=\"async\" src=\"https:\/\/www.17golang.com\/uploads\/20230225\/167729041763f96bb15d610.png\" style=\"max-width:100%\" class=\"aligncenter\"><\/p>\n<h3>5.3 Redis\u6269\u5bb9\u673a\u5236<\/h3>\n<p>\u56e0\u4e3a\u6211\u4eec\u7684dictEntry\u6570\u7ec4\u9ed8\u8ba4\u5927\u5c0f\u662f4\uff0c\u5982\u679c\u4e0d\u8fdb\u884c\u6269\u5bb9\uff0c\u90a3\u4e48\u6211\u4eec\u6240\u6709\u7684\u6570\u636e\u90fd\u4f1a\u4ee5\u94fe\u8868\u7684\u5f62\u5f0f\u6dfb\u52a0\u81f3\u6570\u7ec4\u4e0b\u6807 \u968f\u7740\u6570\u636e\u91cf\u8d8a\u6765\u8d8a\u5927\uff0c\u4e4b\u524d\u53ea\u9700\u8981hash\u53d6\u6a21\u5c31\u80fd\u5f97\u5230\u4e0b\u6807\u4f4d\u7f6e\uff0c\u73b0\u5728\u5f97\u53bb\u5faa\u73af\u6211\u4e0b\u6807\u7684\u94fe\u8868\uff0c\u6240\u4ee5\u6027\u80fd\u4f1a\u8d8a\u6765\u8d8a\u6162\uff0c\u5f53\u6211\u4eec\u7684\u6570\u636e\u91cf\u8fbe\u5230\u4e00\u5b9a\u7a0b\u5ea6\u540e\uff0c\u6211\u4eec\u5c31\u5f97\u53bb\u89e6\u53d1\u6269\u5bb9\u64cd\u4f5c\u3002<\/p>\n<h4>5.3.1 \u4ec0\u4e48\u65f6\u5019\u6269\u5bb9<\/h4>\n<h5>5.3.1.1 \u6269\u5bb9\u673a\u5236<\/h5>\n<ol>\n<li>\u5f53\u6ca1\u6709fork\u5b50\u8fdb\u7a0b\u5728\u8fdb\u884cRDB\u6216AOF\u6301\u4e45\u5316\u65f6\uff0cht[0]\u7684used\u5927\u4e8esize\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9<\/li>\n<li>\u5982\u679c\u6709\u5b50\u8fdb\u7a0b\u5728\u8fdb\u884cRDB\u6216\u8005AOF\u65f6\uff0cht[0]\u7684used\u5927\u4e8e\u7b49\u4e8esize\u76845\u500d\u7684\u65f6\u5019\uff0c\u4f1a\u89e6\u53d1\u6269\u5bb9<\/li>\n<\/ol>\n<h5>5.3.1.2 \u6e90\u7801\u9a8c\u8bc1<\/h5>\n<p>\u6269\u5bb9\uff0c\u80af\u5b9a\u662f\u5728\u6dfb\u52a0\u6570\u636e\u7684\u65f6\u5019\u624d\u4f1a\u6269\u5bb9\uff0c\u6240\u4ee5\u6211\u4eec\u627e\u4e00\u4e2a\u6dfb\u52a0\u6570\u636e\u7684\u5165\u53e3\u3002<\/p>\n<ol>\n<li>\u5165\u53e3\uff0c\u6dfb\u52a0\u6216\u66ff\u6362dictReplace (dict.c\u6587\u4ef6)<\/li>\n<\/ol>\n<pre>int dictReplace(dict *d, void *key, void *val) {\n    dictEntry *entry, *existing, auxentry;\n    \/* Try to add the element. If the key\n    * does not exists dictAdd will succeed. *\/\n    entry = dictAddRaw(d,key,&amp;existing);\n    if (entry) {\n        dictSetVal(d, entry, val);\n        return 1;\n    }\n    \/* Set the new value and free the old one. Note that\n    it is important\n    * to do that in this order, as the value may just be\n    exactly the same\n    * as the previous one. In this context, think to\n    reference counting,\n    * you want to increment (set), and then decrement\n    (free), and not the\n    * reverse. *\/\n    auxentry = *existing;\n    dictSetVal(d, existing, val);\n    dictFreeVal(d, &amp;auxentry);\n    return 0;\n}<\/pre>\n<ol>\n<li>\u8fdb\u5165dictAddRaw\u65b9\u6cd5 \uff08dict.c\u6587\u4ef6\uff09<\/li>\n<\/ol>\n<pre>dictEntry *dictAddRaw(dict *d, void *key, dictEntry **existing){\n    long index;\n    dictEntry *entry;\n    dictht *ht;\n    \n    if (dictIsRehashing(d)) _dictRehashStep(d); \/\/\u5982\u679c\u6b63\u5728Rehash \u8fdb\u884c\u6e10\u8fdb\u5f0fhash \u6309\u6b65rehash\n    \n    \/* Get the index of the new element, or -1 if\n    * the element already exists. *\/\n    if ((index = _dictKeyIndex(d, key, dictHashKey(d,key),existing)) == -1)\n        return NULL;\n    \n    \/* Allocate the memory and store the new entry.\n    * Insert the element in top, with the assumption that\n    in a database\n    * system it is more likely that recently added\n    entries are accessed\n    * more frequently. *\/\n    \/\/\u5982\u679c\u5728hash \u653e\u5728ht[1] \u5426\u5219\u653e\u5728ht[0]\n    ht = dictIsRehashing(d) ? &amp;d-&gt;ht[1] : &amp;d-&gt;ht[0];\n    entry = zmalloc(sizeof(*entry));\n    \/\/\u91c7\u7528\u5934\u63d2\u6cd5\u63d2\u5165hash\u6876\n    entry-&gt;next = ht-&gt;table[index];\n    ht-&gt;table[index] = entry;\n    \/\/\u5df2\u4f7f\u7528++\n    ht-&gt;used++;\n    \n    \/* Set the hash entry fields. *\/\n    dictSetKey(d, entry, key);\n    return entry;\n}<\/pre>\n<pre>static long _dictKeyIndex(dict *d, const void *key,uint64_t hash, dictEntry **existing){\n    unsigned long idx, table;\n    dictEntry *he;\n    if (existing) *existing = NULL;\n    \n    \/* Expand the hash table if needed *\/\n    \/\/\u6269\u5bb9\u5982\u679c\u9700\u8981\n    if (_dictExpandIfNeeded(d) == DICT_ERR)\n        return -1;\n    \/\/\u6bd4\u8f83\u662f\u5426\u5b58\u5728\u8fd9\u4e2a\u503c\n    for (table = 0; table ht[table].sizemask;\n        \/* Search if this slot does not already contain\n        the given key *\/\n        he = d-&gt;ht[table].table[idx];\n        while(he) {\n            if (key==he-&gt;key || dictCompareKeys(d, key,he-&gt;key)) {\n                if (existing) *existing = he;\n                    return -1;\n                }\n            he = he-&gt;next;\n        }\n        if (!dictIsRehashing(d)) break;\n    }\n    return idx;\n}<\/pre>\n<pre>\/* Expand the hash table if needed *\/\nstatic int _dictExpandIfNeeded(dict *d){\n    \/* Incremental rehashing already in progress. Return.*\/\n    if (dictIsRehashing(d)) return DICT_OK; \/\/\u6b63\u5728rehash\uff0c\u8fd4\u56de\n    \n    \/* If the hash table is empty expand it to the initialsize. *\/\n    \/\/\u5982\u679cht[0]\u7684\u957f\u5ea6\u4e3a0\uff0c\u8bbe\u7f6e\u9ed8\u8ba4\u957f\u5ea64 dictExpand\u4e3a\u6269\u5bb9\u7684\u5173\u952e\u65b9\u6cd5\n    if (d-&gt;ht[0].size == 0) \n            return dictExpand(d,DICT_HT_INITIAL_SIZE);\n\n    \/\/\u6269\u5bb9\u6761\u4ef6 hash\u8868\u4e2d\u5df2\u4f7f\u7528\u7684\u6570\u91cf\u5927\u4e8e\u7b49\u4e8e hash\u8868\u7684\u5927\u5c0f\n    \/\/\u5e76\u4e14dict_can_resize\u4e3a1 \u6216\u8005 \u5df2\u4f7f\u7528\u7684\u5927\u5c0f\u5927\u4e8ehash\u8868\u5927\u5c0f\u7684 5\u500d\uff0c\u5927\u4e8e\u7b49\u4e8e1\u500d\u7684\u65f6\u5019\uff0c\u4e0b\u97622\u4e2a\u6ee1\u8db3\u4e00\u4e2a\u6761\u4ef6\u5373\u53ef\n    if (d-&gt;ht[0].used &gt;= d-&gt;ht[0].size &amp;&amp;\n        (dict_can_resize || d-&gt;ht[0].used\/d-&gt;ht[0].size &gt;dict_force_resize_ratio)){\n        \/\/\u6269\u5bb9\u6210\u539f\u6765\u76842\u500d\n        return dictExpand(d, d-&gt;ht[0].used*2);\n    }\n    return DICT_OK;\n}<\/pre>\n<h5>5.3.2.1 \u6269\u5bb9\u6b65\u9aa4<\/h5>\n<ol>\n<li>\u5f53\u6ee1\u8db3\u6211\u6269\u5bb9\u6761\u4ef6\uff0c\u89e6\u53d1\u6269\u5bb9\u65f6\uff0c\u5224\u65ad\u662f\u5426\u5728\u6269\u5bb9\uff0c\u5982\u679c\u5728\u6269\u5bb9\uff0c\u6216\u8005 \u6269\u5bb9\u7684\u5927\u5c0f\u8ddf\u6211\u73b0\u5728\u7684ht[0].size\u4e00\u6837\uff0c\u8fd9\u6b21\u6269\u5bb9\u4e0d\u505a<\/li>\n<li>new\u4e00\u4e2a\u65b0\u7684dictht\uff0c\u5927\u5c0f\u4e3aht[0].used * 2\uff08\u4f46\u662f\u5fc5\u987b\u5411\u4e0a2\u7684\u5e42\uff0c\u6bd4 \u59826 \uff0c\u90a3\u4e48\u5927\u5c0f\u4e3a8\uff09 \uff0c\u5e76\u4e14ht[1]=\u65b0\u521b\u5efa\u7684dictht<\/li>\n<li>\u6211\u4eec\u6709\u4e2a\u66f4\u5927\u7684table\u4e86\uff0c\u4f46\u662f\u9700\u8981\u628a\u6570\u636e\u8fc1\u79fb\u5230ht[1].table \uff0c\u6240\u4ee5\u5c06 dict\u7684rehashidx\uff08\u6570\u636e\u8fc1\u79fb\u7684\u504f\u79fb\u91cf\uff09\u8d4b\u503c\u4e3a0 \uff0c\u4ee3\u8868\u53ef\u4ee5\u8fdb\u884c\u6570\u636e\u8fc1 \u79fb\u4e86\uff0c\u4e5f\u5c31\u662f\u53ef\u4ee5rehash\u4e86<\/li>\n<li>\u7b49\u5f85\u6570\u636e\u8fc1\u79fb\u5b8c\u6210\uff0c\u6570\u636e\u4e0d\u4f1a\u9a6c\u4e0a\u8fc1\u79fb\uff0c\u800c\u662f\u91c7\u7528\u6e10\u8fdb\u5f0frehash\uff0c\u6162\u6162\u7684\u628a\u6570\u636e\u8fc1\u79fb\u5230ht[1]<\/li>\n<li>\u5f53\u6570\u636e\u8fc1\u79fb\u5b8c\u6210\uff0cht[0].table=ht[1] \uff0cht[1] .table = NULL\u3001ht[1] .size = 0\u3001ht[1] .sizemask = 0\u3001 ht[1] .used = 0<\/li>\n<li>\u628adict\u7684rehashidex=-1<\/li>\n<\/ol>\n<h5>5.3.2.2 \u6e90\u7801\u9a8c\u8bc1<\/h5>\n<ol>\n<li>dictExpand\u65b9\u6cd5\u5728_dictExpandIfNeeded \u65b9\u6cd5\u4e2d\u8c03\u7528 (dict.c\u6587\u4ef6)\uff0c\u4e3a\u6269\u5bb9\u7684\u5173\u952e\u65b9\u6cd5<\/li>\n<\/ol>\n<pre>int dictExpand(dict *d, unsigned long size){\n    \/* the size is invalid if it is smaller than the\n    number of\n    * elements already inside the hash table *\/\n    \/\/\u6b63\u5728\u6269\u5bb9\uff0c\u4e0d\u5141\u8bb8\u7b2c\u4e8c\u6b21\u6269\u5bb9\uff0c\u6216\u8005ht[0]\u7684\u6570\u636e\u91cf\u5927\u4e8e\u6269\u5bb9\u540e\u7684\u6570\u91cf\uff0c\u6ca1\u6709\u610f\u4e49\uff0c\u8fd9\u6b21\u4e0d\u6269\u5bb9\n    if (dictIsRehashing(d) || d-&gt;ht[0].used &gt; size)\n        return DICT_ERR;\n    \n    dictht n; \/* the new hash table *\/\n    \/\/\u5f97\u5230\u6700\u63a5\u8fd12\u7684\u5e42 \u8ddfhashMap\u601d\u60f3\u4e00\u6837\n    unsigned long realsize = _dictNextPower(size);\n    \n    \/* Rehashing to the same table size is not useful. *\/\n    \/\/\u5982\u679c\u8ddfht[0]\u7684\u5927\u5c0f\u4e00\u81f4 \u76f4\u63a5\u8fd4\u56de\u9519\u8bef\n    if (realsize == d-&gt;ht[0].size) return DICT_ERR;\n    \n    \/* Allocate the new hash table and initialize all\n    pointers to NULL *\/\n    \/\/\u4e3a\u65b0\u7684dictht\u8d4b\u503c\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = zcalloc(realsize*sizeof(dictEntry*));\n    n.used = 0;\n    \n    \/* Is this the first initialization? If so it's not\n    really a rehashing\n    * we just set the first hash table so that it can\n    accept keys. *\/\n    \/\/ht[0].table\u4e3a\u7a7a\uff0c\u4ee3\u8868\u662f\u521d\u59cb\u5316\n    if (d-&gt;ht[0].table == NULL) {\n        d-&gt;ht[0] = n;\n        return DICT_OK;\n    }\n    \n    \/* Prepare a second hash table for incremental rehashing *\/\n    \/\/\u5c06\u6269\u5bb9\u540e\u7684dictht\u8d4b\u503c\u7ed9ht[1]\n    d-&gt;ht[1] = n;\n    \/\/\u6807\u8bb0\u4e3a0\uff0c\u4ee3\u8868\u53ef\u4ee5\u5f00\u59cbrehash\n    d-&gt;rehashidx = 0;\n    return DICT_OK;\n}<\/pre>\n<h5>5.3.3.1 \u8fc1\u79fb\u65b9\u5f0f<\/h5>\n<p>\u5047\u5982\u4e00\u6b21\u6027\u628a\u6570\u636e\u5168\u90e8\u8fc1\u79fb\u4f1a\u5f88\u8017\u65f6\u95f4\uff0c\u4f1a\u8ba9\u5355\u6761\u6307\u4ee4\u7b49\u5f85\u5f88\u4e45\uff0c\u4f1a\u5f62\u6210\u963b\u585e\u3002<\/p>\n<p>\u6240\u4ee5\uff0credis\u91c7\u7528\u6e10\u8fdb\u5f0fRehash\uff0c\u6240\u8c13\u6e10\u8fdb\u5f0f\uff0c\u5c31\u662f\u6162\u6162\u7684\uff0c\u4e0d\u4f1a\u4e00\u6b21\u6027\u628a\u6240\u6709\u6570\u636e\u8fc1\u79fb\u3002<\/p>\n<p>\u90a3\u4ec0\u4e48\u65f6\u5019\u4f1a\u8fdb\u884c\u6e10\u8fdb\u5f0f\u6570\u636e\u8fc1\u79fb\uff1f<\/p>\n<ol>\n<li>\u6bcf\u6b21\u8fdb\u884ckey\u7684crud\u64cd\u4f5c\u90fd\u4f1a\u8fdb\u884c\u4e00\u4e2ahash\u6876\u7684\u6570\u636e\u8fc1\u79fb<\/li>\n<li>\u5b9a\u65f6\u4efb\u52a1\uff0c\u8fdb\u884c\u90e8\u5206\u6570\u636e\u8fc1\u79fb<\/li>\n<\/ol>\n<h5>5.3.3.2 \u6e90\u7801\u9a8c\u8bc1<\/h5>\n<h6>CRUD\u89e6\u53d1\u90fd\u4f1a\u89e6\u53d1_dictRehashStep\uff08\u6e10\u8fdb\u5f0fhash\uff09<\/h6>\n<ol>\n<li>\u6bcf\u6b21\u589e\u5220\u6539\u7684\u65f6\u5019\u90fd\u4f1a\u8c03\u7528_dictRehashStep\u65b9\u6cd5<\/li>\n<\/ol>\n<pre>if (dictIsRehashing(d)) _dictRehashStep(d); \/\/\u8fd9\u4e2a\u4ee3\u7801\u5728\u589e\u5220\u6539\u67e5\u7684\u65b9\u6cd5\u4e2d\u90fd\u4f1a\u8c03\u7528<\/pre>\n<ol>\n<li>_dictRehashStep\u65b9\u6cd5<\/li>\n<\/ol>\n<pre>static void _dictRehashStep(dict *d) {\n  if (d-&gt;iterators == 0) dictRehash(d,1);\n}<\/pre>\n<pre>int dictRehash(dict *d, int n) {\n    int empty_visits = n*10; \/* Max number of empty\n    buckets to visit. *\/ \/\/\u8981\u8bbf\u95ee\u7684\u6700\u5927\u7684\u7a7a\u6876\u6570 \u9632\u6b62\u6b64\u6b21\u8017\u65f6\u8fc7\u957f\n    \n    if (!dictIsRehashing(d)) return 0; \/\/\u5982\u679c\u6ca1\u6709\u5728rehash\u8fd4\u56de0\n    \n    \/\/\u5faa\u73af\uff0c\u6700\u591a1\u6b21\uff0c\u5e76\u4e14ht[0]\u7684\u6570\u636e\u6ca1\u6709\u8fc1\u79fb\u5b8c \u8fdb\u5165\u5faa\u73af\n    while(n-- &amp;&amp; d-&gt;ht[0].used != 0) {\n        dictEntry *de, *nextde;\n        \/* Note that rehashidx can't overflow as we are\n        sure there are more\n        * elements because ht[0].used != 0 *\/\n        assert(d-&gt;ht[0].size &gt; (unsigned long)d-&gt;rehashidx);\n        \/\/rehashidx rehash\u7684\u7d22\u5f15\uff0c\u9ed8\u8ba40 \u5982\u679chash\u6876\u4e3a\u7a7a \u8fdb\u5165\u81ea\u65cb \u5e76\u4e14\u5224\u65ad\u662f\u5426\u5230\u4e86\u6700\u5927\u7684\u8bbf\u95ee\u7a7a\u6876\u6570\n        while(d-&gt;ht[0].table[d-&gt;rehashidx] == NULL) {\n            d-&gt;rehashidx++;\n            if (--empty_visits == 0) return 1;\n        }\n        de = d-&gt;ht[0].table[d-&gt;rehashidx]; \/\/\u5f97\u5230ht[0]\u7684\u4e0b\u6807\u4e3arehashidx\u6876\n        \/* Move all the keys in this bucket from the old\n        to the new hash HT *\/\n        while(de) { \/\/\u5faa\u73afhash\u6876\u7684\u94fe\u8868 \u5e76\u4e14\u8f6c\u79fb\u5230ht[1]\n            uint64_t h;\n            nextde = de-&gt;next;\n            \/* Get the index in the new hash table *\/\n            h = dictHashKey(d, de-&gt;key) &amp; d-\n            &gt;ht[1].sizemask;\n            de-&gt;next = d-&gt;ht[1].table[h]; \/\/\u5934\u63d2\n            d-&gt;ht[1].table[h] = de;\n            d-&gt;ht[0].used--;\n            d-&gt;ht[1].used++;\n            de = nextde;\n        }\n        \/\/\u8f6c\u79fb\u5b8c\u540e \u5c06ht[0]\u76f8\u5bf9\u7684hash\u6876\u8bbe\u7f6e\u4e3anull\n        d-&gt;ht[0].table[d-&gt;rehashidx] = NULL;\n        d-&gt;rehashidx++;\n    }\n    \/* Check if we already rehashed the whole table... *\/\n    \/\/ht[0].used=0 \u4ee3\u8868rehash\u5168\u90e8\u5b8c\u6210\n    if (d-&gt;ht[0].used == 0) {\n        \/\/\u6e05\u7a7aht[0]table\n        zfree(d-&gt;ht[0].table);\n        \/\/\u5c06ht[0] \u91cd\u65b0\u6307\u5411\u5df2\u7ecf\u5b8c\u6210rehash\u7684ht[1]\n        d-&gt;ht[0] = d-&gt;ht[1];\n        \/\/\u5c06ht[1]\u6240\u6709\u6570\u636e\u91cd\u65b0\u8bbe\u7f6e\n        _dictReset(&amp;d-&gt;ht[1]);\n        \/\/\u8bbe\u7f6e-1,\u4ee3\u8868rehash\u5b8c\u6210\n        d-&gt;rehashidx = -1;\n        return 0;\n    }\n    \/* More to rehash... *\/\n    return 1;\n}\n\n\/\/\u5c06ht[1]\u7684\u5c5e\u6027\u590d\u4f4d\nstatic void _dictReset(dictht *ht)\n{\n    ht-&gt;table = NULL;\n    ht-&gt;size = 0;\n    ht-&gt;sizemask = 0;\n    ht-&gt;used = 0;\n}<\/pre>\n<p>\u518d\u8bb2\u5b9a\u65f6\u4efb\u52a1\u4e4b\u524d\uff0c\u6211\u4eec\u8981\u77e5\u9053Redis\u4e2d\u6709\u4e2a\u65f6\u95f4\u4e8b\u4ef6\u9a71\u52a8,\u5728 server.c\u6587\u4ef6\u4e0b\u6709\u4e2aserverCron \u65b9\u6cd5\u3002<\/p>\n<p>serverCron \u6bcf\u9694\u591a\u4e45\u4f1a\u6267\u884c\u4e00\u6b21\uff0c\u6267\u884c\u9891\u7387\u6839\u636eredis.conf\u4e2d\u7684hz\u914d\u7f6e\uff0cserverCorn\u4e2d\u6709\u4e2a\u65b9\u6cd5databasesCron()<\/p>\n<ol>\n<li>\u5b9a\u65f6\u65b9\u6cd5serverCron<\/li>\n<\/ol>\n<pre>int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n    \/\/.......\n    \/* We need to do a few operations on clients\n    asynchronously. *\/\n    clientsCron();\n    \/* Handle background operations on Redis databases. *\/\n    databasesCron(); \/\/\u5904\u7406Redis\u6570\u636e\u5e93\u4e0a\u7684\u540e\u53f0\u64cd\u4f5c\u3002\n    \/\/.......\n}<\/pre>\n<ol>\n<li>databasesCron\u65b9\u6cd5<\/li>\n<\/ol>\n<pre>void databasesCron(void) {\n    \/* Expire keys by random sampling. Not required for\n    slaves\n    * as master will synthesize DELs for us. *\/\n    if (server.active_expire_enabled) {\n        if (iAmMaster()) {\n            activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);\n        } else {\n            expireSlaveKeys();\n        }\n    }\n    \/* Defrag keys gradually. *\/\n    activeDefragCycle();\n    \/* Perform hash tables rehashing if needed, but only\n    if there are no\n    * other processes saving the DB on disk. Otherwise\n    rehashing is bad\n    * as will cause a lot of copy-on-write of memory\n    pages. *\/\n    if (!hasActiveChildProcess()) {\n        \/* We use global counters so if we stop the\n        computation at a given\n        * DB we'll be able to start from the successive\n        in the next\n        * cron loop iteration. *\/\n        static unsigned int resize_db = 0;\n        static unsigned int rehash_db = 0;\n        int dbs_per_call = CRON_DBS_PER_CALL;\n        int j;\n        \/* Don't test more DBs than we have. *\/\n        if (dbs_per_call &gt; server.dbnum) \n            dbs_per_call = server.dbnum;\n        \/* Resize *\/\n        for (j = 0; j \n<p><\/p>\n<pre>int incrementallyRehash(int dbid) {\n    \/* Keys dictionary *\/\n    if (dictIsRehashing(server.db[dbid].dict)) {\n        dictRehashMilliseconds(server.db[dbid].dict,1);\n        return 1; \n        \/* already used our millisecond for this\n        loop... *\/\n    }\n    \/* Expires *\/\n    if (dictIsRehashing(server.db[dbid].expires)) {\n        dictRehashMilliseconds(server.db[dbid].expires,1);\n        return 1; \/* already used our millisecond for this\n        loop... *\/\n    }\n    return 0;\n}<\/pre>\n<ol>\n<li>\u8fdb\u5165dictRehashMilliseconds\uff08dict.c\uff09<\/li>\n<\/ol>\n<pre>int dictRehashMilliseconds(dict *d, int ms) {\n    long long start = timeInMilliseconds();\n    int rehashes = 0;\n    \/\/\u8fdb\u5165rehash\u65b9\u6cd5 dictRehash \u53bb\u5b8c\u6210\u6e10\u8fdb\u65f6HASH\n    while(dictRehash(d,100)) {\n        rehashes += 100;\n        \/\/\u5224\u65ad\u662f\u5426\u8d85\u65f6\n        if (timeInMilliseconds()-start &gt; ms) break;\n    }\n    return rehashes;\n}<\/pre>\n<h3>5.4 String\u7c7b\u578b\u6570\u636e\u7ed3\u6784<\/h3>\n<p>Redis\u4e2dString\u7684\u5e95\u5c42\u6ca1\u6709\u7528c\u7684char\u6765\u5b9e\u73b0\uff0c\u800c\u662f\u91c7\u7528\u4e86SDS\uff08simple Dynamic String\uff09\u7684\u6570\u636e\u7ed3\u6784\u6765\u5b9e\u73b0\u3002\u5e76\u4e14\u63d0\u4f9b\u4e865\u79cd\u4e0d\u540c\u7684\u7c7b\u578b<\/p>\n<h4>5.4.1 SDS\u6570\u636e\u7ed3\u6784\u5b9a\u4e49\uff08sds.h\u6587\u4ef6\uff09<\/h4>\n<pre>typedef char *sds;\n\/* Note: sdshdr5 is never used, we just access the flags\n    byte directly.\n    * However is here to document the layout of type 5 SDS\nstrings. *\/\nstruct __attribute__ ((__packed__)) sdshdr5 {\n    unsigned char flags; \/* 3 lsb of type, and 5 msb of\n        string length *\/\n    char buf[];\n}\n\nstruct __attribute__ ((__packed__)) sdshdr8 {\n    uint8_t len;  \/* used *\/ \/\/\u5df2\u4f7f\u7528\u7684\u957f\u5ea6\n    uint8_t alloc; \/* excluding the header and null terminator *\/ \/\/\u5206\u914d\u7684\u603b\u5bb9\u91cf \u4e0d\u5305\u542b\u5934\u548c\u7a7a\u7ec8\u6b62\u7b26\n    unsigned char flags; \/* 3 lsb of type, 5 unused bits *\/ \/\/\u4f4e\u4e09\u4f4d\u7c7b\u578b \u9ad85bit\u672a\u4f7f\u7528\n    char buf[]; \/\/\u6570\u636ebuf \u5b58\u50a8\u5b57\u7b26\u4e32\u6570\u7ec4\n};\n\nstruct __attribute__ ((__packed__)) sdshdr16 {\n    uint16_t len; \/* used *\/\n    uint16_t alloc; \/* excluding the header and null\n    terminator *\/\n    unsigned char flags; \/* 3 lsb of type, 5 unused bits\n    *\/\n    char buf[];\n};\n\nstruct __attribute__ ((__packed__)) sdshdr32 {\n    uint32_t len; \/* used *\/\n    uint32_t alloc; \/* excluding the header and null\n    terminator *\/\n    unsigned char flags; \/* 3 lsb of type, 5 unused bits\n    *\/\n    char buf[];\n};\n\nstruct __attribute__ ((__packed__)) sdshdr64 {\n    uint64_t len; \/* used *\/\n    uint64_t alloc; \/* excluding the header and null\n    terminator *\/\n    unsigned char flags; \/* 3 lsb of type, 5 unused bits\n    *\/\n    char buf[];\n};<\/pre>\n<ol>\n<li>char\u5b57\u7b26\u4e32\u4e0d\u8bb0\u5f55\u81ea\u8eab\u957f\u5ea6\uff0c\u6240\u4ee5\u83b7\u53d6\u4e00\u4e2a\u5b57\u7b26\u4e32\u957f\u5ea6\u7684\u590d\u6742\u5ea6\u662fO(n)\uff0c\u4f46\u662fSDS\u8bb0\u5f55\u5206\u914d\u7684\u957f\u5ea6alloc\uff0c\u5df2\u4f7f\u7528\u7684\u957f\u5ea6len\uff0c\u83b7\u53d6\u957f\u5ea6\u4e3a O(1)<\/li>\n<li>\u51cf\u5c11\u4fee\u6539\u5b57\u7b26\u4e32\u5e26\u6765\u7684\u5185\u5b58\u91cd\u5206\u914d\u6b21\u6570<\/li>\n<li>\u7a7a\u95f4\u9884\u5206\u914d\uff0cSDS\u957f\u5ea6\u5982\u679c\u5c0f\u4e8e1MB\uff0c\u9884\u5206\u914d\u8ddf\u957f\u5ea6\u4e00\u6837\u7684\uff0c\u5927\u4e8e1M\uff0c\u6bcf\u6b21\u8ddflen\u7684\u5927\u5c0f\u591a1M<\/li>\n<li>\u60f0\u6027\u7a7a\u95f4\u91ca\u653e\uff0c\u622a\u53d6\u7684\u65f6\u5019\u4e0d\u9a6c\u4e0a\u91ca\u653e\u7a7a\u95f4\uff0c\u4f9b\u4e0b\u6b21\u4f7f\u7528\uff01\u540c\u65f6\u63d0\u4f9b\u76f8\u5e94\u7684\u91ca\u653eSDS\u672a\u4f7f\u7528\u7a7a\u95f4\u7684API<\/li>\n<li>\u4e8c\u8fdb\u5236\u5b89\u5168<\/li>\n<\/ol>\n<h3>5.5 Hash\u7c7b\u578b\u6570\u636e\u7ed3\u6784<\/h3>\n<p>Redis\u7684\u5b57\u5178\u76f8\u5f53\u4e8eJava\u8bed\u8a00\u4e2d\u7684HashMap\uff0c\u4ed6\u662f\u65e0\u5e8f\u5b57\u5178\u3002\u5185\u90e8\u7ed3\u6784\u4e0a\u540c\u6837\u662f\u6570\u7ec4 + \u94fe\u8868\u4e8c\u7ef4\u7ed3\u6784\u3002\u7b2c\u4e00\u7ef4hash\u7684\u6570\u7ec4\u4f4d\u7f6e\u78b0\u649e\u65f6\uff0c\u5c31\u4f1a\u5c06\u78b0\u649e\u7684\u5143\u7d20\u4f7f\u7528\u94fe\u8868\u4e32\u8d77\u6765\u3002<\/p>\n<h4>5.5.1 Hash\u6570\u636e\u7ed3\u6784\u56fe<\/h4>\n<p style=\"text-align:center\"><img decoding=\"async\" src=\"https:\/\/www.17golang.com\/uploads\/20230225\/167729041763f96bb1a937c.png\" style=\"max-width:100%\" class=\"aligncenter\"><\/p>\n<h4>5.5.2 Hash\u7684\u538b\u7f29\u5217\u8868<\/h4>\n<p>\u538b\u7f29\u5217\u8868\u4f1a\u6839\u636e\u5b58\u5165\u7684\u6570\u636e\u7684\u4e0d\u540c\u7c7b\u578b\u4ee5\u53ca\u4e0d\u540c\u5927\u5c0f\uff0c\u5206\u914d\u4e0d\u540c\u5927\u5c0f\u7684\u7a7a\u95f4\u3002\u6240\u4ee5\u662f\u4e3a\u4e86\u8282\u7701\u5185\u5b58\u800c\u91c7\u7528\u7684\u3002<\/p>\n<p>\u56e0\u4e3a\u662f\u4e00\u5757\u5b8c\u6574\u7684\u5185\u5b58\u7a7a\u95f4\uff0c\u5f53\u91cc\u9762\u7684\u5143\u7d20\u53d1\u751f\u53d8\u66f4\u65f6\uff0c\u4f1a\u4ea7\u751f\u8fde\u9501\u66f4\u65b0\uff0c\u4e25\u91cd\u5f71\u54cd\u6211\u4eec\u7684\u8bbf\u95ee\u6027\u80fd\u3002\u6240\u4ee5\uff0c\u53ea\u9002\u7528\u4e8e\u6570\u636e\u91cf\u6bd4\u8f83\u5c0f\u7684\u573a\u666f\u3002<\/p>\n<p>\u6240\u4ee5\uff0cRedis\u4f1a\u6709\u76f8\u5173\u914d\u7f6e\uff0cHashes\u53ea\u6709\u5c0f\u6570\u636e\u91cf\u7684\u65f6\u5019\u624d\u4f1a\u7528\u5230ziplist\uff0c\u5f53hash\u5bf9\u8c61\u540c\u65f6\u6ee1\u8db3\u4ee5\u4e0b\u4e24\u4e2a\u6761\u4ef6\u7684\u65f6\u5019\uff0c\u4f7f\u7528ziplist\u7f16\u7801\uff1a<\/p>\n<ol>\n<li>\u54c8\u5e0c\u5bf9\u8c61\u4fdd\u5b58\u7684\u952e\u503c\u5bf9\u6570\u91cf\uff1c512\u4e2a<\/li>\n<li>\u6240\u6709\u7684\u952e\u503c\u5bf9\u7684\u952e\u548c\u503c\u7684\u5b57\u7b26\u4e32\u957f\u5ea6\u90fd\uff1c64byte\uff08\u4e00\u4e2a\u82f1\u6587\u5b57\u6bcd\u4e00\u4e2a\u5b57\u8282\uff09<\/li>\n<\/ol>\n<pre>hash-max-ziplist-value 64 \/\/ ziplist\u4e2d\u6700\u5927\u80fd\u5b58\u653e\u7684\u503c\u957f\u5ea6\nhash-max-ziplist-entries 512 \/\/ ziplist\u4e2d\u6700\u591a\u80fd\u5b58\u653e\u7684entry\u8282\u70b9\u6570\u91cf<\/pre>\n<h3>5.6 List\u7c7b\u578b\u6570\u636e\u7ed3\u6784<\/h3>\n<h4>5.6.1 quickList\u5feb\u901f\u5217\u8868<\/h4>\n<p>\u517c\u987e\u4e86ziplist\u7684\u8282\u7701\u5185\u5b58\uff0c\u5e76\u4e14\u4e00\u5b9a\u7a0b\u5ea6\u4e0a\u89e3\u51b3\u4e86\u8fde\u9501\u66f4\u65b0\u7684\u95ee\u9898\uff0c\u6211\u4eec\u7684 quicklistNode\u8282\u70b9\u91cc\u9762\u662f\u4e2aziplist\uff0c\u6bcf\u4e2a\u8282\u70b9\u662f\u5206\u5f00\u7684\u3002\u90a3\u4e48\u5c31\u7b97\u53d1\u751f\u4e86\u8fde\u9501\u66f4\u65b0\uff0c\u4e5f\u53ea\u4f1a\u53d1\u751f\u5728\u4e00\u4e2aquicklistNode\u8282\u70b9\u3002<\/p>\n<p>quicklist.h\u6587\u4ef6<\/p>\n<pre>typedef struct{\n    struct quicklistNode *prev; \/\/\u524d\u6307\u9488\n    struct quicklistNode *next; \/\/\u540e\u6307\u9488\n    unsigned char *zl; \/\/\u6570\u636e\u6307\u9488 \u6307\u5411ziplist\u7ed3\u679c\n    unsigned int sz; \/\/ziplist\u5927\u5c0f \/* ziplist\n    size in bytes *\/\n    unsigned int count : 16; \/* count of items in ziplist *\/ \/\/ziplist\u7684\u5143\u7d20\n    unsigned int encoding : 2; \/* RAW==1 or LZF==2 *\/ \/\/\n    \u662f\u5426\u538b\u7f29\uff0c 1\u6ca1\u6709\u538b\u7f29 2 lzf\u538b\u7f29\n    unsigned int container : 2; \/* NONE==1 or ZIPLIST==2 *\/ \/\/\u9884\u7559\u5bb9\u5668\u5b57\u6bb5\n    unsigned int recompress : 1; \/* was this node previous compressed? *\/\n    unsigned int attempted_compress : 1; \/* node can't compress; too small *\/\n    unsigned int extra : 10; \/* more bits to steal for  future usage *\/ \/\/\u9884\u7559\u5b57\u6bb5\n} quicklistNode;<\/pre>\n<h4>5.6.2 list\u6570\u636e\u7ed3\u6784\u56fe<\/h4>\n<p style=\"text-align:center\"><img decoding=\"async\" src=\"https:\/\/www.17golang.com\/uploads\/20230225\/167729041863f96bb21eb61.png\" style=\"max-width:100%\" class=\"aligncenter\"><\/p>\n<h3>5.7 Set\u7c7b\u578b\u6570\u636e\u7ed3\u6784<\/h3>\n<p>Redis\u7528intset\u6216hashtable\u5b58\u50a8set\u3002\u6ee1\u8db3\u4e0b\u9762\u6761\u4ef6\uff0c\u5c31\u7528inset\u5b58\u50a8\u3002<\/p>\n<ol>\n<li>\u5982\u679c\u4e0d\u662f\u6574\u6570\u7c7b\u578b\uff0c\u5c31\u7528dictht hash\u8868\uff08\u6570\u7ec4+\u94fe\u8868\uff09<\/li>\n<li>\u5982\u679c\u5143\u7d20\u4e2a\u6570\u8d85\u8fc7512\u4e2a\uff0c\u4e5f\u4f1a\u7528hashtable\u5b58\u50a8\u3002\u8ddf\u4e00\u4e2a\u914d\u7f6e\u6709\u5173\uff1a<\/li>\n<\/ol>\n<pre>set-max-intset-entries 512<\/pre>\n<p>\u4e0d\u6ee1\u8db3\u4e0a\u8ff0\u6761\u4ef6\u7684\uff0c\u90fd\u4f7f\u7528hash\u8868\u5b58\u50a8\uff0cvalue\u5b58null\u3002<\/p>\n<h3>5.8 ZSet\u6570\u636e\u7ed3\u6784<\/h3>\n<h4>5.8.1 ZipList<\/h4>\n<p>\u9ed8\u8ba4\u4f7f\u7528ziplist\u7f16\u7801\u3002<\/p>\n<p>\u5728ziplist\u7684\u5185\u90e8\uff0c\u6309\u7167score\u6392\u5e8f\u9012\u589e\u6765\u5b58\u50a8\u3002\u63d2\u5165\u7684\u65f6\u5019\u8981\u79fb\u52a8\u4e4b\u540e\u7684\u6570\u636e\u3002<\/p>\n<p>\u5982\u679c\u5143\u7d20\u6570\u91cf\u5927\u4e8e\u7b49\u4e8e128\u4e2a\uff0c\u6216\u8005\u4efb\u4e00member\u957f\u5ea6\u5927\u4e8e\u7b49\u4e8e64\u5b57\u8282\u4f7f\u7528 skiplist+dict\u5b58\u50a8\u3002<\/p>\n<pre>zset-max-ziplist-entries 128\nzset-max-ziplist-value 64<\/pre>\n<p>\u5982\u679c\u4e0d\u6ee1\u8db3\u6761\u4ef6\uff0c\u91c7\u7528\u8df3\u8868\u3002<\/p>\n<h4>5.8.2 \u8df3\u8868\uff08skiplist\uff09<\/h4>\n<p>\u7ed3\u6784\u5b9a\u4e49\uff08servier.h\uff09<\/p>\n<pre>\/* ZSETs use a specialized version of Skiplists *\/\ntypedef struct zskiplistNode {\n sds ele; \/\/sds\u6570\u636e\n double score; \/\/score\n struct zskiplistNode *backward; \/\/\u540e\u9000\u6307\u9488\n \/\/\u5c42\u7ea7\u6570\u7ec4\n struct zskiplistLevel {\n     struct zskiplistNode *forward; \/\/\u524d\u8fdb\u6307\u9488\n     unsigned long span; \/\/\u8de8\u5ea6\n } level[];\n} zskiplistNode;\n\n\/\/\u8df3\u8868\u5217\u8868\ntypedef struct zskiplist {\n struct zskiplistNode *header, *tail; \/\/\u5934\u5c3e\u8282\u70b9\n unsigned long length; \/\/\u8282\u70b9\u6570\u91cf\n int level; \/\/\u6700\u5927\u7684\u8282\u70b9\u5c42\u7ea7\n} zskiplist;<\/pre>\n<p>zslInsert \u6dfb\u52a0\u8282\u70b9\u65b9\u6cd5 \uff08t_zset.c\uff09<\/p>\n<pre>zskiplistNode *zslInsert(zskiplist *zsl, double score, sds\nele) {\n zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n unsigned int rank[ZSKIPLIST_MAXLEVEL];\n int i, level;\n serverAssert(!isnan(score));\n x = zsl-&gt;header;\n for (i = zsl-&gt;level-1; i &gt;= 0; i--) {\n     \/* store rank that is crossed to reach the insert\n     position *\/\n     rank[i] = i == (zsl-&gt;level-1) ? 0 : rank[i+1];\n     while (x-&gt;level[i].forward &amp;&amp;\n         (x-&gt;level[i].forward-&gt;score level[i].forward-&gt;score == score\n         &amp;&amp;\n         sdscmp(x-&gt;level[i].forward-&gt;ele,ele) level[i].span;\n         x = x-&gt;level[i].forward;\n     }\n     update[i] = x;\n }\n \/* we assume the element is not already inside, since\n we allow duplicated\n    * scores, reinserting the same element should never\n    happen since the\n    * caller of zslInsert() should test in the hash table\n    if the element is\n    * already inside or not. *\/\n    level = zslRandomLevel();\n    if (level &gt; zsl-&gt;level) {\n        for (i = zsl-&gt;level; i header;\n            update[i]-&gt;level[i].span = zsl-&gt;length;\n        }\n        zsl-&gt;level = level;\n    }\n    x = zslCreateNode(level,score,ele);\n    \/\/\u4e0d\u540c\u5c42\u7ea7\u5efa\u7acb\u94fe\u8868\u8054\u7cfb\n    for (i = 0; i level[i].forward = update[i]-&gt;level[i].forward;\n        update[i]-&gt;level[i].forward = x;\n        \/* update span covered by update[i] as x is\n        inserted here *\/\n        x-&gt;level[i].span = update[i]-&gt;level[i].span -\n        (rank[0] - rank[i]);\n        update[i]-&gt;level[i].span = (rank[0] - rank[i]) +\n        1;\n    }\n    \/* increment span for untouched levels *\/\n    for (i = level; i level; i++) {\n        update[i]-&gt;level[i].span++;\n    }\n    x-&gt;backward = (update[0] == zsl-&gt;header) ? NULL :\n    update[0];\n    if (x-&gt;level[0].forward)\n        x-&gt;level[0].forward-&gt;backward = x;\n    else\n        zsl-&gt;tail = x;\n        zsl-&gt;length++;\n    return x;\n}<\/pre>\n<pre>#define ZSKIPLIST_MAXLEVEL 32 \/* Should be enough for 2^64\nelements *\/<\/pre>\n<h2>\u516d\u3001Redis\u8fc7\u671f\u7b56\u7565<\/h2>\n<h3>6.1 \u60f0\u6027\u8fc7\u671f<\/h3>\n<p>\u6240\u8c13\u60f0\u6027\u8fc7\u671f\uff0c\u5c31\u662f\u5728\u6bcf\u6b21\u8bbf\u95ee\u64cd\u4f5ckey\u7684\u65f6\u5019\uff0c\u5224\u65ad\u8fd9\u4e2akey\u662f\u4e0d\u662f\u8fc7\u671f\u4e86\uff0c\u8fc7\u671f\u4e86\u5c31\u5220\u9664\u3002<\/p>\n<h4>6.1.1 \u6e90\u7801\u9a8c\u8bc1<\/h4>\n<ol>\n<li>expireIfNeeded\u65b9\u6cd5\uff08db.c\u6587\u4ef6\uff09<\/li>\n<\/ol>\n<pre>int expireIfNeeded(redisDb *db, robj *key) {\n    if (!keyIsExpired(db,key)) return 0;\n    \/* If we are running in the context of a slave,\n    instead of\n    * evicting the expired key from the database, we\n    return ASAP:\n    * the slave key expiration is controlled by the\n    master that will\n    * send us synthesized DEL operations for expired\n    keys.\n    *\n    * Still we try to return the right information to the\n    caller,\n    * that is, 0 if we think the key should be still\n    valid, 1 if\n    * we think the key is expired at this time. *\/\n    \/\/ \u5982\u679c\u914d\u7f6e\u6709masterhost\uff0c\u8bf4\u660e\u662f\u4ece\u8282\u70b9\uff0c\u90a3\u4e48\u4e0d\u64cd\u4f5c\u5220\u9664\n    if (server.masterhost != NULL) return 1;\n    \/* Delete the key *\/\n    server.stat_expiredkeys++;\n    propagateExpire(db,key,server.lazyfree_lazy_expire);\n    notifyKeyspaceEvent(NOTIFY_EXPIRED,\n    \"expired\",key,db-&gt;id);\n    \/\/\u662f\u5426\u662f\u5f02\u6b65\u5220\u9664 \u9632\u6b62\u5355\u4e2aKey\u7684\u6570\u636e\u91cf\u5f88\u5927 \u963b\u585e\u4e3b\u7ebf\u7a0b \u662f4.0\u4e4b\u540e\u6dfb\u52a0\u7684\u65b0\u529f\u80fd\uff0c\u9ed8\u8ba4\u5173\u95ed\n    int retval = server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) : dbSyncDelete(db,key);\n    if (retval) signalModifiedKey(NULL,db,key);\n    return retval;\n}<\/pre>\n<p>\u8be5\u7b56\u7565\u53ef\u4ee5\u6700\u5927\u5316\u7684\u8282\u7701CPU\u8d44\u6e90\u3002<\/p>\n<p>\u4f46\u662f\u5374\u5bf9\u5185\u5b58\u975e\u5e38\u4e0d\u53cb\u597d\u3002\u56e0\u4e3a\u5982\u679c\u6ca1\u6709\u518d\u6b21\u8bbf\u95ee\uff0c\u5c31\u53ef\u80fd\u4e00\u76f4\u5806\u79ef\u518d\u5185\u5b58\u4e2d\u3002\u5360\u7528\u5185\u5b58<\/p>\n<p>\u6240\u4ee5\u5c31\u9700\u8981\u53e6\u4e00\u79cd\u7b56\u7565\u6765\u914d\u5408\u4f7f\u7528\uff0c\u5c31\u662f\u5b9a\u671f\u8fc7\u671f<\/p>\n<h3>6.2 \u5b9a\u671f\u8fc7\u671f<\/h3>\n<p>\u90a3\u4e48\u591a\u4e45\u53bb\u6e05\u9664\u4e00\u6b21\uff0c\u6211\u4eec\u5728\u8bb2Rehash\u7684\u65f6\u5019\uff0c\u6709\u4e2a\u65b9\u6cd5\u662fserverCron\uff0c\u6267\u884c\u9891\u7387\u6839\u636eredis.conf\u4e2d\u7684hz\u914d\u7f6e\u3002<\/p>\n<p>\u8fd9\u65b9\u6cd5\u9664\u4e86\u505aRehash\u4ee5\u5916\uff0c\u8fd8\u4f1a\u505a\u5f88\u591a\u5176\u4ed6\u7684\u4e8b\u60c5\uff0c\u6bd4\u5982\uff1a<\/p>\n<ol>\n<li>\u6e05\u7406\u6570\u636e\u5e93\u4e2d\u7684\u8fc7\u671f\u952e\u503c\u5bf9<\/li>\n<li>\u66f4\u65b0\u670d\u52a1\u5668\u7684\u5404\u7c7b\u7edf\u8ba1\u4fe1\u606f\uff0c\u6bd4\u5982\u65f6\u95f4\u3001\u5185\u5b58\u5360\u7528\u3001\u6570\u636e\u5e93\u5360\u7528\u60c5\u51b5\u7b49<\/li>\n<li>\u5173\u95ed\u548c\u6e05\u7406\u8fde\u63a5\u5931\u6548\u7684\u5ba2\u6237\u7aef<\/li>\n<li>\u5c1d\u8bd5\u8fdb\u884c\u6301\u4e45\u5316\u64cd\u4f5c<\/li>\n<\/ol>\n<h4>6.2.1 \u5b9e\u73b0\u6d41\u7a0b<\/h4>\n<ol>\n<li>\u5b9a\u65f6serverCron\u65b9\u6cd5\u53bb\u6267\u884c\u6e05\u7406\uff0c\u6267\u884c\u9891\u7387\u6839\u636eredis.cong\u4e2d\u7684hz\u914d\u7f6e\u7684\u503c\uff08\u9ed8\u8ba4\u662f10\uff0c\u4e5f\u5c31\u662f1s\u6267\u884c10\u6b21\uff0c100ms\u6267\u884c\u4e00\u6b21\uff09<\/li>\n<li>\u6267\u884c\u6e05\u7406\u7684\u65f6\u5019\uff0c\u4e0d\u662f\u53bb\u626b\u63cf\u6240\u6709\u7684key\uff0c\u800c\u662f\u53bb\u626b\u63cf\u6240\u6709\u8bbe\u7f6e\u4e86\u8fc7\u671f\u65f6\u95f4\u7684key redisDB.expires<\/li>\n<li>\u5982\u679c\u6bcf\u6b21\u53bb\u628a\u6240\u6709\u7684key\u90fd\u62ff\u51fa\u6765\uff0c\u90a3\u4e48\u5047\u5982\u8fc7\u671f\u7684key\u5f88\u591a\uff0c\u5c31\u4f1a\u5f88\u6162\uff0c\u6240\u4ee5\u4e5f\u4e0d\u662f\u4e00\u6b21\u6027\u62ff\u51fa\u6240\u6709\u7684key<\/li>\n<li>\u6839\u636ehash\u6876\u7684\u7ef4\u5ea6\u53bb\u626b\u63cfkey\uff0c\u626b\u523020(\u53ef\u914d\u7f6e)\u4e2akey\u4e3a\u6b62\u3002\u5047\u5982\u7b2c\u4e00\u4e2a\u6876\u662f15\u4e2akey\u6ca1\u6709\u6ee1\u8db320\uff0c\u7ee7\u7eed\u626b\u63cf\u7b2c\u4e8c\u4e2a\u6876\uff0c\u7b2c\u4e8c\u4e2a\u687620\u4e2akey\uff0c\u7531\u4e8e\u662f\u4ee5hash\u6876\u7684\u7ef4\u5ea6\u626b\u63cf\u7684\uff0c\u6240\u4ee5\u7b2c\u4e8c\u4e2a\u626b\u5230\u4e86\u5c31\u4f1a\u5168\u626b\uff0c\u603b\u5171\u626b\u63cf35\u4e2akey<\/li>\n<li>\u627e\u5230\u626b\u63cf\u7684key\u91cc\u9762\u8fc7\u671f\u7684key\uff0c\u5e76\u8fdb\u884c\u5220\u9664<\/li>\n<li>\u5982\u679c\u53d6\u4e86400\u4e2a\u7a7a\u6876\uff08\u6700\u591a\u62ff400\u4e2a\u6876\uff09\uff0c\u6216\u8005\u626b\u63cf\u7684\u5220\u9664\u6bd4\u4f8b\u8ddf\u626b\u63cf\u7684\u603b\u6570\u8d85\u8fc710%\uff0c\u7ee7\u7eed\u6267\u884c4\u30015\u6b65<\/li>\n<li>\u4e5f\u4e0d\u80fd\u65e0\u9650\u7684\u5faa\u73af\uff0c\u5faa\u73af16\u6b21\u540e\u56de\u53bb\u68c0\u6d4b\u65f6\u95f4\uff0c\u8d85\u8fc7\u6307\u5b9a\u65f6\u95f4\u4f1a\u8df3\u51fa<\/li>\n<\/ol>\n<h4>6.2.2 \u6e90\u7801\u9a8c\u8bc1<\/h4>\n<ol>\n<li>\u5165\u53e3serverCrom<\/li>\n<\/ol>\n<pre>\/\/ serverCron\u65b9\u6cd5\u8c03\u7528databasesCron\u65b9\u6cd5\uff08server.c\uff09\n\/* Handle background operations on Redis databases. *\/\ndatabasesCron();\n\nvoid databasesCron(void) {\n    \/* Expire keys by random sampling. Not required for\n    slaves\n    * as master will synthesize DELs for us. *\/\n    if (server.active_expire_enabled) {\n        if (iAmMaster()) {\n            activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);\n        \/\/\u8fc7\u671f\u5220\u9664\u65b9\u6cd5\n        } else {\n            expireSlaveKeys();\n        }\n    }\n}<\/pre>\n<p>\u7531\u4e8eRedis\u5185\u5b58\u662f\u6709\u5927\u5c0f\u7684\uff0c\u5e76\u4e14\u6211\u53ef\u80fd\u91cc\u9762\u7684\u6570\u636e\u90fd\u6ca1\u6709\u8fc7\u671f\uff0c\u5f53\u5feb\u6ee1\u7684\u65f6\u5019\uff0c\u6211\u53c8\u6ca1\u6709\u8fc7\u671f\u7684\u6570\u636e\u8fdb\u884c\u6dd8\u6c70\uff0c\u90a3\u4e48\u8fd9\u4e2a\u65f6\u5019\u5185\u5b58\u4e5f\u4f1a\u6ee1\u3002\u5185\u5b58\u6ee1\u4e86\uff0cRedis\u4e5f\u4f1a\u4e0d\u80fd\u653e\u5165\u65b0\u7684\u6570\u636e\u3002\u6240\u4ee5\uff0c\u6211\u4eec\u4e0d\u5f97\u5df2\u9700\u8981\u4e00\u4e9b\u7b56\u7565\u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u6765\u4fdd\u8bc1\u53ef\u7528\u6027\u3002<\/p>\n<h3>7.1 \u6dd8\u6c70\u7b56\u7565<\/h3>\n<h4>7.1.1 noeviction<\/h4>\n<p>New values aren\u2019t saved when memory limit is reached. When a database uses replication, this applies to the primary database.<\/p>\n<p>\u9ed8\u8ba4\uff0c\u4e0d\u6dd8\u6c70 \u80fd\u8bfb\u4e0d\u80fd\u5199<\/p>\n<h4>7.1.2 allkeys-lru<\/h4>\n<p>Keeps most recently used keys; removes least recently used (LRU) keys<\/p>\n<p>\u57fa\u4e8e\u4f2aLRU\u7b97\u6cd5\uff0c\u5728\u6240\u6709\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.3 allkeys-lfu<\/h4>\n<p>Keeps frequently used keys; removes least frequently used (LFU) keys.<\/p>\n<p>\u57fa\u4e8e\u4f2aLFU\u7b97\u6cd5\uff0c\u5728\u6240\u6709\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.4 volatile-lru<\/h4>\n<p>Removes least recently used keys with the expire field set to true.<\/p>\n<p>\u57fa\u4e8e\u4f2aLRU\u7b97\u6cd5\uff0c\u5728\u8bbe\u7f6e\u4e86\u8fc7\u671f\u65f6\u95f4\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.5 volatile-lfu<\/h4>\n<p>Removes least frequently used keys with the expire field set to true.<\/p>\n<p>\u57fa\u4e8e\u4f2aLFU\u7b97\u6cd5 \u5728\u8bbe\u7f6e\u4e86\u8fc7\u671f\u65f6\u95f4\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.6 allkeys-random<\/h4>\n<p>Randomly removes keys to make space for the new data added.<\/p>\n<p>\u57fa\u4e8e\u968f\u673a\u7b97\u6cd5\uff0c\u5728\u6240\u6709\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.7 volatile-random<\/h4>\n<p>Randomly removes keys with expire field set to true.<\/p>\n<p>\u57fa\u4e8e\u968f\u673a\u7b97\u6cd5 \u5728\u8bbe\u7f6e\u4e86\u8fc7\u671f\u65f6\u95f4\u7684key\u4e2d\u53bb\u6dd8\u6c70<\/p>\n<h4>7.1.8 volatile-ttl<\/h4>\n<p>Removes least frequently used keys with expire field set to true and the shortest remaining time-to-live (TTL) value.<\/p>\n<p>\u6839\u636e\u8fc7\u671f\u65f6\u95f4\u6765\uff0c\u6dd8\u6c70\u5373\u5c06\u8fc7\u671f\u7684<\/p>\n<h3>7.2 \u6dd8\u6c70\u6d41\u7a0b<\/h3>\n<ol>\n<li>\u9996\u5148\uff0c\u6211\u4eec\u4f1a\u6709\u4e2a\u6dd8\u6c70\u6c60\uff0c\u9ed8\u8ba4\u5927\u5c0f\u662f16\uff0c\u5e76\u4e14\u91cc\u9762\u7684\u6570\u636e\u662f\u672b\u5c3e\u6dd8\u6c70\u5236<\/li>\n<li>\u6bcf\u6b21\u6307\u4ee4\u64cd\u4f5c\u7684\u65f6\u5019\uff0c\u81ea\u65cb\u4f1a\u5224\u65ad\u5f53\u524d\u5185\u5b58\u662f\u5426\u6ee1\u8db3\u6307\u4ee4\u6240\u9700\u8981\u7684\u5185\u5b58<\/li>\n<li>\u5982\u679c\u5f53\u524d\u4e0d\u6ee1\u8db3\uff0c\u4f1a\u4ece\u6dd8\u6c70\u6c60\u7684\u5c3e\u90e8\u62ff\u4e00\u4e2a\u6700\u9002\u5408\u6dd8\u6c70\u7684\u6570\u636e<\/li>\n<\/ol>\n<ul>\n<li>\u4f1a\u53d6\u6837\uff08\u914d\u7f6e maxmemory-samples\uff09\uff0c\u4eceRedis\u4e2d\u83b7\u53d6\u968f\u673a\u83b7\u53d6\u5230\u53d6\u6837\u7684\u6570\u636e\uff0c\u89e3\u51b3\u4e00\u6b21\u6027\u8bfb\u53d6\u6240\u6709\u7684\u6570\u636e\u6162\u7684\u95ee\u9898<\/li>\n<li>\u5728\u53d6\u6837\u7684\u6570\u636e\u4e2d\uff0c\u6839\u636e\u6dd8\u6c70\u7b97\u6cd5\u627e\u5230\u6700\u9002\u5408\u6dd8\u6c70\u7684\u6570\u636e<\/li>\n<li>\u5c06\u6700\u5408\u9002\u7684\u90a3\u4e2a\u6570\u636e\u8ddf\u6dd8\u6c70\u6c60\u4e2d\u7684\u6570\u636e\u8fdb\u884c\u6bd4\u8f83\uff0c\u662f\u5426\u6bd4\u6dd8\u6c70\u6c60\u7684\u6570\u636e\u66f4\u9002\u5408\u6dd8\u6c70\uff0c\u5982\u679c\u66f4\u9002\u5408\uff0c\u653e\u5165\u6dd8\u6c70\u6c60<\/li>\n<li>\u6309\u7167\u9002\u5408\u7684\u7a0b\u5ea6\u8fdb\u884c\u6392\u5e8f\uff0c\u6700\u9002\u5408\u6dd8\u6c70\u7684\u653e\u5165\u5c3e\u90e8<\/li>\n<\/ul>\n<ol>\n<li>\u5c06\u9700\u8981\u6dd8\u6c70\u7684\u6570\u636e\u4eceRedis\u5220\u9664\uff0c\u5e76\u4e14\u4ece\u6dd8\u6c70\u6c60\u79fb\u9664<\/li>\n<\/ol>\n<h3>7.3 LRU\u7b97\u6cd5<\/h3>\n<p>Lru\uff0cLeast Recently Used \u7ffb\u8bd1\u8fc7\u6765\u662f\u6700\u4e45\u672a\u4f7f\u7528\uff0c\u6839\u636e\u65f6\u95f4\u8f74\u6765\u8d70\uff0c\u4ecd\u5f88\u4e45\u6ca1\u7528\u7684\u6570\u636e\u3002\u53ea\u8981\u6700\u8fd1\u6709\u7528\u8fc7\uff0c\u6211\u5c31\u9ed8\u8ba4\u662f\u6709\u6548\u7684\u3002<\/p>\n<p>\u90a3\u4e48\u5b83\u7684\u4e00\u4e2a\u8861\u91cf\u6807\u51c6\u662f\u5565\uff1f\u65f6\u95f4\uff01\u6839\u636e\u4f7f\u7528\u65f6\u95f4\uff0c\u4ece\u8fd1\u5230\u8fdc\uff0c\u8d8a\u8fdc\u7684\u8d8a\u5bb9\u6613\u6dd8\u6c70\u3002<\/p>\n<h4>7.3.1 \u5b9e\u73b0\u539f\u7406<\/h4>\n<p>\u9700\u6c42\uff1a\u5f97\u5230\u5bf9\u8c61\u9694\u591a\u4e45\u6ca1\u8bbf\u95ee\uff0c\u9694\u7684\u65f6\u95f4\u8d8a\u4e45\uff0c\u8d8a\u5bb9\u6613\u88ab\u6dd8\u6c70<\/p>\n<ol>\n<li>\u9996\u5148\uff0cLRU\u662f\u6839\u636e\u8fd9\u4e2a\u5bf9\u8c61\u7684\u8bbf\u95ee\u64cd\u4f5c\u65f6\u95f4\u6765\u8fdb\u884c\u6dd8\u6c70\u7684\uff0c\u90a3\u4e48\u6211\u4eec\u9700\u8981\u77e5\u9053\u8fd9\u4e2a\u5bf9\u8c61\u6700\u540e\u64cd\u4f5c\u7684\u8bbf\u95ee\u65f6\u95f4<\/li>\n<li>\u77e5\u9053\u4e86\u5bf9\u8c61\u7684\u6700\u540e\u64cd\u4f5c\u8bbf\u95ee\u65f6\u95f4\u540e\uff0c\u6211\u4eec\u53ea\u9700\u8981\u8ddf\u5f53\u524d\u7cfb\u7edf\u65f6\u95f4\u6765\u8fdb\u884c\u5bf9\u6bd4\uff0c\u5c31\u80fd\u7b97\u51fa\u5bf9\u8c61\u591a\u4e45\u6ca1\u8bbf\u95ee\u4e86<\/li>\n<\/ol>\n<h4>7.3.2 \u6e90\u7801\u9a8c\u8bc1<\/h4>\n<p>redis\u4e2d\uff0c\u5bf9\u8c61\u90fd\u4f1a\u88abredisObject\u5bf9\u8c61\u5305\u88c5\uff0c\u5176\u4e2d\u6709\u4e2a\u5b57\u6bb5\u53eblru\u3002<\/p>\n<p>redisObject\u5bf9\u8c61 \uff08server.h\u6587\u4ef6\uff09<\/p>\n<pre>typedef struct redisObject {\n unsigned type:4;\n unsigned encoding:4;\n unsigned lru:LRU_BITS; \/* LRU time (relative to global\n lru_clock) or\n * LFU data (least significant 8 bits frequency\n * and most significant 16 bits access time). *\/\n int refcount;\n void *ptr;\n} robj;<\/pre>\n<p>\u770bLRU\u7684\u5b57\u6bb5\u7684\u8bf4\u660e\uff0c\u90a3\u4e48\u6211\u4eec\u5927\u6982\u80fd\u731c\u51fa\u6765\uff0credis\u53bb\u5b9e\u73b0lru\u6dd8\u6c70\u7b97\u6cd5\u80af\u5b9a\u8ddf\u6211\u4eec\u8fd9\u4e2a\u5bf9\u8c61\u7684lru\u76f8\u5173<\/p>\n<p>\u5e76\u4e14\u8fd9\u4e2a\u5b57\u6bb5\u7684\u5927\u5c0f\u4e3a24bit\uff0c\u90a3\u4e48\u8fd9\u4e2a\u5b57\u6bb5\u8bb0\u5f55\u7684\u662f\u5bf9\u8c61\u64cd\u4f5c\u8bbf\u95ee\u65f6\u5019\u7684\u79d2\u5355\u4f4d\u65f6\u95f4\u7684\u540e24bit<\/p>\n<p>\u76f8\u5f53\u4e8e\uff1a<\/p>\n<pre>long timeMillis=System.currentTimeMillis();\nSystem.out.println(timeMillis\/1000); \/\/\u83b7\u53d6\u5f53\u524d\u79d2\nSystem.out.println(timeMillis\/1000 &amp; ((1\n<p>\u6211\u4eec\u77e5\u9053\u4e86\u8fd9\u4e2a\u5bf9\u8c61\u7684\u6700\u540e\u64cd\u4f5c\u8bbf\u95ee\u7684\u65f6\u95f4\u3002\u5982\u679c\u6211\u4eec\u8981\u5f97\u5230\u8fd9\u4e2a\u5bf9\u8c61\u591a\u4e45\u6ca1\u8bbf\u95ee\u4e86\uff0c\u6211\u4eec\u662f\u4e0d\u662f\u5c31\u5f88\u7b80\u5355\uff0c\u7528\u6211\u5f53\u524d\u7684\u65f6\u95f4-\u8fd9\u4e2a\u5bf9\u8c61\u7684\u8bbf\u95ee\u65f6\u95f4\u5c31\u53ef\u4ee5\u4e86\uff01\u4f46\u662f\u8fd9\u4e2a\u8bbf\u95ee\u65f6\u95f4\u662f\u79d2\u5355\u4f4d\u65f6\u95f4\u7684\u540e24bit \u6240\u4ee5\uff0c\u4e5f\u662f\u7528\u5f53\u524d\u7684\u65f6\u95f4\u7684\u79d2\u5355\u4f4d\u7684\u540e24bit\u53bb\u51cf\u3002<\/p>\n<p>estimateObjectIdleTime\u65b9\u6cd5(evict.c)<\/p>\n<pre>unsigned long long estimateObjectIdleTime(robj *o) {\n \/\/\u83b7\u53d6\u79d2\u5355\u4f4d\u65f6\u95f4\u7684\u6700\u540e24\u4f4d\n unsigned long long lruclock = LRU_CLOCK();\n \/\/\u56e0\u4e3a\u53ea\u670924\u4f4d\uff0c\u6240\u6709\u6700\u5927\u7684\u503c\u4e3a2\u768424\u6b21\u65b9-1\n \/\/\u8d85\u8fc7\u6700\u5927\u503c\u4ece0\u5f00\u59cb\uff0c\u6240\u4ee5\u9700\u8981\u5224\u65adlruclock\uff08\u5f53\u524d\u7cfb\u7edf\u65f6\u95f4\uff09\u8ddf\u7f13\u5b58\u5bf9\u8c61\u7684lru\u5b57\u6bb5\u7684\u5927\u5c0f\n if (lruclock &gt;= o-&gt;lru) {\n     \/\/\u5982\u679clruclock&gt;=robj.lru\uff0c\u8fd4\u56delruclock-o-&gt;lru\uff0c\u518d\u8f6c\u6362\u5355\u4f4d\n     return (lruclock - o-&gt;lru) * LRU_CLOCK_RESOLUTION;\n } else {\n     \/\/\u5426\u5219\u91c7\u7528lruclock + (LRU_CLOCK_MAX - o-&gt;lru)\uff0c\u5f97\u5230\u5bf9\n     \u8c61\u7684\u503c\u8d8a\u5c0f\uff0c\u8fd4\u56de\u7684\u503c\u8d8a\u5927\uff0c\u8d8a\u5927\u8d8a\u5bb9\u6613\u88ab\u6dd8\u6c70\n     return (lruclock + (LRU_CLOCK_MAX - o-&gt;lru)) *\n     LRU_CLOCK_RESOLUTION;\n }\n}<\/pre>\n<h4>7.3.3 LRU\u603b\u7ed3<\/h4>\n<p>\u7528lruclock\u4e0e redisObject.lru\u8fdb\u884c\u6bd4\u8f83\uff0c\u56e0\u4e3alruclock\u53ea\u83b7\u53d6\u4e86\u5f53\u524d\u79d2\u5355\u4f4d\u65f6\u95f4\u7684\u540e24\u4f4d\uff0c\u6240\u4ee5\u80af\u5b9a\u6709\u4e2a\u8f6e\u8be2\u3002<\/p>\n<p>\u6240\u4ee5\uff0c\u6211\u4eec\u4f1a\u7528lruclock\u8ddf redisObject.lru\u8fdb\u884c\u6bd4\u8f83\uff0c\u5982\u679clruclock&gt;redisObject.lru\uff0c\u90a3\u4e48\u6211\u4eec\u7528lruclock- redisObject.lru\uff0c\u5426\u5219lruclock+(24bit\u7684\u6700\u5927\u503c-redisObject.lru)\uff0c\u5f97\u5230lru\u8d8a\u5c0f\uff0c\u90a3\u4e48\u8fd4\u56de\u7684\u6570\u636e\u8d8a\u5927\uff0c\u76f8\u5dee\u8d8a\u5927\u7684\u8d8a\u4f18\u5148\u4f1a\u88ab\u6dd8\u6c70\uff01<\/p>\n<\/p>\n<h3>7.4 LFU\u7b97\u6cd5<\/h3>\n<p>LFU\uff0c\u82f1\u6587 Least Frequently Used\uff0c\u7ffb\u8bd1\u6210\u4e2d\u6587\u5c31\u662f\u6700\u4e0d\u5e38\u7528\u7684\u4f18\u5148\u6dd8\u6c70\u3002<\/p>\n<p>\u4e0d\u5e38\u7528\uff0c\u5b83\u7684\u8861\u91cf\u6807\u51c6\u5c31\u662f\u6b21\u6570\uff0c\u6b21\u6570\u8d8a\u5c11\u7684\u8d8a\u5bb9\u6613\u88ab\u6dd8\u6c70\u3002<\/p>\n<p>\u8fd9\u4e2a\u5b9e\u73b0\u8d77\u6765\u5e94\u8be5\u4e5f\u5f88\u7b80\u5355\uff0c\u5bf9\u8c61\u88ab\u64cd\u4f5c\u8bbf\u95ee\u7684\u65f6\u5019\uff0c\u53bb\u8bb0\u5f55\u6b21\u6570\uff0c\u6bcf\u6b21\u64cd\u4f5c\u8bbf\u95ee\u4e00\u6b21\uff0c\u5c31+1\uff1b\u6dd8\u6c70\u7684\u65f6\u5019\uff0c\u76f4\u63a5\u53bb\u6bd4\u8f83\u8fd9\u4e2a\u6b21\u6570\uff0c\u6b21\u6570\u8d8a\u5c11\u7684\u8d8a\u5bb9\u6613\u6dd8\u6c70\uff01<\/p>\n<h4>7.4.1 LFU\u7684\u65f6\u6548\u6027\u95ee\u9898<\/h4>\n<p>\u4f55\u4e3a\u65f6\u6548\u6027\u95ee\u9898\uff1f\u5c31\u662f\u53ea\u4f1a\u53bb\u8003\u8651\u6570\u91cf\uff0c\u4f46\u662f\u4e0d\u4f1a\u53bb\u8003\u8651\u65f6\u95f4\u3002<\/p>\n<p>ps\uff1a\u53bb\u5e74\u7684\u67d0\u4e2a\u65b0\u95fb\u5f88\u706b\uff0c\u70b9\u51fb\u91cf3000W\uff0c\u4eca\u5e74\u6709\u4e2a\u65b0\u95fb\u521a\u51fa\u6765\u70b9\u51fb\u91cf100\u6b21\uff0c\u672c\u6765\u6211\u4eec\u662f\u60f3\u4fdd\u7559\u4eca\u5e74\u7684\u65b0\u7684\u65b0\u95fb\u7684\uff0c\u4f46\u662f\u5982\u679c\u6839\u636eLFU\u6765\u505a\u7684\u8bdd\uff0c\u6211\u4eec\u53d1\u73b0\u6dd8\u6c70\u7684\u662f\u4eca\u5e74\u7684\u65b0\u95fb\uff0c\u660e\u663e\u662f\u4e0d\u5408\u7406\u7684<\/p>\n<p>\u5bfc\u81f4\u7684\u95ee\u9898\uff1a\u65b0\u7684\u6570\u636e\u8fdb\u4e0d\u53bb\uff0c\u65e7\u7684\u6570\u636e\u51fa\u4e0d\u6765\u3002<\/p>\n<p>\u90a3\u4e48\u5982\u4f55\u89e3\u51b3\u5462\uff0c\u4e14\u5f80\u4e0b\u770b<\/p>\n<h4>7.4.2 \u6e90\u7801\u5206\u6790<\/h4>\n<p>\u6211\u4eec\u8fd8\u662f\u6765\u770bredisObject(server.h)<\/p>\n<pre>typedef struct redisObject {\n    unsigned type:4;\n    unsigned encoding:4;\n    unsigned lru:LRU_BITS; \/* LRU time (relative to global\n    lru_clock) or\n    * LFU data (least significant 8 bits frequency\n    * and most significant 16 bits access time). *\/\n    int refcount;\n    void *ptr;\n} robj;<\/pre>\n<p>\u6211\u4eec\u770b\u5b83\u7684lru\uff0c\u5b83\u5982\u679c\u5728LFU\u7b97\u6cd5\u7684\u65f6\u5019\uff01\u5b83\u524d\u976216\u4f4d\u4ee3\u8868\u7684\u662f\u65f6\u95f4\uff0c\u540e8\u4f4d\u4ee3\u8868\u7684\u662f\u4e00\u4e2a\u6570\u503c\uff0cfrequency\u662f\u9891\u7387\uff0c\u5e94\u8be5\u5c31\u662f\u4ee3\u8868\u8fd9\u4e2a\u5bf9\u8c61\u7684\u8bbf\u95ee\u6b21\u6570\uff0c\u6211\u4eec\u5148\u7ed9\u5b83\u53eb\u505acounter\u3002<\/p>\n<p>\u524d16bits\u65f6\u95f4\u6709\u5565\u7528?<\/p>\n<p>\u8ddf\u65f6\u95f4\u76f8\u5173\uff0c\u6211\u731c\u60f3\u5e94\u8be5\u662f\u8ddf\u89e3\u51b3\u65f6\u6548\u6027\u76f8\u5173\u7684\uff0c\u90a3\u4e48\u600e\u4e48\u89e3\u51b3\u7684\uff1f\u4ece\u751f\u6d3b\u4e2d\u627e\u4f8b\u5b50<\/p>\n<p>\u5927\u5bb6\u5e94\u8be5\u5145\u8fc7\u4e00\u4e9b\u4f1a\u5458\uff0c\u6bd4\u5982\u6211\u8fd9\u4e2a\u5e74\u7eaa\u7684\uff0c\u5c0f\u65f6\u5019\u559c\u6b22\u5145\u817e\u8baf\u7684\u9ec4\u94bb\u3001\u7eff\u94bb\u3001\u84dd\u94bb\u7b49\u7b49\u3002\u4f46\u662f\u6709\u4e00\u4e2a\u70b9\uff0c\u5047\u5982\u54ea\u5929\u6211\u6ca1\u5145\u94b1\u4e86\u7684\u8bdd\uff0c\u6216\u8005\u6ca1\u6709\u7eedVIP\u7684\u65f6\u5019\uff0c\u6211\u8fd9\u4e2a\u94bb\u77f3\u7b49\u7ea7\u4f1a\u968f\u7740\u65f6\u95f4\u7684\u6d41\u5931\u800c\u964d\u4f4e\u3002\u6bd4\u5982\u6211\u672c\u6765\u662f\u9ec4\u94bbV6\uff0c\u4f46\u662f\u4e00\u5e74\u4e0d\u5145\u94b1\u7684\u8bdd\uff0c\u53ef\u80fd\u5c31\u53d8\u6210\u4e86V4\u3002<\/p>\n<p>\u90a3\u4e48\u56de\u5230Redis\uff0c\u5927\u80c6\u7684\u53bb\u731c\u6d4b\uff0c\u90a3\u4e48\u8fd9\u4e2a\u65f6\u95f4\u662f\u4e0d\u662f\u53bb\u8bb0\u5f55\u8fd9\u4e2a\u5bf9\u8c61\u6709\u591a\u4e45\u6ca1\u8bbf\u95ee\u4e86\uff0c\u5982\u679c\u591a\u4e45\u6ca1\u8bbf\u95ee\uff0c\u6211\u5c31\u53bb\u51cf\u5c11\u5bf9\u5e94\u7684\u6b21\u6570\u3002<\/p>\n<p>LFUDecrAndReturn\u65b9\u6cd5\uff08evict.c\uff09<\/p>\n<pre>unsigned long LFUDecrAndReturn(robj *o) {\n    \/\/lru\u5b57\u6bb5\u53f3\u79fb8\u4f4d\uff0c\u5f97\u5230\u524d\u976216\u4f4d\u7684\u65f6\u95f4\n    unsigned long ldt = o-&gt;lru &gt;&gt; 8;\n    \/\/lru\u5b57\u6bb5\u4e0e255\u8fdb\u884c&amp;\u8fd0\u7b97\uff08255\u4ee3\u88688\u4f4d\u7684\u6700\u5927\u503c\uff09\uff0c\n    \/\/\u5f97\u52308\u4f4dcounter\u503c\n    unsigned long counter = o-&gt;lru &amp; 255;\n    \/\/\u5982\u679c\u914d\u7f6e\u4e86lfu_decay_time\uff0c\u7528LFUTimeElapsed(ldt) \u9664\u4ee5\u914d\u7f6e\u7684\u503c\n    \/\/LFUTimeElapsed(ldt)\u6e90\u7801\u89c1\u4e0b\n    \/\/\u603b\u7684\u6ca1\u8bbf\u95ee\u7684\u5206\u949f\u65f6\u95f4\/\u914d\u7f6e\u503c\uff0c\u5f97\u5230\u6bcf\u5206\u949f\u6ca1\u8bbf\u95ee\u8870\u51cf\u591a\u5c11\n    unsigned long num_periods = server.lfu_decay_time ?LFUTimeElapsed(ldt) \/ server.lfu_decay_time : 0;\n    if (num_periods)\n    \/\/\u4e0d\u80fd\u51cf\u5c11\u4e3a\u8d1f\u6570\uff0c\u975e\u8d1f\u6570\u7528couter\u503c\u51cf\u53bb\u8870\u51cf\u503c\n    counter = (num_periods &gt; counter) ? 0 : counter - num_periods;\n    return counter;\n}<\/pre>\n<p>\u8870\u51cf\u56e0\u5b50\u7531\u914d\u7f6e<\/p>\n<pre>lfu-decay-time 1 \/\/\u591a\u5c11\u5206\u949f\u6ca1\u64cd\u4f5c\u8bbf\u95ee\u5c31\u53bb\u8870\u51cf\u4e00\u6b21<\/pre>\n<p>\u540e8bits\u7684\u6b21\u6570\uff0c\u6700\u5927\u503c\u662f255\uff0c\u591f\u4e0d\u591f?<\/p>\n<p>\u80af\u5b9a\u4e0d\u591f\uff0c\u4e00\u4e2a\u5bf9\u8c61\u7684\u8bbf\u95ee\u64cd\u4f5c\u6b21\u6570\u80af\u5b9a\u4e0d\u6b62255\u6b21\u3002<\/p>\n<p>\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u8ba9\u6570\u636e\u8fbe\u5230255\u7684\u5f88\u96be\u3002\u90a3\u4e48\u600e\u4e48\u505a\u7684\uff1f\u8fd9\u4e2a\u6bd4\u8f83\u7b80\u5355\uff0c\u6211\u4eec\u5148\u770b\u6e90\u7801\uff0c\u7136\u540e\u518d\u603b\u7ed3<\/p>\n<p>LFULogIncr\u65b9\u6cd5 \uff08evict.c \u6587\u4ef6\uff09<\/p>\n<pre>uint8_t LFULogIncr(uint8_t counter) {\n    \/\/\u5982\u679c\u5df2\u7ecf\u5230\u6700\u5927\u503c255\uff0c\u8fd4\u56de255 \uff0c8\u4f4d\u7684\u6700\u5927\u503c\n    if (counter == 255) return 255;\n    \/\/\u5f97\u5230\u968f\u673a\u6570\uff080-1\uff09\n    double r = (double)rand()\/RAND_MAX;\n    \/\/LFU_INIT_VAL\u8868\u793a\u57fa\u6570\u503c\uff08\u5728server.h\u914d\u7f6e\uff09\n    double baseval = counter - LFU_INIT_VAL;\n    \/\/\u5982\u679c\u8fbe\u4e0d\u5230\u57fa\u6570\u503c\uff0c\u8868\u793a\u5feb\u4e0d\u884c\u4e86\uff0cbaseval =0\n    if (baseval \n<h2>\u516b\u3001Redis \u6301\u4e45\u5316<\/h2>\n<h3>8.1 RBD<\/h3>\n<h4>8.1.1 \u4f55\u65f6\u89e6\u53d1RBD<\/h4>\n<p>\u81ea\u52a8\u89e6\u53d1<\/p>\n\n    \n  \n  \n  \n  \n  \n  \n  <ol>\n     \n   \n   \n   \n   \n   \n   \n   <li>\u914d\u7f6e\u89e6\u53d1<\/li>\n    \n  \n  \n  \n  \n  \n  \n  <\/ol><pre>save 900 1 900s\u68c0\u67e5\u4e00\u6b21\uff0c\u81f3\u5c11\u67091\u4e2akey\u88ab\u4fee\u6539\u5c31\u89e6\u53d1\nsave 300 10 300s\u68c0\u67e5\u4e00\u6b21\uff0c\u81f3\u5c11\u670910\u4e2akey\u88ab\u4fee\u6539\u5c31\u89e6\u53d1\nsave 60 10000 60s\u68c0\u67e5\u4e00\u6b21\uff0c\u81f3\u5c11\u670910000\u4e2akey\u88ab\u4fee\u6539<\/pre>\n<ol>\n<li>shutdown\u6b63\u5e38\u5173\u95ed<\/li>\n<\/ol>\n<p>\u4efb\u4f55\u7ec4\u4ef6\u5728\u6b63\u5e38\u5173\u95ed\u7684\u65f6\u5019\uff0c\u90fd\u4f1a\u53bb\u5b8c\u6210\u5e94\u8be5\u5b8c\u6210\u7684\u4e8b\u3002\u6bd4\u5982Mysql \u4e2d\u7684Redolog\u6301\u4e45\u5316\uff0c\u6b63\u5e38\u5173\u95ed\u7684\u65f6\u5019\u4e5f\u4f1a\u53bb\u6301\u4e45\u5316\u3002<\/p>\n<ol>\n<li>flushall\u6307\u4ee4\u89e6\u53d1<\/li>\n<\/ol>\n<p>\u6570\u636e\u6e05\u7a7a\u6307\u4ee4\u4f1a\u89e6\u53d1RDB\u64cd\u4f5c\uff0c\u5e76\u4e14\u662f\u89e6\u53d1\u4e00\u4e2a\u7a7a\u7684RDB\u6587\u4ef6\uff0c\u6240\u4ee5\uff0c \u5982\u679c\u5728\u6ca1\u6709\u5f00\u542f\u5176\u4ed6\u7684\u6301\u4e45\u5316\u7684\u65f6\u5019\uff0cflushall\u662f\u53ef\u4ee5\u5220\u5e93\u8dd1\u8def\u7684\uff0c\u5728\u751f\u4ea7\u73af\u5883\u614e\u7528\u3002<\/p>\n<h4>8.1.2 RDB\u7684\u4f18\u52a3<\/h4>\n<p>\u4f18\u52bf<\/p>\n<ol>\n<li>\u662f\u4e2a\u975e\u5e38\u7d27\u51d1\u578b\u7684\u6587\u4ef6\uff0c\u975e\u5e38\u9002\u5408\u5907\u4efd\u4e0e\u707e\u96be\u6062\u590d<\/li>\n<li>\u6700\u5927\u9650\u5ea6\u7684\u63d0\u5347\u4e86\u6027\u80fd\uff0c\u4f1afork\u4e00\u4e2a\u5b50\u8fdb\u7a0b\uff0c\u7236\u8fdb\u7a0b\u6c38\u8fdc\u4e0d\u4f1a\u4ea7\u4e8e\u78c1\u76d8 IO\u6216\u8005\u7c7b\u4f3c\u64cd\u4f5c<\/li>\n<li>\u66f4\u5feb\u7684\u91cd\u542f<\/li>\n<\/ol>\n<p>\u4e0d\u8db3<\/p>\n<ol>\n<li>\u6570\u636e\u5b89\u5168\u6027\u4e0d\u662f\u5f88\u9ad8\uff0c\u56e0\u4e3a\u662f\u6839\u636e\u914d\u7f6e\u7684\u65f6\u95f4\u6765\u5907\u4efd\uff0c\u5047\u5982\u6bcf5\u5206\u949f\u5907\u4efd \u4e00\u6b21\uff0c\u4e5f\u4f1a\u67095\u5206\u949f\u6570\u636e\u7684\u4e22\u5931<\/li>\n<li>\u7ecf\u5e38fork\u5b50\u8fdb\u7a0b\uff0c\u6240\u4ee5\u6bd4\u8f83\u8017CPU\uff0c\u5bf9CPU\u4e0d\u662f\u5f88\u53cb\u597d<\/li>\n<\/ol>\n<h3>8.2 AOF<\/h3>\n<p>\u7531\u4e8eRDB\u7684\u6570\u636e\u53ef\u9760\u6027\u975e\u5e38\u4f4e\uff0c\u6240\u4ee5Redis\u53c8\u63d0\u4f9b\u4e86\u53e6\u5916\u4e00\u79cd\u6301\u4e45\u5316\u65b9\u6848\uff1a Append Only File \u7b80\u79f0\uff1aAOF<\/p>\n<p>AOF\u9ed8\u8ba4\u662f\u5173\u95ed\u7684\uff0c\u4f60\u53ef\u4ee5\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u8fdb\u884c\u5f00\u542f\uff1a<\/p>\n<pre>appendonly no \/\/\u9ed8\u8ba4\u5173\u95ed\uff0c\u53ef\u4ee5\u8fdb\u884c\u5f00\u542f\n# The name of the append only file (default:\"appendonly.aof\")\nappendfilename \"appendonly.aof\" \/\/AOF\u6587\u4ef6\u540d<\/pre>\n<p>\u8ffd\u52a0\u6587\u4ef6\uff0c\u5373\u6bcf\u6b21\u66f4\u6539\u7684\u547d\u4ee4\u90fd\u4f1a\u9644\u52a0\u5230\u6211\u7684AOF\u6587\u4ef6\u4e2d\u3002<\/p>\n<h4>8.2.1 \u540c\u6b65\u673a\u5236<\/h4>\n<p>AOF\u4f1a\u8bb0\u5f55\u6bcf\u4e2a\u5199\u64cd\u4f5c\uff0c\u90a3\u4e48\u95ee\u9898\u6765\u4e86\u3002\u6211\u96be\u9053\u6bcf\u6b21\u64cd\u4f5c\u547d\u4ee4\u90fd\u8981\u548c\u78c1\u76d8\u4ea4\u4e92\uff1f<\/p>\n<p>\u5f53\u7136\u4e0d\u884c\uff0c\u6240\u4ee5redis\u652f\u6301\u51e0\u79cd\u7b56\u7565\uff0c\u7531\u7528\u6237\u6765\u51b3\u5b9a\u8981\u4e0d\u8981\u6bcf\u6b21\u90fd\u548c\u78c1\u76d8\u4ea4\u4e92<\/p>\n<pre># appendfsync always \u8868\u793a\u6bcf\u6b21\u5199\u5165\u90fd\u6267\u884cfsync(\u5237\u65b0)\u51fd\u6570 \u6027\u80fd\u4f1a\u975e\u5e38\u975e\u5e38\u6162 \u4f46\u662f\u975e\u5e38\u5b89\u5168\nappendfsync everysec \u6bcf\u79d2\u6267\u884c\u4e00\u6b21fsync\u51fd\u6570 \u53ef\u80fd\u4e22\u59311s\u7684\u6570\u636e\n# appendfsync no \u7531\u64cd\u4f5c\u7cfb\u7edf\u4fdd\u8bc1\u6570\u636e\u540c\u6b65\u5230\u78c1\u76d8\uff0c\u901f\u5ea6\u6700\u5feb \u4f60\u7684\u6570\u636e\u53ea\u9700\u8981\u4ea4\u7ed9\u64cd\u4f5c\u7cfb\u7edf\u5c31\u884c<\/pre>\n<p>\u9ed8\u8ba41s\u4e00\u6b21\uff0c\u6700\u591a\u67091s\u4e22\u5931<\/p>\n<h4>8.2.2 \u91cd\u5199\u673a\u5236<\/h4>\n<p>\u7531\u4e8eAOF\u662f\u8ffd\u52a0\u7684\u5f62\u5f0f\uff0c\u6240\u4ee5\u6587\u4ef6\u4f1a\u8d8a\u6765\u8d8a\u5927\uff0c\u8d8a\u5927\u7684\u8bdd\uff0c\u6570\u636e\u52a0\u8f7d\u8d8a\u6162\u3002 \u6240\u4ee5\u6211\u4eec\u9700\u8981\u5bf9AOF\u6587\u4ef6\u8fdb\u884c\u91cd\u5199\u3002<\/p>\n<p><strong>\u4f55\u4e3a\u91cd\u5199<\/strong><\/p>\n<p>\u6bd4\u5982 \u6211\u4eec\u7684incr\u6307\u4ee4\uff0c\u5047\u5982\u6211\u4eecincr\u4e86100\u6b21\uff0c\u73b0\u5728\u6570\u636e\u662f100\uff0c\u4f46\u662f\u6211\u4eec\u7684aof\u6587\u4ef6\u4e2d\u4f1a\u6709100\u6761incr\u6307\u4ee4\uff0c\u4f46\u662f\u6211\u4eec\u53d1\u73b0\u8fd9\u4e2a100\u6761\u6307\u4ee4\u7528\u5904\u4e0d\u5927\uff0c \u5047\u5982\u6211\u4eec\u80fd\u628a\u6700\u65b0\u7684\u5185\u5b58\u91cc\u7684\u6570\u636e\u4fdd\u5b58\u4e0b\u6765\u7684\u8bdd\u3002\u6240\u4ee5\uff0c\u91cd\u5199\u5c31\u662f\u505a\u4e86\u8fd9\u4e48\u4e00\u4ef6\u4e8b\u60c5\uff0c\u628a\u5f53\u524d\u5185\u5b58\u7684\u6570\u636e\u91cd\u5199\u4e0b\u6765\uff0c\u7136\u540e\u628a\u4e4b\u524d\u7684\u8ffd\u52a0\u7684\u6587\u4ef6\u5220\u9664\u3002<\/p>\n<p><strong>\u91cd\u5199\u6d41\u7a0b<\/strong><\/p>\n<ul>\n<li><strong>\u5728Redis7\u4e4b\u524d<\/strong><\/li>\n<\/ul>\n<ol>\n<li>Redis fork\u4e00\u4e2a\u5b50\u8fdb\u7a0b\uff0c\u5728\u4e00\u4e2a\u4e34\u65f6\u6587\u4ef6\u4e2d\u5199\u5165\u65b0\u7684AOF\uff08\u5f53\u524d\u5185\u5b58\u7684\u6570\u636e\u751f\u6210\u7684\u65b0\u7684AOF\uff09<\/li>\n<li>\u90a3\u4e48\u5728\u5199\u5165\u65b0\u7684AOF\u7684\u65f6\u5019\uff0c\u4e3b\u8fdb\u7a0b\u8fd8\u4f1a\u6709\u6307\u4ee4\u8fdb\u5165\uff0c\u90a3\u4e48\u4e3b\u8fdb\u7a0b\u4f1a\u5728\u5185\u5b58\u7f13\u5b58\u533a\u4e2d\u7d2f\u8ba1\u65b0\u7684\u6307\u4ee4 \uff08\u4f46\u662f\u540c\u65f6\u4e5f\u4f1a\u5199\u5728\u65e7\u7684AOF\u6587\u4ef6\u4e2d\uff0c\u5c31\u7b97 \u91cd\u5199\u5931\u8d25\uff0c\u4e5f\u4e0d\u4f1a\u5bfc\u81f4AOF\u635f\u574f\u6216\u8005\u6570\u636e\u4e22\u5931\uff09<\/li>\n<li>\u5982\u679c\u5b50\u8fdb\u7a0b\u91cd\u5199\u5b8c\u6210\uff0c\u7236\u8fdb\u7a0b\u4f1a\u6536\u5230\u5b8c\u6210\u4fe1\u53f7\uff0c\u5e76\u4e14\u628a\u5185\u5b58\u7f13\u5b58\u4e2d\u7684\u6307\u4ee4\u8ffd\u52a0\u5230\u65b0\u7684AOF\u6587\u4ef6\u4e2d<\/li>\n<li>\u66ff\u6362\u65e7\u7684AOF\u6587\u4ef6 \uff0c\u5e76\u4e14\u5c06\u65b0\u7684\u6307\u4ee4\u9644\u52a0\u5230\u91cd\u5199\u597d\u7684AOF\u6587\u4ef6\u4e2d<\/li>\n<\/ol>\n<ul>\n<li><strong>\u5728Redis7\u4e4b\u540e\uff0cAOF\u6587\u4ef6\u4e0d\u518d\u662f\u4e00\u4e2a\uff0c\u6240\u4ee5\u4f1a\u6709\u4e34\u65f6\u6e05\u5355\u7684\u6982\u5ff5<\/strong><\/li>\n<\/ul>\n<ol>\n<li>\u5b50\u8fdb\u7a0b\u5f00\u59cb\u5728\u4e00\u4e2a\u4e34\u65f6\u6587\u4ef6\u4e2d\u5199\u5165\u65b0\u7684\u57fa\u7840AOF<\/li>\n<li>\u7236\u7ea7\u6253\u5f00\u4e00\u4e2a\u65b0\u7684\u589e\u91cf AOF \u6587\u4ef6\u4ee5\u7ee7\u7eed\u5199\u5165\u66f4\u65b0\u3002\u5982\u679c\u91cd\u5199\u5931\u8d25\uff0c\u65e7\u7684\u57fa\u7840\u548c\u589e\u91cf\u6587\u4ef6\uff08\u5982\u679c\u6709\u7684\u8bdd\uff09\u52a0\u4e0a\u8fd9\u4e2a\u65b0\u6253\u5f00\u7684\u589e\u91cf\u6587\u4ef6\u5c31\u4ee3\u8868\u4e86\u5b8c\u6574\u7684\u66f4\u65b0\u6570\u636e\u96c6\uff0c\u6240\u4ee5\u6211\u4eec\u662f\u5b89\u5168\u7684<\/li>\n<li>\u5f53\u5b50\u8fdb\u7a0b\u5b8c\u6210\u57fa\u7840\u6587\u4ef6\u7684\u91cd\u5199\u540e\uff0c\u7236\u8fdb\u7a0b\u6536\u5230\u4e00\u4e2a\u4fe1\u53f7\uff0c\u5e76\u4f7f\u7528\u65b0\u6253\u5f00 \u7684\u589e\u91cf\u6587\u4ef6\u548c\u5b50\u8fdb\u7a0b\u751f\u6210\u7684\u57fa\u7840\u6587\u4ef6\u6765\u6784\u5efa\u4e34\u65f6\u6e05\u5355\uff0c\u5e76\u5c06\u5176\u6301\u4e45\u5316<\/li>\n<li>\u73b0\u5728 Redis \u5bf9\u6e05\u5355\u6587\u4ef6\u8fdb\u884c\u539f\u5b50\u4ea4\u6362\uff0c\u4ee5\u4fbf\u6b64 AOF \u91cd\u5199\u7684\u7ed3\u679c\u751f\u6548\u3002 Redis \u8fd8\u4f1a\u6e05\u7406\u65e7\u7684\u57fa\u7840\u6587\u4ef6\u548c\u4efb\u4f55\u672a\u4f7f\u7528\u7684\u589e\u91cf\u6587\u4ef6<\/li>\n<\/ol>\n<p>\u4f46\u662f\u91cd\u5199\u662f\u628a\u5f53\u524d\u5185\u5b58\u7684\u6570\u636e\uff0c\u5199\u5165\u4e00\u4e2a\u65b0\u7684AOF\u6587\u4ef6\uff0c\u5982\u679c\u5f53\u524d\u6570\u636e\u6bd4\u8f83\u5927\uff0c\u7136\u540e\u4ee5\u6307\u4ee4\u7684\u5f62\u5f0f\u5199\u5165\u7684\u8bdd\uff0c\u4f1a\u5f88\u6162\u5f88\u6162<\/p>\n<p>\u6240\u4ee5\u57284.0\u4e4b\u540e\uff0c\u5728\u91cd\u5199\u7684\u65f6\u5019\u662f\u91c7\u7528RDB\u7684\u65b9\u5f0f\u53bb\u751f\u6210\u65b0\u7684AOF\u6587\u4ef6\uff0c\u7136 \u540e\u540e\u7eed\u8ffd\u52a0\u7684\u6307\u4ee4\uff0c\u8fd8\u662f\u4ee5\u6307\u4ee4\u8ffd\u52a0\u7684\u5f62\u5f0f\u8ffd\u52a0\u7684\u6587\u4ef6\u672b\u5c3e<\/p>\n<\/p>\n<pre>aof-use-rdb-preamble yes \/\/\u662f\u5426\u5f00\u542fRDB\u4e0eAOF\u6df7\u5408\u6a21\u5f0f<\/pre>\n<p>\u4ec0\u4e48\u65f6\u5019\u91cd\u5199<\/p>\n<p>\u914d\u7f6e\u6587\u4ef6redis.conf<\/p>\n<pre># \u91cd\u5199\u89e6\u53d1\u673a\u5236\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb \u5c31\u7b97\u8fbe\u5230\u4e86\u7b2c\u4e00\u4e2a\u767e\u5206\u6bd4\u7684\u5927\u5c0f\uff0c\u4e5f\u5fc5\u987b\u5927\u4e8e 64M\n\n\u5728 aof \u6587\u4ef6\u5c0f\u4e8e64mb\u7684\u65f6\u5019\u4e0d\u8fdb\u884c\u91cd\u5199\uff0c\u5f53\u5230\u8fbe64mb\u7684\u65f6\u5019\uff0c\u5c31\u91cd\u5199\u4e00\n\u6b21\u3002\u91cd\u5199\u540e\u7684 aof \u6587\u4ef6\u53ef\u80fd\u662f40mb\u3002\u4e0a\u9762\u914d\u7f6e\u4e86auto-aof-rewritepercentag\u4e3a100\uff0c\u5373 aof \u6587\u4ef6\u5230\u4e8680mb\u7684\u65f6\u5019\uff0c\u8fdb\u884c\u91cd\u5199\u3002<\/pre>\n<h4>8.2.3 AOF\u7684\u4f18\u52bf\u4e0e\u4e0d\u8db3<\/h4>\n<p><strong>\u4f18\u52bf<\/strong><\/p>\n<ol>\n<li>\u5b89\u5168\u6027\u9ad8\uff0c\u5c31\u7b97\u662f\u9ed8\u8ba4\u7684\u6301\u4e45\u5316\u540c\u6b65\u673a\u5236\uff0c\u4e5f\u6700\u591a\u53ea\u4f1a\u4e22\u59311s\u6570\u636e<\/li>\n<li>AOF\u7531\u4e8e\u67d0\u4e9b\u539f\u56e0\uff0c\u6bd4\u5982\u78c1\u76d8\u6ee1\u4e86\u7b49\u5bfc\u81f4\u8ffd\u52a0\u5931\u8d25\uff0c\u4e5f\u80fd\u901a\u8fc7redischeck-aof \u5de5\u5177\u6765\u4fee\u590d<\/li>\n<li>\u683c\u5f0f\u90fd\u662f\u8ffd\u52a0\u7684\u65e5\u5fd7\uff0c\u6240\u4ee5\u53ef\u8bfb\u6027\u66f4\u9ad8<\/li>\n<\/ol>\n<p><strong>\u4e0d\u8db3<\/strong><\/p>\n<ol>\n<li>\u6570\u636e\u96c6\u4e00\u822c\u6bd4RDB\u5927<\/li>\n<li>\u6301\u4e45\u5316\u8ddf\u6570\u636e\u52a0\u8f7d\u6bd4RDB\u66f4\u6162<\/li>\n<li>\u57287.0\u4e4b\u524d\uff0c\u91cd\u5199\u7684\u65f6\u5019\uff0c\u56e0\u4e3a\u91cd\u5199\u7684\u65f6\u5019\uff0c\u65b0\u7684\u6307\u4ee4\u4f1a\u7f13\u5b58\u5728\u5185\u5b58\u533a\uff0c\u6240\u4ee5\u4f1a\u5bfc\u81f4\u5927\u91cf\u7684\u5185\u5b58\u4f7f\u7528<\/li>\n<li>\u5e76\u4e14\u91cd\u5199\u671f\u95f4\uff0c\u4f1a\u8ddf\u78c1\u76d8\u8fdb\u884c2\u6b21IO\uff0c\u4e00\u4e2a\u662f\u5199\u5165\u8001\u7684AOF\u6587\u4ef6\uff0c\u4e00\u4e2a\u662f\u5199\u5165\u65b0\u7684AOF\u6587\u4ef6<\/li>\n<\/ol>\n<h2>\u4e5d\u3001Redis\u5e38\u89c1\u95ee\u9898\u603b\u7ed3<\/h2>\n<h3>9.1 Redis\u6570\u636e\u4e22\u5931\u573a\u666f<\/h3>\n<h4>9.1.1 \u6301\u4e45\u5316\u4e22\u5931<\/h4>\n<p>\u91c7\u7528RDB\u6216\u8005\u4e0d\u6301\u4e45\u5316\uff0c \u4f1a\u6709\u6570\u636e\u4e22\u5931\uff0c\u56e0\u4e3a\u662f\u624b\u52a8\u6216\u8005\u914d\u7f6e\u4ee5\u5feb\u7167\u7684\u5f62\u5f0f\u6765\u8fdb\u884c\u5907\u4efd\u3002<\/p>\n<p>\u89e3\u51b3\uff1a\u542f\u7528AOF\uff0c\u4ee5\u547d\u4ee4\u8ffd\u52a0\u7684\u5f62\u5f0f\u8fdb\u884c\u5907\u4efd\uff0c\u4f46\u662f\u9ed8\u8ba4\u4e5f\u4f1a\u67091s\u4e22\u5931\uff0c \u8fd9\u662f\u5728\u6027\u80fd\u4e0e\u6570\u636e\u5b89\u5168\u6027\u4e2d\u5bfb\u6c42\u7684\u4e00\u4e2a\u6700\u9002\u5408\u7684\u65b9\u6848\uff0c\u5982\u679c\u4e3a\u4e86\u4fdd\u8bc1\u6570\u636e \u4e00\u81f4\u6027\uff0c\u53ef\u4ee5\u5c06\u914d\u7f6e\u66f4\u6539\u4e3aalways\uff0c\u4f46\u662f\u6027\u80fd\u5f88\u6162\uff0c\u4e00\u822c\u4e0d\u7528\u3002<\/p>\n<h4>9.1.2 \u4e3b\u4ece\u5207\u6362<\/h4>\n<p>\u56e0\u4e3aRedis\u7684\u6570\u636e\u662f\u4e3b\u5f02\u6b65\u540c\u6b65\u7ed9\u4ece\u7684\uff0c\u63d0\u5347\u4e86\u6027\u80fd\uff0c\u4f46\u662f\u7531\u4e8e\u662f\u5f02\u6b65\u540c\u6b65\u5230\u4ece\u3002\u6240\u4ee5\u5b58\u5728\u6570\u636e\u4e22\u5931\u7684\u53ef\u80fd<\/p>\n<ol>\n<li>master\u5199\u5165\u6570\u636ek1 ,\u7531\u4e8e\u662f\u5f02\u6b65\u540c\u6b65\u5230slave\uff0c\u5f53master\u6ca1\u6709\u540c\u6b65\u7ed9slave\u7684\u65f6\u5019\uff0cmaster\u6302\u4e86<\/li>\n<li>slave\u4f1a\u6210\u4e3a\u65b0\u7684master\uff0c\u5e76\u4e14\u6ca1\u6709\u540c\u6b65k1<\/li>\n<li>master\u91cd\u542f\uff0c\u4f1a\u6210\u4e3a\u65b0master\u7684slave\uff0c\u540c\u6b65\u6570\u636e\u4f1a\u6e05\u7a7a\u81ea\u5df1\u7684\u6570\u636e\uff0c\u4ece\u65b0\u7684master\u52a0\u8f7d<\/li>\n<li>k1\u4e22\u5931<\/li>\n<\/ol>\n<h3>9.2 Redis\u7f13\u5b58\u96ea\u5d29\u3001\u7a7f\u900f\u3001\u51fb\u7a7f\u95ee\u9898\u5206\u6790<\/h3>\n<h4>9.2.1 \u7f13\u5b58\u96ea\u5d29<\/h4>\n<p>\u7f13\u5b58\u96ea\u5d29\u5c31\u662fRedis\u7684\u5927\u91cf\u70ed\u70b9\u6570\u636e\u540c\u65f6\u8fc7\u671f\uff08\u5931\u6548)\uff0c\u56e0\u4e3a\u8bbe\u7f6e\u4e86\u76f8\u540c\u7684\u8fc7\u671f\u65f6\u95f4\uff0c\u521a\u597d\u8fd9\u4e2a\u65f6\u5019Redis\u8bf7\u6c42\u7684\u5e76\u53d1\u91cf\u53c8\u5f88\u5927\uff0c\u5c31\u4f1a\u5bfc\u81f4\u6240\u6709\u7684\u8bf7\u6c42\u843d\u5230\u6570\u636e\u5e93\u3002<\/p>\n<ol>\n<li>\u4fdd\u8bc1Redis\u7684\u9ad8\u53ef\u7528\uff0c\u9632\u6b62\u7531\u4e8eRedis\u4e0d\u53ef\u7528\u5bfc\u81f4\u5168\u90e8\u6253\u5230DB<\/li>\n<li>\u52a0\u4e92\u65a5\u9501\u6216\u8005\u4f7f\u7528\u961f\u5217\uff0c\u9488\u5bf9\u540c\u4e00\u4e2akey\u53ea\u5141\u8bb8\u4e00\u4e2a\u7ebf\u7a0b\u5230\u6570\u636e\u5e93\u67e5\u8be2<\/li>\n<li>\u7f13\u5b58\u5b9a\u65f6\u9884\u5148\u66f4\u65b0\uff0c\u907f\u514d\u540c\u65f6\u5931\u6548<\/li>\n<li>\u901a\u8fc7\u52a0\u968f\u673a\u6570\uff0c\u4f7fkey\u5728\u4e0d\u540c\u7684\u65f6\u95f4\u8fc7\u671f<\/li>\n<\/ol>\n<h4>9.2.2 \u7f13\u5b58\u7a7f\u900f<\/h4>\n<p>\u7f13\u5b58\u7a7f\u900f\u662f\u6307\u7f13\u5b58\u548c\u6570\u636e\u5e93\u4e2d\u90fd\u6ca1\u6709\u7684\u6570\u636e\uff0c\u4f46\u662f\u7528\u6237\u4e00\u76f4\u8bf7\u6c42\u4e0d\u5b58\u5728\u7684\u6570\u636e\uff01\u8fd9\u65f6\u7684\u7528\u6237\u5f88\u53ef\u80fd\u5c31\u662f\u653b\u51fb\u8005\uff0c\u6076\u610f\u641e\u4f60\u4eec\u516c\u53f8\u7684\uff0c\u653b\u51fb\u4f1a\u5bfc\u81f4\u6570\u636e\u5e93\u538b\u529b\u8fc7\u5927\u3002<\/p>\n<p>\u89e3\u51b3\u65b9\u6848\uff1a\u5e03\u9686\u8fc7\u6ee4\u5668<\/p>\n<p>\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u601d\u60f3\uff1a\u65e2\u7136\u662f\u56e0\u4e3a\u4f60Redis\u8ddfDB\u90fd\u6ca1\u6709\uff0c\u7136\u540e\u7528\u6237\u6076\u610f\u4e00\u76f4\u8bbf\u95ee\u4e0d\u5b58\u5728\u7684key\uff0c\u7136\u540e\u5168\u90e8\u6253\u5230Redis\u8ddfDB\u3002\u90a3\u4e48\u6211\u4eec\u80fd\u4e0d\u80fd\u5355\u72ec\u628aDB\u7684\u6570\u636e\u5355\u72ec\u5b58\u5230\u53e6\u5916\u4e00\u4e2a\u5730\u65b9\uff0c\u4f46\u662f\u8fd9\u4e2a\u5730\u65b9\u53ea\u5b58\u4e00\u4e2a\u7b80\u5355\u7684\u6807\u8bb0\uff0c\u6807\u8bb0\u8fd9\u4e2akey\u5b58\u4e0d\u5b58\u5728\uff0c\u5982\u679c\u5b58\u5728\uff0c\u5c31\u53bb\u8bbf\u95eeRedis\u8ddfDB\uff0c\u5426\u5219\u76f4\u63a5\u8fd4\u56de\u3002\u5e76\u4e14\u8fd9\u4e2a\u5185\u5b58\u6700\u597d\u5f88\u5c0f\u3002<\/p>\n<h4>9.2.3 \u7f13\u5b58\u51fb\u7a7f<\/h4>\n<p>\u5355\u4e2akey\u8fc7\u671f\u7684\u65f6\u5019\u6709\u5927\u91cf\u5e76\u53d1\uff0c\u4f7f\u7528\u4e92\u65a5\u9501\uff0c\u56de\u5199redis\uff0c\u5e76\u4e14\u91c7\u7528\u53cc\u91cd\u68c0\u67e5\u9501\u6765\u63d0\u5347\u6027\u80fd\uff01\u51cf\u5c11\u5bf9DB\u7684\u8bbf\u95ee\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u7bc7\u6587\u7ae0\u5e26\u4f60\u5f04\u6e05\u695aRedis\u7684\u7cbe&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[101],"tags":[],"class_list":["post-201609","post","type-post","status-publish","format-standard","hentry","category-database"],"_links":{"self":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/201609","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/comments?post=201609"}],"version-history":[{"count":0,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/201609\/revisions"}],"wp:attachment":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/media?parent=201609"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/categories?post=201609"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/tags?post=201609"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}