{"id":116,"date":"2021-04-29T09:07:51","date_gmt":"2021-04-29T01:07:51","guid":{"rendered":"https:\/\/blog.king011.com\/?p=116"},"modified":"2021-04-29T09:07:54","modified_gmt":"2021-04-29T01:07:54","slug":"%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e7%9a%84%e7%b7%a9%e5%ad%98%e7%94%9f%e6%b4%bb-lru","status":"publish","type":"post","link":"https:\/\/blog.king011.com\/?p=116","title":{"rendered":"\u5f9e\u96f6\u958b\u59cb\u7684\u7de9\u5b58\u751f\u6d3b-LRU"},"content":{"rendered":"\n<p>\u4e0a\u7bc7\u6587\u7ae0\u8a0e\u8ad6\u7684 LFU \u6dd8\u6c70\u7b97\u6cd5\u592a\u904e\u8907\u96dc\uff0c\u4e26\u4e14\u71b1\u9ede\u6578\u64da\u8b8a\u6210\u51b7\u9580\u6578\u64da\u5f8c\u7121\u6cd5\u6709\u6548\u7684\u88ab\u79fb\u9664\uff0c\u7232\u6b64 LRU \u63d0\u4f9b\u4e86\u7c21\u55ae\u4e14\u6709\u6548\u7684\u66ff\u4ee3\u65b9\u6848\u3002\u6700\u8fd1\u6700\u5c11\u4f7f\u7528\u7684\u662f\u51b7\u9580\u6578\u64da\u61c9\u8a72\u88ab\u6dd8\u6c70\uff0c\u6700\u8fd1\u4f7f\u7528\u7684\u6578\u64da\u8ddd\u96e2\u7576\u524d\u6642\u9593\u8d8a\u8fd1\u5b83\u5c31\u8d8a\u71b1\u9580\u3002\u5be6\u73fe\u8d77\u4f86\u4e5f\u7c21\u55ae\u5f88\u591a\u4f7f\u7528\u4e00\u500b\u93c8\u8868\uff0c\u6bcf\u6b21\u4f7f\u7528\u4e86\u6578\u64da\u5c31\u5c07\u5176\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\uff0c\u7de9\u5b58\u6eff\u4e86\u5c31\u522a\u9664\u93c8\u8868\u982d\u7684\u6578\u64da(\u4e00\u76f4\u6c92\u88ab\u8a2a\u554f\u6240\u4ee5\u624d\u6703\u5728\u93c8\u8868\u982d\uff0c\u4e00\u76f4\u6c92\u88ab\u4f7f\u7528\u6240\u4ee5\u5b83\u61c9\u8a72\u662f\u51b7\u9580\u6578\u64da)\uff0c\u800c\u771f\u6b63\u71b1\u9580\u7684\u6578\u64da\u901a\u5e38\u5728\u88ab\u522a\u9664\u524d\u6703\u88ab\u6301\u7e8c\u8a2a\u554f\u6240\u4ee5\u6301\u7e8c\u88ab\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\u59cb\u7d42\u4e0d\u88ab\u522a\u9664\uff0c\u5f9e\u800c\u4fdd\u8b49\u4e86\u7de9\u5b58\u4e2d\u5b58\u5132\u4e86\u6b63\u5728\u71b1\u9580\u7684\u6578\u64da\u800c\u975e\u53ea\u662f\u5982 LFU \u5b58\u5132\u4e86\u66fe\u7d93\u71b1\u9580\u4f46\u7576\u524d\u5df2\u7d93\u8b8a\u5f97\u51b7\u9580\u7684\u6578\u64da\u3002<\/p>\n\n\n\n<p>LRU \u5be6\u73fe\u7c21\u55ae\u6548\u7387\u4e5f\u5f88\u9ad8(\u5be6\u73fe\u96e3\u5ea6\u5e7e\u4e4e\u548c FIFO \u4e00\u6a23\uff0cPut Get Delete \u57f7\u884c\u6642\u9593\u4e5f\u5e7e\u4e4e\u548c FIFO \u7b97\u6cd5\u4e00\u81f4)\uff0c\u6545\u662f\u76ee\u524d\u6700\u5e38\u4f7f\u7528\u7684\u7de9\u5b58\u7b97\u6cd5\u4e4b\u4e00\u3002<\/p>\n\n\n\n<p>LRU \u5be6\u73fe\u4e5f\u548c\u524d\u9762\u6587\u7ae0\u7684 FIFO \u5e7e\u4e4e\u4e00\u81f4\uff0c\u552f\u4e00\u9700\u8981\u505a\u51fa\u4fee\u6539\u7684\u5730\u65b9\u662f Get \u63a5\u53e3\u4e2d\u5c07\u88ab\u8a2a\u554f\u7684\u6578\u64da\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5be6\u73fe LRU<\/h2>\n\n\n\n<p>\u548c FIFO \u4e00\u6a23 LRU \u9700\u8981\u4e09\u500b\u57fa\u672c\u5c6c\u6027\uff0c\u4e00\u500b Map \u7528\u65bc\u5b58\u5132\u7de9\u5b58\uff0c\u4e00\u500b List \u5be6\u73fe\u6dd8\u6c70\u7b97\u6cd5\uff0c\u4e00\u500b capacity \u5b9a\u7fa9\u7de9\u5b58\u5bb9\u91cf\u4e0a\u9650\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u7232\u7de9\u5b58\u6578\u64da\u5b9a\u7fa9\u4e00\u500b\u985e\u578b\ntype cacheValue struct {\n\tKey   interface{}\n\tValue interface{}\n}\n\n\/\/ LRU \u7232\u7de9\u5b58\u5b9a\u7fa9\u4e00\u500b\u81ea\u5b9a\u7fa9\u985e\u578b\ntype LRU struct {\n\t\/\/ \u6b64\u5b57\u6bb5\u8a2d\u7f6e\u7de9\u5b58\u5bb9\u91cf\u4e0a\u9650\n\tcapacity int\n\t\/\/ Map \u7232 \u67e5\u8a62\u7de9\u5b58\u6578\u64da\u63d0\u4f9b \u652f\u6301\n\tkeys map&#91;interface{}]*list.Element\n\t\/\/ \u7de9\u5b58\u6dd8\u6c70\u7b97\u6cd5\u4f7f\u7528 \u6b64\u93c8\u8868\u5be6\u73fe \u6700\u8fd1\u6700\u5c11\u8a2a\u554f\u7684\u5148\u88ab\u6dd8\u6c70\n\thot *list.List\n}\n\n\/\/ \u56e0\u7232golang\u6c92\u6709\u69cb\u9020\u51fd\u6578 \u63d0\u4f9b\u4e00\u500b New \u51fd\u6578 \u5275\u5efa\u7de9\u5b58\nfunc NewLRU(capacity int) *LRU {\n\tif capacity &lt; 1 {\n\t\tpanic(`capacity must &gt; 0`)\n\t}\n\treturn &amp;LRU{\n\t\tcapacity: capacity,\n\t\tkeys:     make(map&#91;interface{}]*list.Element, capacity),\n\t\thot:      list.New(),\n\t}\n}<\/code><\/pre>\n\n\n\n<p>\u5be6\u73fe\u6700\u7c21\u55ae\u7684 Delete \u63a5\u53e3\uff0c\u76f4\u63a5\u5c07 FIFO \u5be6\u73fe\u62f7\u8c9d\u904e\u4f86\u5373\u53ef\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LRU) Delete(key interface{}) {\n\tele, exists := c.keys&#91;key]\n\tif !exists {\n\t\t\/\/ \u7de9\u5b58\u4e0d\u5b58\u5728 \u76f4\u63a5\u8fd4\u56de\u5373\u53ef\n\t\treturn\n\t}\n\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5f9e Map \u548c List \u522a\u9664\u4e4b\n\tdelete(c.keys, key)\n\tc.hot.Remove(ele)\n}<\/code><\/pre>\n\n\n\n<p>\u5be6\u73fe Get \u63a5\u53e3\uff0c\u9996\u5148\u5c07 FIFO \u5be6\u73fe\u62f7\u8c9d\u904e\u6ffe\uff0c\u7136\u5f8c\u4fee\u6539\u4e0b\u5728\u6578\u64da\u5b58\u5728\u6642\u5c07\u5176\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\u5373\u53ef\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LRU) Get(key interface{}) (value interface{}, exists bool) {\n\tele, exists := c.keys&#91;key]\n\tif !exists {\n\t\treturn\n\t}\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5c07\u7de9\u5b58\u8a2d\u7f6e\u7d66\u8fd4\u56de\u503c\n\tv := ele.Value.(cacheValue)\n\tvalue = v.Value\n\t\/\/ \u5c07\u7bc0\u9ede\u79fb\u52d5\u5230\u9023\u63a5\u5c3e\n\tc.hot.MoveToBack(ele)\n\treturn\n}<\/code><\/pre>\n\n\n\n<p>\u5be6\u73fe\u6700\u5f8c\u7684 Put \u63a5\u53e3\uff0c\u76f4\u63a5\u5c07 FIFO \u5be6\u73fe\u62f7\u8c9d\u904e\u4f86\u5373\u53ef\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LRU) Put(key, value interface{}) {\n\tele, exists := c.keys&#91;key]\n\tif exists { \/\/ \u7de9\u5b58\u5b58\u5728 \u66f4\u65b0\u503c \u4e26\u5c07\u5176\u5728\u93c8\u8868\u4e2d\u7684\u4f4d\u7f6e\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\n\t\tele.Value = cacheValue{\n\t\t\tKey:   key,\n\t\t\tValue: value,\n\t\t}\n\t\tc.hot.MoveToBack(ele)\n\t\treturn\n\t}\n\t\/\/ \u4e0d\u5b58\u5728\u9996\u5148\u5224\u65b7\u7de9\u5b58\u662f\u5426\u5df2\u6eff\n\tif len(c.keys) == c.capacity {\n\t\t\/\/ \u7de9\u5b58\u5df2\u6eff \u522a\u9664\u93c8\u8868\u982d\u90e8\u7684\u7de9\u5b58\n\t\tele = c.hot.Front()\n\t\tv := ele.Value.(cacheValue)\n\t\tc.hot.Remove(ele)\n\t\tdelete(c.keys, v.Key)\n\t}\n\n\t\/\/ \u5c07\u65b0\u7de9\u5b58\u5167\u5bb9\u52a0\u5165\n\tele = c.hot.PushBack(cacheValue{\n\t\tKey:   key,\n\t\tValue: value,\n\t})\n\tc.keys&#91;key] = ele\n}<\/code><\/pre>\n\n\n\n<p>\u81f3\u6b64\u6211\u5011\u4fbf\u5b8c\u6210\u4e86 LRU \u7de9\u5b58\u7b97\u6cd5\uff0c\u4e0b\u9762\u4f86\u5beb\u500b\u7c21\u55ae\u7684\u6e2c\u8a66\u793a\u4f8b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package cache\n\nimport \"testing\"\n\nfunc TestLRU(t *testing.T) {\n\t\/\/ \u5b9a\u7fa9\u4e00\u500b\u8f14\u52a9\u51fd\u6578\u6e2c\u8a66\u7de9\u5b58\u4e2d\u5b58\u5728\u7684 key\n\tassertExists := func(t *testing.T, cache *LRU, key ...interface{}) {\n\t\tfor _, k := range key {\n\t\t\t_, exists := cache.keys&#91;k]\n\t\t\tif !exists {\n\t\t\t\tt.Fatalf(\"key not exists : %v\", k)\n\t\t\t}\n\t\t}\n\t}\n\n\tc := NewLRU(3)\n\t\/\/ \u63d2\u5165 3 \u500b\u7de9\u5b58 \u6b64\u6642\u7de9\u5b58\u4e86 key \u7232 0 1 2 \u7684\u6578\u64da\n\tfor i := 0; i &lt; 3; i++ {\n\t\tc.Put(i, i)\n\t}\n\n\t\/\/ \u9a57\u8b49 \u7de9\u5b58\u5b58\u5728\n\tassertExists(t, c, 0, 1, 2)\n\n\t\/\/ \u63d2\u5165 key 3 \u7de9\u5b58\u8b8a\u7232 1 2 3 \uff0ckey \u7232 0 \u7684\u7de9\u5b58\u88ab\u79fb\u9664\n\tc.Put(3, 3)\n\tassertExists(t, c, 1, 2, 3)\n\n\t\/\/ \u8a2a\u554f key 1 \u7de9\u5b58\u8b8a\u7232 2 3 1\n\tc.Get(1)\n\tassertExists(t, c, 1, 2, 3)\n\n\t\/\/ \u63d2\u5165 key 3 \u7de9\u5b58\u8b8a\u7232 3 1 4 \uff0ckey \u7232 2 \u7684\u7de9\u5b58\u88ab\u79fb\u9664\n\tc.Put(4, 4)\n\tassertExists(t, c, 1, 3, 4)\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5b8c\u6574\u4ee3\u78bc<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package cache\n\nimport \"container\/list\"\n\n\/\/ \u7232\u7de9\u5b58\u6578\u64da\u5b9a\u7fa9\u4e00\u500b\u985e\u578b\ntype cacheValue struct {\n\tKey   interface{}\n\tValue interface{}\n}\n\n\/\/ LRU \u7232\u7de9\u5b58\u5b9a\u7fa9\u4e00\u500b\u81ea\u5b9a\u7fa9\u985e\u578b\ntype LRU struct {\n\t\/\/ \u6b64\u5b57\u6bb5\u8a2d\u7f6e\u7de9\u5b58\u5bb9\u91cf\u4e0a\u9650\n\tcapacity int\n\t\/\/ Map \u7232 \u67e5\u8a62\u7de9\u5b58\u6578\u64da\u63d0\u4f9b \u652f\u6301\n\tkeys map&#91;interface{}]*list.Element\n\t\/\/ \u7de9\u5b58\u6dd8\u6c70\u7b97\u6cd5\u4f7f\u7528 \u6b64\u93c8\u8868\u5be6\u73fe \u6700\u8fd1\u6700\u5c11\u8a2a\u554f\u7684\u5148\u88ab\u6dd8\u6c70\n\thot *list.List\n}\n\n\/\/ \u56e0\u7232golang\u6c92\u6709\u69cb\u9020\u51fd\u6578 \u63d0\u4f9b\u4e00\u500b New \u51fd\u6578 \u5275\u5efa\u7de9\u5b58\nfunc NewLRU(capacity int) *LRU {\n\tif capacity &lt; 1 {\n\t\tpanic(`capacity must &gt; 0`)\n\t}\n\treturn &amp;LRU{\n\t\tcapacity: capacity,\n\t\tkeys:     make(map&#91;interface{}]*list.Element, capacity),\n\t\thot:      list.New(),\n\t}\n}\nfunc (c *LRU) Delete(key interface{}) {\n\tele, exists := c.keys&#91;key]\n\tif !exists {\n\t\t\/\/ \u7de9\u5b58\u4e0d\u5b58\u5728 \u76f4\u63a5\u8fd4\u56de\u5373\u53ef\n\t\treturn\n\t}\n\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5f9e Map \u548c List \u522a\u9664\u4e4b\n\tdelete(c.keys, key)\n\tc.hot.Remove(ele)\n}\nfunc (c *LRU) Get(key interface{}) (value interface{}, exists bool) {\n\tele, exists := c.keys&#91;key]\n\tif !exists {\n\t\treturn\n\t}\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5c07\u7de9\u5b58\u8a2d\u7f6e\u7d66\u8fd4\u56de\u503c\n\tv := ele.Value.(cacheValue)\n\tvalue = v.Value\n\t\/\/ \u5c07\u7bc0\u9ede\u79fb\u52d5\u5230\u9023\u63a5\u5c3e\n\tc.hot.MoveToBack(ele)\n\treturn\n}\nfunc (c *LRU) Put(key, value interface{}) {\n\tele, exists := c.keys&#91;key]\n\tif exists { \/\/ \u7de9\u5b58\u5b58\u5728 \u66f4\u65b0\u503c \u4e26\u5c07\u5176\u5728\u93c8\u8868\u4e2d\u7684\u4f4d\u7f6e\u79fb\u52d5\u5230\u93c8\u8868\u5c3e\n\t\tele.Value = cacheValue{\n\t\t\tKey:   key,\n\t\t\tValue: value,\n\t\t}\n\t\tc.hot.MoveToBack(ele)\n\t\treturn\n\t}\n\t\/\/ \u4e0d\u5b58\u5728\u9996\u5148\u5224\u65b7\u7de9\u5b58\u662f\u5426\u5df2\u6eff\n\tif len(c.keys) == c.capacity {\n\t\t\/\/ \u7de9\u5b58\u5df2\u6eff \u522a\u9664\u93c8\u8868\u982d\u90e8\u7684\u7de9\u5b58\n\t\tele = c.hot.Front()\n\t\tv := ele.Value.(cacheValue)\n\t\tc.hot.Remove(ele)\n\t\tdelete(c.keys, v.Key)\n\t}\n\n\t\/\/ \u5c07\u65b0\u7de9\u5b58\u5167\u5bb9\u52a0\u5165\n\tele = c.hot.PushBack(cacheValue{\n\t\tKey:   key,\n\t\tValue: value,\n\t})\n\tc.keys&#91;key] = ele\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">LRU \u7b97\u6cd5\u7684\u554f\u984c<\/h2>\n\n\n\n<p>LRU \u7b97\u6cd5\u80fd\u5920\u5f88\u597d\u7684\u61c9\u5c0d\u5927\u90e8\u5206\u60c5\u6cc1\uff0c\u4f46\u4f9d\u7136\u5b58\u5728\u7740\u7f3a\u9677\uff0c\u6bd4\u5982\u67d0\u4eba\u9806\u5e8f\u8acb\u6c42\u4e00\u6279\u6578\u64da\uff0c\u6bd4\u5982\u8acb\u6c42\u4e86 1 2 3 \u4e09\u500b\u6578\u64da\uff0c\u56e0\u7232\u8acb\u6c42\u8005\u6253\u7b97\u6279\u91cf\u8655\u7406\u9019\u4e9b\u6578\u64da\uff0c\u6b64\u6642 1 2 3 \u5c07\u6703\u5c07\u7de9\u5b58\u4e2d\u7684\u4e09\u500b\u5df2\u5b58\u5728\u7684\u7de9\u5b58\u6dd8\u6c70\u6389\uff0c\u9019\u6642\u5f88\u53ef\u80fd\u5c31\u5c07\u71b1\u9580\u6578\u64da\u6dd8\u6c70\u4e86\uff0c\u4f46 1 2 3 \u88ab\u6279\u91cf\u8acb\u6c42\u5f8c\u53ef\u80fd\u5c31\u4e0d\u518d\u4f7f\u7528\u4e86\u3002<\/p>\n\n\n\n<p>LRU \u5728\u9762\u5c0d\u6279\u91cf\u64cd\u4f5c\u6642\u5f88\u5bb9\u6613\u8b93\u71b1\u9ede\u6578\u64da\u88ab\u6279\u91cf\u6578\u64da\u66ff\u63db\u6389\uff0c\u7232\u6b64 \u884d\u751f\u51fa\u4e86 LRU-K \u7b97\u6cd5\u7528\u65bc\u89e3\u6c7a\u6b64\u554f\u984c\uff0c\u672c\u55b5\u5c07\u5728\u4e0b\u7bc7\u6587\u7ae0\u9032\u884c\u8a0e\u8ad6\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>lru \u7de9\u5b58\u7b97\u6cd5 \u4ecb\u7d39 \u4ee5\u53ca golang \u5be6\u73fe\u793a\u4f8b<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[11,14,2,13],"tags":[21,12,18],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-golang","category-re0-cache","category-code","category-algorithm","tag-cache","tag-golang","tag-lru"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=116"}],"version-history":[{"count":11,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":135,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/116\/revisions\/135"}],"wp:attachment":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}