{"id":201514,"date":"2025-05-10T08:52:31","date_gmt":"2025-05-10T00:52:31","guid":{"rendered":"https:\/\/server.hk\/cnblog\/201514\/"},"modified":"2025-05-10T08:52:31","modified_gmt":"2025-05-10T00:52:31","slug":"redis%e4%b8%adredisson%e5%b8%83%e9%9a%86%e8%bf%87%e6%bb%a4%e5%99%a8%e7%9a%84%e5%ad%a6%e4%b9%a0","status":"publish","type":"post","link":"https:\/\/server.hk\/cnblog\/201514\/","title":{"rendered":"Redis\u4e2dRedisson\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u5b66\u4e60"},"content":{"rendered":"<p><b><\/b> <\/p>\n<h1>Redis\u4e2dRedisson\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u5b66\u4e60<\/h1>\n<p><span style=\"cursor: pointer\"><i><\/i>\u6536\u85cf<\/span> <\/p>\n<p>\u5bf9\u4e8e\u4e00\u4e2a\u6570\u636e\u5e93\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u7262\u56fa\u624e\u5b9e\u7684\u57fa\u7840\u662f\u5341\u5206\u91cd\u8981\u7684\uff0cgolang\u5b66\u4e60\u7f51\u5c31\u6765\u5e26\u5927\u5bb6\u4e00\u70b9\u70b9\u7684\u638c\u63e1\u57fa\u7840\u77e5\u8bc6\u70b9\u3002\u4eca\u5929\u672c\u7bc7\u6587\u7ae0\u5e26\u5927\u5bb6\u4e86\u89e3\u300aRedis\u4e2dRedisson\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u5b66\u4e60\u300b\uff0c\u4e3b\u8981\u4ecb\u7ecd\u4e86\u5e03\u9686\u8fc7\u6ee4\u5668\u3001RedisRedisson\uff0c\u5e0c\u671b\u5bf9\u5927\u5bb6\u7684\u77e5\u8bc6\u79ef\u7d2f\u6709\u6240\u5e2e\u52a9\uff0c\u5feb\u70b9\u6536\u85cf\u8d77\u6765\u5427\uff0c\u5426\u5219\u9700\u8981\u65f6\u5c31\u627e\u4e0d\u5230\u4e86\uff01<\/p>\n<h2>\u7b80\u4ecb<\/h2>\n<p>\u672c\u6587\u57fa\u4e8eSpring Boot 2.6.6\u3001redisson 3.16.0\u7b80\u5355\u5206\u6790Redisson\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u4f7f\u7528\u3002<\/p>\n<p>\u5e03\u9686\u8fc7\u6ee4\u5668\u662f\u4e00\u4e2a\u975e\u5e38\u957f\u7684\u4e8c\u8fdb\u5236\u5411\u91cf\u548c\u4e00\u7cfb\u5217\u968f\u673a\u54c8\u5e0c\u51fd\u6570\u7684\u7ec4\u5408\uff0c\u53ef\u7528\u4e8e\u68c0\u7d22\u4e00\u4e2a\u5143\u7d20\u662f\u5426\u5b58\u5728\uff1b<\/p>\n<p>\u4f7f\u7528\u573a\u666f\u5982\u4e0b\uff1a<\/p>\n<ul>\n<li>\u89e3\u51b3Redis\u7f13\u5b58\u7a7f\u900f\u95ee\u9898\uff1b<\/li>\n<li>\u90ae\u4ef6\u8fc7\u6ee4\uff1b<\/li>\n<\/ul>\n<h2>\u4f7f\u7528<\/h2>\n<ul>\n<li>\u5efa\u7acb\u4e00\u4e2a\u4e8c\u8fdb\u5236\u5411\u91cf\uff0c\u6240\u6709\u4f4d\u8bbe\u7f6e0\uff1b<\/li>\n<li>\u9009\u62e9K\u4e2a\u6563\u5217\u51fd\u6570\uff0c\u7528\u4e8e\u5bf9\u5143\u7d20\u8fdb\u884cK\u6b21\u6563\u5217\uff0c\u8ba1\u7b97\u5411\u91cf\u7684\u4f4d\u4e0b\u6807\uff1b<\/li>\n<li>\u6dfb\u52a0\u5143\u7d20\uff1a\u5c06K\u4e2a\u6563\u5217\u51fd\u6570\u4f5c\u7528\u4e8e\u8be5\u5143\u7d20\uff0c\u751f\u6210K\u4e2a\u503c\u4f5c\u4e3a\u4f4d\u4e0b\u6807\uff0c\u5c06\u5411\u91cf\u7684\u5bf9\u5e94\u4f4d\u8bbe\u7f6e\u4e3a1\uff1b<\/li>\n<li>\u68c0\u7d22\u5143\u7d20\uff1a\u5c06K\u4e2a\u6563\u5217\u51fd\u6570\u4f5c\u7528\u4e8e\u8be5\u5143\u7d20\uff0c\u751f\u6210K\u4e2a\u503c\u4f5c\u4e3a\u4f4d\u4e0b\u6807\uff0c\u82e5\u5411\u91cf\u7684\u5bf9\u5e94\u4f4d\u90fd\u662f1\uff0c\u5219\u8bf4\u660e\u8be5\u5143\u7d20\u53ef\u80fd\u5b58\u5728\uff1b\u5426\u5219\uff0c\u8be5\u5143\u7d20\u80af\u5b9a\u4e0d\u5b58\u5728\uff1b<\/li>\n<\/ul>\n<h2>Demo<\/h2>\n<h3>\u4f9d\u8d56<\/h3>\n<pre>\n   \n    \n     org.springframework.boot\n    \n    \n     spring-boot-starter-data-redis\n    \n    \n     \n      \n       io.lettuce\n      \n      \n       lettuce-core\n      \n     \n    \n   \n   \n    \n     redis.clients\n    \n    \n     jedis\n    \n   \n   \n    \n     org.redisson\n    \n    \n     redisson\n    \n    \n     3.16.0\n    \n   <\/pre>\n<h3>\u6d4b\u8bd5\u4ee3\u7801<\/h3>\n<pre>public class BloomFilterDemo {\n\n&nbsp; &nbsp; public static void main(String[] args) {\n&nbsp; &nbsp; &nbsp; &nbsp; Config config = new Config();\n&nbsp; &nbsp; &nbsp; &nbsp; config.useSingleServer().setAddress(\"redis:\/\/127.0.0.1:6379\");\n&nbsp; &nbsp; &nbsp; &nbsp; RedissonClient redissonClient = Redisson.create(config);\n&nbsp; &nbsp; &nbsp; &nbsp; RBloomFilter\n   \n     bloomFilter = redissonClient.getBloomFilter(\"bloom-filter\");\n&nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u521d\u59cb\u5316\u5e03\u9686\u8fc7\u6ee4\u5668\n&nbsp; &nbsp; &nbsp; &nbsp; bloomFilter.tryInit(200, 0.01);\n\n&nbsp; &nbsp; &nbsp; &nbsp; List\n    \n      elements = new ArrayList(); &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i bloomFilter, List\n     \n       elements) { &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i bloomFilter, List\n      \n        elements) { &nbsp; &nbsp; &nbsp; &nbsp; int counter = 0; &nbsp; &nbsp; &nbsp; &nbsp; for (String element : elements) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (bloomFilter.contains(element)) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(counter); &nbsp; &nbsp; } }\n      \n     \n    \n   <\/pre>\n<h2>\u7b80\u6790<\/h2>\n<h3>\u521d\u59cb\u5316<\/h3>\n<p>\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u521d\u59cb\u5316\u65b9\u6cd5tryInit\u6709\u4e24\u4e2a\u53c2\u6570\uff1a<\/p>\n<ul>\n<li>expectedInsertions\uff1a\u9884\u671f\u7684\u63d2\u5165\u5143\u7d20\u6570\u91cf\uff1b<\/li>\n<li>falseProbability\uff1a\u9884\u671f\u7684\u9519\u8bef\u7387\uff1b<\/li>\n<\/ul>\n<p>\u5e03\u9686\u8fc7\u6ee4\u5668\u53ef\u4ee5\u660e\u786e\u5143\u7d20\u4e0d\u5b58\u5728\uff0c\u4f46\u5bf9\u4e8e\u5143\u7d20\u5b58\u5728\u7684\u5224\u65ad\u662f\u5b58\u5728\u9519\u8bef\u7387\u7684\uff1b\u6240\u4ee5\u521d\u59cb\u5316\u65f6\u6307\u5b9a\u7684\u8fd9\u4e24\u4e2a\u53c2\u6570\u4f1a\u51b3\u5b9a\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u5411\u91cf\u957f\u5ea6\u548c\u6563\u5217\u51fd\u6570\u7684\u4e2a\u6570\uff1b<br \/>RedissonBloomFilter.tryInit\u65b9\u6cd5\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre>public boolean tryInit(long expectedInsertions, double falseProbability) {\n&nbsp; &nbsp; if (falseProbability &gt; 1) {\n&nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException(\"Bloom filter false probability can't be greater than 1\");\n&nbsp; &nbsp; }\n&nbsp; &nbsp; if (falseProbability  getMaxSize()) {\n&nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException(\"Bloom filter size can't be greater than \" + getMaxSize() + \". But calculated size is \" + size);\n&nbsp; &nbsp; }\n&nbsp; &nbsp; \/\/ \u6839\u636e\u5143\u7d20\u4e2a\u6570\u548c\u5411\u91cf\u957f\u5ea6\u8ba1\u7b97\u5f97\u5230\u6563\u5217\u51fd\u6570\u7684\u4e2a\u6570\n&nbsp; &nbsp; hashIterations = optimalNumOfHashFunctions(expectedInsertions, size);\n\n&nbsp; &nbsp; CommandBatchService executorService = new CommandBatchService(commandExecutor);\n&nbsp; &nbsp; executorService.evalReadAsync(configName, codec, RedisCommands.EVAL_VOID,\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"local size = redis.call('hget', KEYS[1], 'size');\" +\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"local hashIterations = redis.call('hget', KEYS[1], 'hashIterations');\" +\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"assert(size == false and hashIterations == false, 'Bloom filter config has been changed')\",\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Arrays.asList(configName), size, hashIterations);\n&nbsp; &nbsp; executorService.writeAsync(configName, StringCodec.INSTANCE,\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new RedisCommand\n    \n     (\"HMSET\", new VoidReplayConvertor()), configName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"size\", size, \"hashIterations\", hashIterations, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"expectedInsertions\", expectedInsertions, \"falseProbability\", BigDecimal.valueOf(falseProbability).toPlainString()); &nbsp; &nbsp; try { &nbsp; &nbsp; &nbsp; &nbsp; executorService.execute(); &nbsp; &nbsp; } catch (RedisException e) { &nbsp; &nbsp; &nbsp; &nbsp; if (e.getMessage() == null || !e.getMessage().contains(\"Bloom filter config has been changed\")) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; readConfig(); &nbsp; &nbsp; &nbsp; &nbsp; return false; &nbsp; &nbsp; } &nbsp; &nbsp; return true; } private long optimalNumOfBits(long n, double p) { &nbsp; &nbsp; if (p == 0) { &nbsp; &nbsp; &nbsp; &nbsp; p = Double.MIN_VALUE; &nbsp; &nbsp; } &nbsp; &nbsp; return (long) (-n * Math.log(p) \/ (Math.log(2) * Math.log(2))); } private int optimalNumOfHashFunctions(long n, long m) { &nbsp; &nbsp; return Math.max(1, (int) Math.round((double) m \/ n * Math.log(2))); }\n    <\/pre>\n<h3>\u6dfb\u52a0\u5143\u7d20<\/h3>\n<p>\u5411\u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\u6dfb\u52a0\u5143\u7d20\u65f6\uff0c\u5148\u4f7f\u7528\u4e00\u7cfb\u5217\u6563\u5217\u51fd\u6570\u6839\u636e\u5143\u7d20\u5f97\u5230K\u4e2a\u4f4d\u4e0b\u6807\uff0c\u7136\u540e\u5c06\u5411\u91cf\u4e2d\u4f4d\u4e0b\u6807\u5bf9\u5e94\u7684\u4f4d\u8bbe\u7f6e\u4e3a1\uff1b<br \/>RedissonBloomFilter.add\u65b9\u6cd5\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre>public boolean add(T object) {\n&nbsp; &nbsp; \/\/ \u6839\u636e\u5e26\u63d2\u5165\u5143\u7d20\u5f97\u5230\u4e24\u4e2along\u7c7b\u578b\u6563\u5217\u503c\n&nbsp; &nbsp; long[] hashes = hash(object);\n\n&nbsp; &nbsp; while (true) {\n&nbsp; &nbsp; &nbsp; &nbsp; if (size == 0) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readConfig();\n&nbsp; &nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; &nbsp; int hashIterations = this.hashIterations;\n&nbsp; &nbsp; &nbsp; &nbsp; long size = this.size;\n\n&nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u5f97\u5230\u4f4d\u4e0b\u6807\u6570\u7ec4\n&nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u4ee5\u4e24\u4e2a\u6563\u5217\u503c\u6839\u636e\u6307\u5b9a\u7b56\u7565\u751f\u6210hashIterations\u4e2a\u6563\u5217\u503c\uff0c\u4ece\u800c\u5f97\u5230\u4f4d\u4e0b\u6807\n&nbsp; &nbsp; &nbsp; &nbsp; long[] indexes = hash(hashes[0], hashes[1], hashIterations, size);\n\n&nbsp; &nbsp; &nbsp; &nbsp; CommandBatchService executorService = new CommandBatchService(commandExecutor);\n&nbsp; &nbsp; &nbsp; &nbsp; addConfigCheck(hashIterations, size, executorService);\n&nbsp; &nbsp; &nbsp; &nbsp; RBitSetAsync bs = createBitSet(executorService);\n&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i  result = (List\n   \n    ) executorService.execute().getResponses();\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (Boolean val : result.subList(1, result.size()-1)) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!val) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u5143\u7d20\u6dfb\u52a0\u6210\u529f\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u5143\u7d20\u5df2\u5b58\u5728\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;\n&nbsp; &nbsp; &nbsp; &nbsp; } catch (RedisException e) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e.getMessage() == null || !e.getMessage().contains(\"Bloom filter config has been changed\")) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; }\n}\n\nprivate long[] hash(Object object) {\n&nbsp; &nbsp; ByteBuf state = encode(object);\n&nbsp; &nbsp; try {\n&nbsp; &nbsp; &nbsp; &nbsp; return Hash.hash128(state);\n&nbsp; &nbsp; } finally {\n&nbsp; &nbsp; &nbsp; &nbsp; state.release();\n&nbsp; &nbsp; }\n}\n\nprivate long[] hash(long hash1, long hash2, int iterations, long size) {\n&nbsp; &nbsp; long[] indexes = new long[iterations];\n&nbsp; &nbsp; long hash = hash1;\n&nbsp; &nbsp; for (int i = 0; i \n\n    <p><code>hash(long hash1, long hash2, int iterations, long size)<\/code>\u65b9\u6cd5\u4e2d\uff0c\u5229\u7528\u6839\u636e\u5143\u7d20\u5f97\u5230\u7684\u4e24\u4e2a\u6563\u5217\u503c\uff0c\u751f\u6210\u4e00\u7cfb\u5217\u6563\u5217\u51fd\u6570\uff0c\u7136\u540e\u5f97\u5230\u4f4d\u4e0b\u6807\u6570\u7ec4\uff1b<\/p>\n\n    <h3>\u68c0\u7d22\u5143\u7d20<\/h3>\n\n    <p>\u68c0\u7d22\u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\u662f\u5426\u5b58\u5728\u6307\u5b9a\u5143\u7d20\u65f6\uff0c\u5148\u4f7f\u7528\u4e00\u7cfb\u5217\u6563\u5217\u51fd\u6570\u6839\u636e\u5143\u7d20\u5f97\u5230K\u4e2a\u4f4d\u4e0b\u6807\uff0c\u7136\u540e\u5224\u65ad\u5411\u91cf\u4e2d\u4f4d\u4e0b\u6807\u5bf9\u5e94\u7684\u4f4d\u662f\u5426\u4e3a1\uff0c\u82e5\u5b58\u5728\u4e00\u4e2a\u4e0d\u4e3a1\uff0c\u5219\u8be5\u5143\u7d20\u4e0d\u5b58\u5728\uff1b\u5426\u5219\u8ba4\u4e3a\u5b58\u5728\uff1b<br>RedissonBloomFilter.contains\u65b9\u6cd5\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n\n    <pre>public boolean contains(T object) {\n&nbsp; &nbsp; \/\/ \u6839\u636e\u5e26\u63d2\u5165\u5143\u7d20\u5f97\u5230\u4e24\u4e2along\u7c7b\u578b\u6563\u5217\u503c\n&nbsp; &nbsp; long[] hashes = hash(object);\n\n&nbsp; &nbsp; while (true) {\n&nbsp; &nbsp; &nbsp; &nbsp; if (size == 0) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readConfig();\n&nbsp; &nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; &nbsp; int hashIterations = this.hashIterations;\n&nbsp; &nbsp; &nbsp; &nbsp; long size = this.size;\n\n&nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u5f97\u5230\u4f4d\u4e0b\u6807\u6570\u7ec4\n&nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u4ee5\u4e24\u4e2a\u6563\u5217\u503c\u6839\u636e\u6307\u5b9a\u7b56\u7565\u751f\u6210hashIterations\u4e2a\u6563\u5217\u503c\uff0c\u4ece\u800c\u5f97\u5230\u4f4d\u4e0b\u6807\n&nbsp; &nbsp; &nbsp; &nbsp; long[] indexes = hash(hashes[0], hashes[1], hashIterations, size);\n\n&nbsp; &nbsp; &nbsp; &nbsp; CommandBatchService executorService = new CommandBatchService(commandExecutor);\n&nbsp; &nbsp; &nbsp; &nbsp; addConfigCheck(hashIterations, size, executorService);\n&nbsp; &nbsp; &nbsp; &nbsp; RBitSetAsync bs = createBitSet(executorService);\n&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i  result = (List\n     \n      ) executorService.execute().getResponses();\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (Boolean val : result.subList(1, result.size()-1)) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!val) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u82e5\u5b58\u5728\u4e0d\u4e3a1\u7684\u4f4d\uff0c\u5219\u8ba4\u4e3a\u5143\u7d20\u4e0d\u5b58\u5728\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ \u90fd\u4e3a1\uff0c\u5219\u8ba4\u4e3a\u5143\u7d20\u5b58\u5728\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;\n&nbsp; &nbsp; &nbsp; &nbsp; } catch (RedisException e) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e.getMessage() == null || !e.getMessage().contains(\"Bloom filter config has been changed\")) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; }\n}\n     <\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Redis\u4e2dRedisson\u5e03\u9686&#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-201514","post","type-post","status-publish","format-standard","hentry","category-database"],"_links":{"self":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/201514","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=201514"}],"version-history":[{"count":0,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/201514\/revisions"}],"wp:attachment":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/media?parent=201514"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/categories?post=201514"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/tags?post=201514"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}