{"id":1248,"date":"2025-09-21T00:17:15","date_gmt":"2025-09-20T16:17:15","guid":{"rendered":"https:\/\/eve2333.top\/?p=1248"},"modified":"2025-09-21T00:17:16","modified_gmt":"2025-09-20T16:17:16","slug":"%e7%89%9b%e5%88%b8onecoupon%e7%b3%bb%e7%bb%9f-%e7%ac%ac%e2%91%a2%e7%ab%a0%e8%8a%82%ef%bc%9a%e5%88%86%e5%8f%91%e5%bc%95%e6%93%8e%e6%9c%8d%e5%8a%a1-%e4%b8%8b","status":"publish","type":"post","link":"https:\/\/eve2333.top\/?p=1248","title":{"rendered":"\u725b\u5238oneCoupon\u7cfb\u7edf \u7b2c\u2462\u7ae0\u8282\uff1a\u5206\u53d1&amp;\u5f15\u64ce\u670d\u52a1-\u4e0b"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">\u7b2c21\u5c0f\u8282\uff1a\u4f18\u60e0\u5238\u5206\u53d1\u5931\u8d25\u8bb0\u5f55\u6df1\u5206\u9875\u4f18\u5316<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5728\u6267\u884c\u4f18\u60e0\u5238\u5206\u53d1\u65f6\uff0c\u5bf9\u4e8e\u56e0\u5e93\u5b58\u4e0d\u8db3\u6216\u7528\u6237\u5df2\u9886\u53d6\u8fc7\u4f18\u60e0\u5238\u800c\u5bfc\u81f4\u7684\u5206\u53d1\u5931\u8d25\u60c5\u51b5\uff0c\u6211\u4eec\u4f1a\u8bb0\u5f55\u8fd9\u4e9b\u5931\u8d25\u7684\u5206\u53d1\u8bb0\u5f55\u3002\u4ece\u4f01\u4e1a\u7684\u5b9e\u9645\u4e1a\u52a1\u9700\u6c42\u6765\u770b\uff0c\u8fd9\u4e9b\u8bb0\u5f55\u53ef\u4ee5\u901a\u8fc7\u540e\u53f0\u5206\u9875\u67e5\u8be2\uff0c\u6216\u8005\u5728\u5206\u53d1\u5b8c\u6210\u540e\u5c06\u5931\u8d25\u8bb0\u5f55\u5199\u5165 Excel \u4f9b\u8fd0\u8425\u4eba\u5458\u67e5\u770b\u3002\u663e\u7136\uff0c\u540e\u8005\u66f4\u4e3a\u4f18\u8d8a\uff0c\u56e0\u4e3a\u8fd9\u4e9b\u5931\u8d25\u8bb0\u5f55\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\u4ef7\u503c\u4e0d\u5927\uff0c\u5c06\u5176\u4fdd\u5b58\u5230 Excel \u6587\u4ef6\u4e2d\u4e0d\u4ec5\u65b9\u4fbf\u67e5\u770b\uff0c\u8fd8\u80fd\u8282\u7701\u6570\u636e\u5e93\u7684\u5b58\u50a8\u7a7a\u95f4\u3002<\/p>\n\n\n\n<p>\u6211\u4eec\u8fd8\u9700\u8981\u8003\u8651\u4e00\u4e2a\u95ee\u9898\uff1a\u9519\u8bef\u5206\u53d1\u7684\u60c5\u51b5\u4f1a\u5f88\u591a\u5417\uff1f\u5b9e\u9645\u4e0a\uff0c\u8fd9\u79cd\u60c5\u51b5\u5e76\u4e0d\u5e38\u89c1\u3002\u4f46\u53ea\u8981\u662f\u4eba\u4e3a\u64cd\u4f5c\uff0c\u603b\u53ef\u80fd\u51fa\u73b0\u6f0f\u6d1e\uff0c\u4f8b\u5982\u672a\u68c0\u67e5\u4f18\u60e0\u5238\u6a21\u677f\u7684\u5e93\u5b58\uff0c\u6216\u8005\u63d0\u53d6\u7684\u7528\u6237\u6570\u636e\u6709\u8bef\uff08\u7528\u6237\u5df2\u9886\u53d6\u8fc7\u4f18\u60e0\u5238\uff09\u3002\u5728\u8fd9\u79cd\u6781\u7aef\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u9700\u8981\u901a\u8fc7\u5206\u9875\u7684\u60c5\u51b5 limit offset, count \u7684\u5f62\u5f0f\u8fdb\u884c\u6309\u6279\u6b21\u8bfb\u53d6\uff0c\u4f8b\u5982\u4e0b\u8ff0 SQL\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>select*from t_coupon_task_fail where batch_id ='xxxxxx'limit0,1000;<\/code><\/pre>\n\n\n\n<p>\u7136\u800c\uff0c\u8bb8\u591a\u4eba\u5e38\u5e38\u5ffd\u89c6\u4e00\u4e2a\u95ee\u9898\uff1a\u5f53 MySQL \u5728\u5904\u7406\u5206\u9875\u5f88\u6df1\u7684\u6570\u636e\u65f6\uff0c\u5c24\u5176\u662f\u8bfb\u53d6\u5927\u6570\u636e\u91cf\u4e2d\u7684\u9760\u540e\u90e8\u5206\u65f6\uff0c\u4f1a\u9047\u5230\u6df1\u5ea6\u5206\u9875\u95ee\u9898\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4ec0\u4e48\u662f\u6df1\u5206\u9875\uff1f<\/h2>\n\n\n\n<p>MySQL \u7684\u6df1\u5206\u9875\u95ee\u9898\u6307\u7684\u662f\u5728\u4f7f\u7528\u5206\u9875\u67e5\u8be2\u65f6\uff0c\u968f\u7740\u9875\u6570\u7684\u589e\u52a0\uff0c\u67e5\u8be2\u7684\u6548\u7387\u4f1a\u663e\u8457\u964d\u4f4e\uff0c\u5c24\u5176\u662f\u5bf9\u4e8e\u5927\u91cf\u6570\u636e\u7684\u8868\u3002\u8fd9\u901a\u5e38\u53d1\u751f\u5728\u4f7f\u7528 <code>LIMIT<\/code> \u5b50\u53e5\u8fdb\u884c\u5206\u9875\u65f6\uff0c\u4f8b\u5982 <code>LIMIT offset, count<\/code>\u3002\u5f53 <code>offset<\/code> \u503c\u5f88\u5927\u65f6\uff0cMySQL \u9700\u8981\u626b\u63cf\u548c\u8df3\u8fc7\u5927\u91cf\u7684\u884c\uff0c\u8fd9\u4f1a\u5bfc\u81f4\u67e5\u8be2\u53d8\u6162\u3002<\/p>\n\n\n\n<p>\u5bf9\u4e8e <code>SELECT * FROM table LIMIT 1000000, 10<\/code> \u8fd9\u6837\u7684\u67e5\u8be2\uff0cMySQL \u4f1a\u626b\u63cf\u524d 1000000 \u6761\u8bb0\u5f55\uff0c\u7136\u540e\u4e22\u5f03\u5b83\u4eec\uff0c\u53ea\u8fd4\u56de\u63a5\u4e0b\u6765\u7684 10 \u6761\u3002\u8fd9\u610f\u5473\u7740\u5373\u4f7f\u6700\u7ec8\u7ed3\u679c\u53ea\u5305\u542b 10 \u6761\u8bb0\u5f55\uff0cMySQL \u4ecd\u7136\u9700\u8981\u5904\u7406\u5e76\u4e22\u5f03\u5927\u91cf\u7684\u884c\uff0c\u5bfc\u81f4\u67e5\u8be2\u65f6\u95f4\u968f\u7740 <code>offset<\/code> \u589e\u5927\u800c\u589e\u52a0\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240904_dev_coupon-distribute-v3_limit-page_ding.ma<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u751f\u6210\u6d4b\u8bd5\u6570\u636e\u590d\u73b0\u6df1\u5206\u9875<\/h2>\n\n\n\n<p>\u6211\u4eec\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u6a21\u62df 100 \u4e07\u7684\u5355\u4e2a\u6279\u6b21\u9519\u8bef\u8bb0\u5f55\uff0c\u786e\u4fdd\u6570\u636e\u6709\u4e2a\u504f\u771f\u5b9e\u7684\u72b6\u6001\u3002\u4e3b\u8981\u662f\u6570\u636e\u91cf\u5c0f\u4e86\u6a21\u62df\u4e0d\u51fa\u6765\u6df1\u5206\u9875\u7684\u6548\u679c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DELIMITER $$\n\nCREATE PROCEDURE insert_coupon_task_fail_records()\nBEGIN\n    DECLARE i INT DEFAULT 1;\n    DECLARE batch_size INT DEFAULT 1000; -- \u6bcf\u6279\u63d2\u51651000\u6761\u8bb0\u5f55\n    DECLARE json_data TEXT;\n\n    WHILE i &lt;= 1000000 DO\n        -- \u5f00\u542f\u4e00\u4e2a\u4e8b\u52a1\n        START TRANSACTION;\n\n        -- \u6267\u884c\u6279\u91cf\u63d2\u5165\n        SET @end = i + batch_size - 1;\n        WHILE i &lt;= @end DO\n            SET json_data = CONCAT('{\"key\": \"value_', i, '\"}');\n            INSERT INTO `t_coupon_task_fail` (`batch_id`, `json_object`)\n            VALUES (1830889785603571980, json_data);\n            SET i = i + 1;\n        END WHILE;\n\n        -- \u63d0\u4ea4\u4e8b\u52a1\n        COMMIT;\n    END WHILE;\nEND$$\n\nDELIMITER ;<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u6267\u884c\u8fd9\u4e2a\u5b58\u50a8\u8fc7\u7a0b\uff0c\u6a21\u62df\u51fa 100 \u4e07\u8bb0\u5f55\uff0c\u5927\u6982\u6267\u884c\u5728 10 \u79d2\u4ee5\u4e0a\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CALL insert_coupon_task_fail_records();<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u5148\u6765\u770b\u770b\u6267\u884c\u67e5\u8be2\u524d 10 \u6761\u6570\u636e SQL \u6267\u884c\u65f6\u95f4\u662f\u591a\u4e45\uff0c\u6839\u636e\u6267\u884c\u8fd4\u56de\u7ed3\u679c\u6765\u770b\uff0c\u8fd4\u56de\u5927\u6982\u5728 <strong>500 \u00b5s<\/strong> \u5de6\u53f3\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>select*from t_coupon_task_fail where batch_id ='1830889785603571980'limit0,10;<\/code><\/pre>\n\n\n\n<p>\u5982\u679c\u67e5\u8be2\u6700\u540e\u51e0\u6761\u6570\u636e\uff0c\u90a3\u4e48\u8fd9\u4e2a SQL \u7684\u5e73\u5747\u6548\u5e94\u65f6\u95f4\u662f <strong>600 ms<\/strong>\uff0c\u76f8\u5bf9\u4e8e\u524d\u9762\u7684\u6570\u636e<strong>\u6027\u80fd\u76f8\u5dee\u4e86\u8fd1 1200 \u500d<\/strong>\uff01\u8fd9\u4e2a\u6570\u636e\u662f\u5f88\u6050\u6016\u7684\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>select*from t_coupon_task_fail where batch_id ='1830889785603571980'limit999990,10;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>1 \u6beb\u79d2\uff08ms\uff09 = 1000 \u5fae\u79d2\uff08\u00b5s\uff09<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u5982\u679c\u6211\u4eec\u591a\u6267\u884c\u51e0\u6b21\u5b58\u50a8\u8fc7\u7a0b\uff0c\u8ba9\u6570\u636e\u6765\u5230 500 \u4e07\uff0c\u67e5\u8be2\u6027\u80fd\u6765\u5230\u4e86\u60ca\u4eba\u7684\u8fd1 5 \u79d2\u3002\u6240\u4ee5\uff0c\u5927\u5bb6\u5982\u679c\u5728\u9879\u76ee\u4e2d\u9047\u5230\u7c7b\u4f3c\u4e8e\u8fd9\u79cd\u5927\u6570\u636e\u91cf\u6df1\u5206\u9875\u7684\u60c5\u51b5\uff0c\u4e00\u5b9a\u8981\u7279\u522b\u6ce8\u610f\uff0c\u7a0d\u5fae\u4e0d\u5c0f\u5fc3\u5c31\u662f\u6027\u80fd\u6df1\u6e0a\u3002<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240904140627135.png\" alt=\"\" title=\"\"\/><\/figure>\n<\/figure>\n\n\n\n<p><strong>\u6df1\u5206\u9875\u4e3b\u8981\u95ee\u9898\u4e0d\u662f\u8bfb\u53d6\u67d0\u4e00\u6b21\u6027\u80fd\u5dee\uff0c\u800c\u662f\u6211\u4eec\u8bfb\u53d6\u90fd\u540e\u9762\u7684\u6240\u6709\u8bb0\u5f55\u90fd\u5f88\u6162\uff0c\u8d8a\u5230\u540e\u9762\u8d8a\u6162<\/strong>\u3002\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u5047\u8bbe\u6211\u4eec\u5171\u9700\u8981\u53bb\u6570\u636e\u5e93\u8bfb\u53d6 100 \u4e07\u6570\u636e\uff0c\u6bcf\u6b21\u8bfb\u53d6 1000 \u6761\uff0c\u53ef\u80fd\u5230 50 \u4e07\u5c31\u5f00\u59cb\u660e\u663e\u53d8\u6162\u4e86\uff0c\u6700\u540e\u5c31\u4f1a\u6f14\u53d8\u6210\u4f1a\u6162 50\u4e07 \/ 1000 \u6b21\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5982\u4f55\u89e3\u51b3\u6df1\u5206\u9875\uff1f<\/h2>\n\n\n\n<p>\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6\u5f88\u76f4\u89c2\u80fd\u7406\u89e3\u4e0d\u540c\u6df1\u5206\u9875\u7684\u6027\u80fd\u5dee\u8ddd\uff0c\u6211\u4eec\u63a5\u4e0b\u6765\u7684\u793a\u4f8b\u4f1a\u6309\u7167 500 \u4e07\u6570\u636e\u7684\u57fa\u6570\u8fdb\u884c\u6d4b\u8bd5\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u5b50\u67e5\u8be2\u4f18\u5316<\/h3>\n\n\n\n<p>\u6211\u4eec\u901a\u8fc7\u5b50\u67e5\u8be2\u7684\u65b9\u5f0f\u8fdb\u884c\u4f18\u5316\uff0c\u4f18\u5316\u8bed\u53e5\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql> select * from t_coupon_task_fail where id >=\n    ->\n    -> (SELECT id\n    ->     FROM t_coupon_task_fail\n    ->     WHERE batch_id = '1830889785603571980'\n    ->     ORDER BY id\n    ->     LIMIT 4999990, 1\n    -> )\n    ->\n    -> limit 10;\n+---------+---------------------+--------------------------+\n| id      | batch_id            | json_object              |\n+---------+---------------------+--------------------------+\n| 4999991 | 1830889785603571980 | {\"key\": \"value_999991\"}  |\n| 4999992 | 1830889785603571980 | {\"key\": \"value_999992\"}  |\n| 4999993 | 1830889785603571980 | {\"key\": \"value_999993\"}  |\n| 4999994 | 1830889785603571980 | {\"key\": \"value_999994\"}  |\n| 4999995 | 1830889785603571980 | {\"key\": \"value_999995\"}  |\n| 4999996 | 1830889785603571980 | {\"key\": \"value_999996\"}  |\n| 4999997 | 1830889785603571980 | {\"key\": \"value_999997\"}  |\n| 4999998 | 1830889785603571980 | {\"key\": \"value_999998\"}  |\n| 4999999 | 1830889785603571980 | {\"key\": \"value_999999\"}  |\n| 5000000 | 1830889785603571980 | {\"key\": \"value_1000000\"} |\n+---------+---------------------+--------------------------+\n10 rows in set (0.61 sec)<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u540c\u6837\u7684 SQL \u8bed\u53e5\uff0c\u6027\u80fd\u4ece\u8fd1 5 \u79d2\u4e0b\u964d\u5230\u4e86 610 \u6beb\u79d2\u3002<\/p>\n\n\n\n<p>\u90a3\u6211\u4eec\u518d\u901a\u8fc7 explain \u8bed\u53e5\uff0c\u5206\u6790\u4e0b\u4e3a\u4ec0\u4e48\u80fd\u591f\u4f18\u5316\u6df1\u5206\u9875\u95ee\u9898\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"237\" src=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image-1024x237.png\" alt=\"\" class=\"wp-image-1309\" srcset=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image-1024x237.png 1024w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image-300x70.png 300w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image-768x178.png 768w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image-1536x356.png 1536w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357252-image.png 1756w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\u6839\u636e\u6267\u884c\u8ba1\u5212\u5f97\u77e5\uff0c\u5b50\u67e5\u8be2\u67e5\u8be2\u662f\u7528\u5230\u4e86\u7d22\u5f15\u3002\u9996\u5148\u5728<strong>\u7d22\u5f15\u4e0a\u62ff\u5230\u4e86\u805a\u96c6\u7d22\u5f15\u7684\u4e3b\u952e ID \u7701\u53bb\u4e86\u56de\u8868\u64cd\u4f5c<\/strong>\uff0c\u7136\u540e\u7b2c\u4e8c\u67e5\u8be2\u76f4\u63a5\u6839\u636e\u7b2c\u4e00\u4e2a\u67e5\u8be2\u7684 ID \u5f80\u540e\u518d\u53bb\u67e5\u5c31\u53ef\u4ee5\u4e86\u3002<\/p>\n\n\n\n<p>\u4f46\u662f\uff0c\u6709\u4e2a\u4e0d\u597d\u7684\u6d88\u606f\uff0c\u8fd9\u79cd\u65b9\u5f0f\u6027\u80fd\u5e76\u4e0d\u662f\u6052\u5b9a\u7684\uff0c\u5982\u679c\u6211\u4eec\u67e5\u8be2 100 \u4e07\u6570\u636e\u540e\u7684 10 \u6761\u8bb0\u5f55\uff0c\u6027\u80fd\u8981\u628a\u8fd9\u4e2a\u66f4\u5feb\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql> select * from t_coupon_task_fail where id >=\n    ->\n    -> (SELECT id\n    ->     FROM t_coupon_task_fail\n    ->     WHERE batch_id = '1830889785603571980'\n    ->     ORDER BY id\n    ->     LIMIT 999990, 1\n    -> )\n    ->\n    -> limit 10;\n+---------+---------------------+--------------------------+\n| id      | batch_id            | json_object              |\n+---------+---------------------+--------------------------+\n|  999991 | 1830889785603571980 | {\"key\": \"value_999991\"}  |\n|  999992 | 1830889785603571980 | {\"key\": \"value_999992\"}  |\n|  999993 | 1830889785603571980 | {\"key\": \"value_999993\"}  |\n|  999994 | 1830889785603571980 | {\"key\": \"value_999994\"}  |\n|  999995 | 1830889785603571980 | {\"key\": \"value_999995\"}  |\n|  999996 | 1830889785603571980 | {\"key\": \"value_999996\"}  |\n|  999997 | 1830889785603571980 | {\"key\": \"value_999997\"}  |\n|  999998 | 1830889785603571980 | {\"key\": \"value_999998\"}  |\n|  999999 | 1830889785603571980 | {\"key\": \"value_999999\"}  |\n| 1000000 | 1830889785603571980 | {\"key\": \"value_1000000\"} |\n+---------+---------------------+--------------------------+\n10 rows in set (0.15 sec)<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u67e5\u8be2 100 \u4e07\u6570\u636e\u4ec5\u9700\u8981 150 \u6beb\u79d2\u3002\u8fd9\u4e5f\u5c31\u610f\u5473\u7740\u5982\u679c\u6570\u636e\u91cf\u8d85\u8fc7 500 \u4e07\uff0c\u6027\u80fd\u4f1a\u4e0b\u964d\u7684\u66f4\u591a\uff0c\u6240\u4ee5\uff0c\u8fd9\u79cd\u6df1\u5206\u9875\u89e3\u51b3\u65b9\u6848\u5e76\u4e0d\u53ef\u53d6\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u5ef6\u8fdf\u5173\u8054<\/h3>\n\n\n\n<p>\u65b0\u7684\u89e3\u51b3\u65b9\u6848\u53eb\u6cd5\u662f\u5ef6\u8fdf\u5173\u8054\uff0c\u5176\u5b9e\u672c\u8d28\u4e0a\u662f\u901a\u8fc7 JOIN \u5173\u8054\u7684\u5f62\u5f0f\u8fdb\u884c\u7ed1\u5b9a\uff0cSQL \u8bed\u53e5\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql> SELECT\n    ->     t1.id,\n    ->     t1.batch_id,\n    ->     t1.json_object\n    -> FROM\n    ->     t_coupon_task_fail t1\n    ->     INNER JOIN (\n    ->         SELECT\n    ->             id\n    ->         FROM\n    ->             t_coupon_task_fail\n    ->         WHERE\n    ->             batch_id = '1830889785603571980'\n    ->         ORDER BY\n    ->             id\n    ->         LIMIT 4999990,\n    ->         10) AS t2 on t1.id = t2.id\n    -> LIMIT 10;\n+---------+---------------------+--------------------------+\n| id      | batch_id            | json_object              |\n+---------+---------------------+--------------------------+\n| 4999991 | 1830889785603571980 | {\"key\": \"value_999991\"}  |\n| 4999992 | 1830889785603571980 | {\"key\": \"value_999992\"}  |\n| 4999993 | 1830889785603571980 | {\"key\": \"value_999993\"}  |\n| 4999994 | 1830889785603571980 | {\"key\": \"value_999994\"}  |\n| 4999995 | 1830889785603571980 | {\"key\": \"value_999995\"}  |\n| 4999996 | 1830889785603571980 | {\"key\": \"value_999996\"}  |\n| 4999997 | 1830889785603571980 | {\"key\": \"value_999997\"}  |\n| 4999998 | 1830889785603571980 | {\"key\": \"value_999998\"}  |\n| 4999999 | 1830889785603571980 | {\"key\": \"value_999999\"}  |\n| 5000000 | 1830889785603571980 | {\"key\": \"value_1000000\"} |\n+---------+---------------------+--------------------------+\n10 rows in set (0.52 sec)<\/code><\/pre>\n\n\n\n<p>\u6027\u80fd\u5dee\u4e0d\u591a\u4e5f\u662f 500 \u6beb\u79d2\u5de6\u53f3\uff0c\u548c\u5b50\u67e5\u8be2\u4f18\u5316\u4e00\u6837\uff0c\u4f1a\u968f\u7740\u6570\u636e\u91cf\u7684\u589e\u591a\uff0c\u6027\u80fd\u4e5f\u4f1a\u4e0b\u964d\u3002<\/p>\n\n\n\n<p>\u6027\u80fd\u4f18\u5316\u601d\u8def\u4e0e\u5b50\u67e5\u8be2\u57fa\u672c\u4e00\u81f4\uff0c\u53ea\u4e0d\u8fc7\u91c7\u7528\u4e86 JOIN \u7684\u5f62\u5f0f\u6267\u884c SQL\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"358\" src=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image-1024x358.png\" alt=\"\" class=\"wp-image-1308\" srcset=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image-1024x358.png 1024w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image-300x105.png 300w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image-768x268.png 768w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image-1536x537.png 1536w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357180-image.png 1785w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u4e66\u7b7e\u8bb0\u5f55<\/h3>\n\n\n\n<p>\u4e0a\u9762\u7684\u4e24\u79cd\u65b9\u5f0f\u5176\u5b9e\u89e3\u51b3\u6df1\u5206\u9875\u7684\u601d\u8def\u662f\u4e00\u81f4\u7684\uff0c\u63a5\u4e0b\u6765\u8981\u8bf4\u7684\u4e66\u7b7e\u8bb0\u5f55\u7684\u65b9\u5f0f\u53ef\u4ee5\u8bf4\u662f\u6027\u80fd\u6700\u5f3a\u7684\u3002<\/p>\n\n\n\n<p>\u4e66\u7b7e\u8bb0\u5f55\u53eb\u8d77\u6765\u6709\u70b9\u7ed5\uff0c\u5f88\u591a\u540c\u5b66\u4e0d\u80fd\u7b2c\u4e00\u65f6\u95f4\u77e5\u9053\u662f\u4ec0\u4e48\uff0c\u4ece\u539f\u7406\u4e0a\u8bf4\uff0c\u5c5e\u4e8e\u662f\u4e00\u79cd\u6eda\u52a8\u67e5\u8be2\u3002\u4e5f\u5c31\u662f\u8bf4\u6211\u4eec\u5fc5\u987b\u4ece\u7b2c\u4e00\u9875\u5f00\u59cb\u67e5\u8be2\uff0c\u7136\u540e\u83b7\u53d6\u672c\u9875\u6700\u5927\u7684\u8bb0\u5f55 ID\uff0c\u7136\u540e\u518d\u6839\u636e\u5927\u4e8e\u6700\u5927\u8bb0\u5f55 ID \u7684\u6570\u636e\u5411\u540e\u6301\u7eed\u6eda\u52a8\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u6211\u4eec\u5982\u679c\u60f3\u67e5\u8be2\u5927\u4e8e 4999990 \u540e\u8bb0\u5f55\u7684 10 \u6761\uff0c\u90a3\u6211\u4eec\u5c31\u5f97\u77e5\u9053 4999990 \u6761\u7684 ID\u3002\u56e0\u4e3a\u6211\u4eec ID \u662f\u9012\u589e\u7684\uff0c\u6240\u4ee5\u76f4\u63a5\u67e5\u8be2\u5373\u53ef\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql> SELECT\n    ->     *\n    -> FROM\n    ->     t_coupon_task_fail\n    -> WHERE\n    ->     batch_id = '1830889785603571980'\n    ->     AND id > 4999990\n    -> LIMIT 10;\n+---------+---------------------+--------------------------+\n| id      | batch_id            | json_object              |\n+---------+---------------------+--------------------------+\n| 4999991 | 1830889785603571980 | {\"key\": \"value_999991\"}  |\n| 4999992 | 1830889785603571980 | {\"key\": \"value_999992\"}  |\n| 4999993 | 1830889785603571980 | {\"key\": \"value_999993\"}  |\n| 4999994 | 1830889785603571980 | {\"key\": \"value_999994\"}  |\n| 4999995 | 1830889785603571980 | {\"key\": \"value_999995\"}  |\n| 4999996 | 1830889785603571980 | {\"key\": \"value_999996\"}  |\n| 4999997 | 1830889785603571980 | {\"key\": \"value_999997\"}  |\n| 4999998 | 1830889785603571980 | {\"key\": \"value_999998\"}  |\n| 4999999 | 1830889785603571980 | {\"key\": \"value_999999\"}  |\n| 5000000 | 1830889785603571980 | {\"key\": \"value_1000000\"} |\n+---------+---------------------+--------------------------+\n10 rows in set (0.00 sec)<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u6211\u4eec\u7684\u8bb0\u5f55\u7edf\u8ba1\u6700\u5c0f\u65f6\u95f4\u662f\u79d2\uff0c\u4f46\u662f\u6267\u884c\u65f6\u95f4\u4e00\u4f46\u662f\u5fae\u79d2\uff08\u00b5s\uff09\u5c31\u6ca1\u529e\u6cd5\u663e\u793a\u4e86\uff0c\u6211\u901a\u8fc7\u6570\u636e\u5e93\u53ef\u89c6\u5316\u5de5\u5177\u770b\u4e86\u4e0b\uff0c\u5927\u6982\u662f 500 \u5fae\u79d2\u5de6\u53f3\u3002<\/p>\n\n\n\n<p>\u8fd9\u4e2a\u65f6\u5019\u518d\u7ed9\u5927\u5bb6\u5e26\u6765\u4e00\u4e2a\u95ee\u9898\uff0c\u5982\u679c\u6570\u636e\u91cf\u5728\u51e0\u5343\u4e07\u7ea7\u522b\uff0c\u5b83\u8fd8\u80fd\u4fdd\u8bc1\u5fae\u5999\u7ea7\u522b\u7684\u67e5\u8be2\u4e48\uff1f\u6211\u4eec\u4fee\u6539\u4e0b\u5b58\u50a8\u8fc7\u7a0b\uff0c\u9020\u5927\u6982 4000 \u4e07\u6570\u636e\u8bd5\u8bd5\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql> select count(*) from t_coupon_task_fail;\n+----------+\n| count(*) |\n+----------+\n| 40000000 |\n+----------+\n1 row in set (3.12 sec)\n\nmysql> SELECT\n    ->     *\n    -> FROM\n    ->     t_coupon_task_fail\n    -> WHERE\n    ->     batch_id = '1830889785603571980'\n    ->     AND id > 39999990\n    -> LIMIT 10;\n+----------+---------------------+---------------------------+\n| id       | batch_id            | json_object               |\n+----------+---------------------+---------------------------+\n| 39999991 | 1830889785603571980 | {\"key\": \"value_19999991\"} |\n| 39999992 | 1830889785603571980 | {\"key\": \"value_19999992\"} |\n| 39999993 | 1830889785603571980 | {\"key\": \"value_19999993\"} |\n| 39999994 | 1830889785603571980 | {\"key\": \"value_19999994\"} |\n| 39999995 | 1830889785603571980 | {\"key\": \"value_19999995\"} |\n| 39999996 | 1830889785603571980 | {\"key\": \"value_19999996\"} |\n| 39999997 | 1830889785603571980 | {\"key\": \"value_19999997\"} |\n| 39999998 | 1830889785603571980 | {\"key\": \"value_19999998\"} |\n| 39999999 | 1830889785603571980 | {\"key\": \"value_19999999\"} |\n| 40000000 | 1830889785603571980 | {\"key\": \"value_20000000\"} |\n+----------+---------------------+---------------------------+\n10 rows in set (0.00 sec)<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u67e5\u8be2 4000 \u4e07\u8bb0\u5f55\uff0c\u6027\u80fd\u4f9d\u65e7\u662f\u5fae\u5999\u7ea7\uff0c\u57fa\u672c\u4e0a\u53ef\u4ee5\u8ba4\u5b9a\u8fd9\u4e2a\u6027\u80fd\u662f\u6052\u5b9a\u7684\u3002<\/p>\n\n\n\n<p>\u4f46\u662f\u8fd9\u4e2a\u6709\u70b9\u4e0d\u597d\u7684\u5730\u65b9\u5728\u4e8e\uff0c\u4e0d\u652f\u6301\u8df3\u9875\uff0c\u53ea\u80fd\u4e0a\u4e00\u9875\u548c\u4e0b\u4e00\u9875\u3002\u4e0d\u8fc7\u5bf9\u6211\u4eec\u7cfb\u7edf\u6765\u8bf4\u65e0\u6240\u8c13\uff0c\u53cd\u6b63\u662f\u8bfb\u53d6\u6240\u6709\u5931\u8d25\u5206\u53d1\u7684\u8bb0\u5f55\u751f\u6210 Excel \u5c31\u597d\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"excel\">\u5206\u53d1\u5931\u8d25\u8bb0\u5f55\u751f\u6210 Excel<\/h2>\n\n\n\n<p>\u6211\u4eec\u5728 Excel \u89e3\u6790\u5b8c\u6210\u540e\u53d1\u9001\u7684\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\u91cc\uff0c\u5c06\u5206\u53d1\u5931\u8d25\u6570\u636e\u4ee5\u4e66\u7b7e\u8bb0\u5f55\u7684\u5f62\u5f0f\u8bfb\u53d6\u5230\uff0c\u7136\u540e\u5c01\u88c5\u4e3a\u65b0\u7684\u5931\u8d25 Excel\uff0c\u5e76\u5c06\u5730\u5740\u4fdd\u5b58\u5230\u5206\u53d1\u4efb\u52a1\u8bb0\u5f55\u4e2d\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Transactional(rollbackFor = Exception.class)\n@Override\npublic void onMessage(MessageWrapper&lt;CouponTemplateDistributionEvent> messageWrapper) {\n    \/\/ ......\n    \/\/ \u8fd9\u91cc\u662f\u5206\u53d1\u4efb\u52a1\u7ed3\u675f\u6807\u8bc6\u4e3a TRUE\uff0c\u4ee3\u8868\u5df2\u7ecf\u6ca1\u6709 Excel \u8bb0\u5f55\n    long initId = 0;\n    boolean isFirstIteration = true;  \/\/ \u7528\u4e8e\u6807\u8bc6\u662f\u5426\u4e3a\u7b2c\u4e00\u6b21\u8fed\u4ee3\n    String failFileAddress = excelPath + \"\/\u7528\u6237\u5206\u53d1\u8bb0\u5f55\u5931\u8d25Excel-\" + event.getCouponTaskBatchId() + \".xlsx\";\n\n    \/\/ \u8fd9\u91cc\u5e94\u8be5\u4e0a\u4f20\u4e91 OSS \u6216\u8005 MinIO \u7b49\u5b58\u50a8\u5e73\u53f0\uff0c\u4f46\u662f\u589e\u52a0\u90e8\u7f72\u6210\u529f\u5e76\u4e14\u4e0d\u592a\u597d\u5f80\u7b80\u5386\u5199\u5c31\u4ec5\u5199\u5165\u672c\u5730\n    try (ExcelWriter excelWriter = EasyExcel.write(failFileAddress, UserCouponTaskFailExcelObject.class).build()) {\n        WriteSheet writeSheet = EasyExcel.writerSheet(\"\u7528\u6237\u5206\u53d1\u5931\u8d25Sheet\").build();\n        while (true) {\n            List&lt;CouponTaskFailDO> couponTaskFailDOList = listUserCouponTaskFail(event.getCouponTaskBatchId(), initId);\n            if (CollUtil.isEmpty(couponTaskFailDOList)) {\n                \/\/ \u5982\u679c\u662f\u7b2c\u4e00\u6b21\u8fed\u4ee3\u4e14\u96c6\u5408\u4e3a\u7a7a\uff0c\u5219\u8bbe\u7f6e failFileAddress \u4e3a null\n                if (isFirstIteration) {\n                    failFileAddress = null;\n                }\n                break;\n            }\n\n            \/\/ \u6807\u8bb0\u7b2c\u4e00\u6b21\u8fed\u4ee3\u5df2\u7ecf\u5b8c\u6210\n            isFirstIteration = false;\n\n            \/\/ \u5c06\u5931\u8d25\u884c\u6570\u548c\u5931\u8d25\u539f\u56e0\u5199\u5165 Excel \u6587\u4ef6\n            List&lt;UserCouponTaskFailExcelObject> excelDataList = couponTaskFailDOList.stream()\n                    .map(each -> JSONObject.parseObject(each.getJsonObject(), UserCouponTaskFailExcelObject.class))\n                    .toList();\n            excelWriter.write(excelDataList, writeSheet);\n\n            \/\/ \u67e5\u8be2\u51fa\u6765\u7684\u6570\u636e\u5982\u679c\u5c0f\u4e8e BATCH_USER_COUPON_SIZE \u610f\u5473\u7740\u540e\u9762\u5c06\u4e0d\u518d\u6709\u6570\u636e\uff0c\u8fd4\u56de\u5373\u53ef\n            if (couponTaskFailDOList.size() &lt; BATCH_USER_COUPON_SIZE) {\n                break;\n            }\n\n            \/\/ \u66f4\u65b0 initId \u4e3a\u5f53\u524d\u5217\u8868\u4e2d\u6700\u5927 ID\n            initId = couponTaskFailDOList.stream()\n                    .mapToLong(CouponTaskFailDO::getId)\n                    .max()\n                    .orElse(initId);\n        }\n    }\n\n    \/\/ \u786e\u4fdd\u6240\u6709\u7528\u6237\u90fd\u5df2\u7ecf\u63a5\u5230\u4f18\u60e0\u5238\u540e\uff0c\u8bbe\u7f6e\u4f18\u60e0\u5238\u63a8\u9001\u4efb\u52a1\u5b8c\u6210\u65f6\u95f4\n    CouponTaskDO couponTaskDO = CouponTaskDO.builder()\n            .id(event.getCouponTaskId())\n            .status(CouponTaskStatusEnum.SUCCESS.getStatus())\n            .completionTime(new Date())\n            .failFileAddress(failFileAddress)\n            .build();\n    couponTaskMapper.updateById(couponTaskDO);\n}\n\n\/**\n * \u67e5\u8be2\u7528\u6237\u5206\u53d1\u4efb\u52a1\u5931\u8d25\u8bb0\u5f55\n *\n * @param batchId \u5206\u53d1\u4efb\u52a1\u6279\u6b21 ID\n * @param maxId   \u4e0a\u6b21\u8bfb\u53d6\u6700\u5927 ID\n * @return \u7528\u6237\u5206\u53d1\u4efb\u52a1\u5931\u8d25\u8bb0\u5f55\u96c6\u5408\n *\/\nprivate List&lt;CouponTaskFailDO> listUserCouponTaskFail(Long batchId, Long maxId) {\n    LambdaQueryWrapper&lt;CouponTaskFailDO> queryWrapper = Wrappers.lambdaQuery(CouponTaskFailDO.class)\n            .eq(CouponTaskFailDO::getBatchId, batchId)\n            .gt(CouponTaskFailDO::getId, maxId)\n            .last(\"LIMIT \" + BATCH_USER_COUPON_SIZE);\n    return couponTaskFailMapper.selectList(queryWrapper);\n}<\/code><\/pre>\n\n\n\n<p>\u53ef\u80fd\u6709\u540c\u5b66\u6709\u7591\u95ee\uff0c\u5728\u4e0d\u67e5\u8be2\u662f\u5426\u6709\u5206\u53d1\u5931\u8d25\u8bb0\u5f55\u7684\u65f6\u5019\u5c31\u521b\u5efa EasyExcel \u5bf9\u8c61\uff0c\u662f\u5426\u6709\u95ee\u9898\uff1f<\/p>\n\n\n\n<p>\u5176\u5b9e\u4e0d\u4f1a\u7684\uff0c\u53ea\u6709\u5728\u7b2c\u4e00\u6b21\u8c03\u7528 <code>excelWriter.write(xx, xx)<\/code> \u65b9\u6cd5\u624d\u4f1a\u521b\u5efa Excel \u6587\u4ef6\uff0c\u6240\u4ee5\u4e0d\u7528\u62c5\u5fc3\u521b\u5efa\u7a7a\u8bb0\u5f55 Excel \u6587\u4ef6\u3002\u5982\u679c\u5199\u5165 Excel \u6587\u4ef6\u6210\u529f\u540e\uff0c\u5c31\u80fd\u5728\u725b\u5238\u6839\u76ee\u5f55 \/tmp \u6587\u4ef6\u5939\u4e0b\u770b\u5230\u6211\u4eec\u7684\u8bb0\u5f55\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u2514\u2500\u2500 tmp\n    \u251c\u2500\u2500 oneCoupon\u4efb\u52a1\u63a8\u9001Excel.xlsx\n    \u251c\u2500\u2500 \u7528\u6237\u5206\u53d1\u8bb0\u5f55\u5931\u8d25Excel-1831284632528740352.xlsx<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u751f\u6210\u7684 Excel \u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240904222349112.png\" alt=\"\" title=\"\"\/><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u6587\u7ae0\u4ecb\u7ecd\u4e86\u6df1\u5206\u9875\u7684\u4e1a\u52a1\u573a\u666f\uff0c\u540c\u65f6\u5462\u4ecb\u7ecd\u4e09\u79cd\u6df1\u5206\u9875\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u5176\u4e2d\u4e66\u7b7e\u8bb0\u5f55\u7684\u65b9\u5f0f\u5728\u5e94\u5bf9\u6df1\u5206\u9875\u573a\u666f\u4e0b\u6027\u80fd\u6700\u9ad8\uff0c\u5728\u6a21\u62df\u7684 4000 \u4e07\u884c\u8bb0\u5f55\u4e2d\u4f9d\u7136\u80fd\u591f\u4fdd\u6301\u5fae\u79d2\u67e5\u8be2\u6027\u80fd\u3002\u6700\u540e\u5c06\u5206\u53d1\u5931\u8d25\u7684\u7528\u6237\u9886\u5238\u8bb0\u5f55\u4fdd\u5b58\u5230\u4e86 Excel \u4e2d\uff0c\u5e76\u8d4b\u503c\u5230\u4f18\u60e0\u5238\u6a21\u677f\u5206\u53d1\u8bb0\u5f55\u4efb\u52a1\u4e2d\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<p>\u4e0d\u652f\u6301\u8df3\u9875\uff1a\u4e0d\u80fd\u83b7\u5f97\u6307\u5b9a\u9875\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u67e5\u8be2\u7b2cn\u9875\u9700\u8981\u7b2cn+1\u6216\u8005\u7b2cn-1\u9875\u7684\u6570\u636e<\/p>\n\n\n\n<p>\u4e2a\u4eba\u8ba4\u4e3a\u8fd9\u91cc\u8fd8\u662f\u6a21\u62df\u4e86\u4e00\u4e2a\u573a\u666f\u6765\u8bb2\u89e3\u6df1\u5206\u9875\u95ee\u9898\uff0c\u5b9e\u9645\u4e0a\u8fd9\u79cd\u6781\u7aef\u573a\u666f\u5f88\u96be\u89c1\u5230\u3002\u5728\u9a6c\u4e01\u54e5\u7684\u793a\u4f8b\u4e2d\uff0c\u662f\u5148\u6307\u5b9abatchId\uff08\u5206\u53d1\u4efb\u52a1\u6279\u6b21ID\uff09\uff0c\u518d\u67e5\u8be2\u5931\u8d25\u6570\u636e\u3002\u4ece\u4e1a\u52a1\u4e0a\u770b\uff0c\u6bcf\u4e00\u6b21\u5206\u53d1\u4efb\u52a1\u7684\u6279\u6b21ID\u90fd\u662f\u4e0d\u540c\uff0c\u4e0d\u53ef\u80fd\u4e0a\u4e00\u6b21\u5206\u53d1\u4efb\u52a1\u7684\u6279\u6b21ID\u662f49001\uff0c\u8fc7\u4e86\u4e24\u4e2a\u6708\u53c8\u6709\u4e00\u4e2a49001\u7684\u6279\u6b21ID\u3002\u800c\u8981\u5728\u4e00\u6b21\u5206\u53d1\u4efb\u52a1\u4e2d\uff0c\u8fbe\u52304000w\u7684\u5931\u8d25\u6570\u91cf\uff0c\u90a3\u5408\u7406\u53cd\u63a8\u6709\u53ef\u80fd\u662f\u5f53\u6b21\u5206\u53d1\u5168\u90e8\u5931\u8d25\u4e86\uff0c\u8fd9\u79cd\u4e1a\u52a1\u573a\u666f\u4e0d\u597d\u89c1\u5230\u7684\u5427<\/p>\n\n\n\n<p>\u672c\u8282\u60f3\u8868\u8fbe\u7684\u610f\u601d\u6ca1\u592a\u770b\u61c2\uff0c\u770b\u4e0b\u6765\u662f\u672c\u9879\u76ee\u662f\u9009\u7528\u4fdd\u5b58Excel\u7684\u65b9\u6848\uff0c\u90a3\u5c31\u6ca1\u6709\u6df1\u5206\u9875\u7684\u95ee\u9898\u5427\uff1f\u5982\u679c\u662f\u9009\u7528\u6570\u636e\u5e93\u6301\u4e45\u5316\u7684\u65b9\u6848\uff0c\u6587\u4e2d\u4e5f\u8bf4\u4e86\uff0c\u5931\u8d25\u7684\u573a\u666f\u5e76\u4e0d\u5e38\u89c1\uff0c\u6df1\u5206\u9875\u5728\u8fd9\u6709\u70b9\u5927\u6750\u5c0f\u7528\u3002\u611f\u89c9\u8fd9\u91cc\u66f4\u591a\u7684\u662f\u8ba9\u540c\u5b66\u4eec\u4e86\u89e3\u4e00\u4e0b\u6df1\u5206\u9875\u7684\u4e00\u4e9b\u5e38\u89c1\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u5982\u679c\u60f3\u8ddf\u9762\u8bd5\u5b98\u804a\u9879\u76ee\u4e2d\u662f\u5426\u9047\u5230\u6df1\u5206\u9875\u95ee\u9898\uff0c\u6700\u597d\u4e0d\u8981\u4e3e\u8fd9\u4e2a\u4f8b\u5b50\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c22\u5c0f\u8282\uff1a\u57fa\u4e8e\u6ce8\u89e3\u5b9e\u73b0\u53bb\u91cd\u8868\u6d88\u606f\u9632\u6b62\u91cd\u590d\u6d88\u8d39<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5f53\u4f7f\u7528\u6d88\u606f\u961f\u5217\u65f6\uff0c\u5ba2\u6237\u7aef\u91cd\u590d\u6d88\u8d39\u53ef\u80fd\u4f1a\u6210\u4e3a\u4e00\u4e2a\u4e25\u91cd\u7684\u95ee\u9898\u3002<\/p>\n\n\n\n<p>\u8fd9\u662f\u56e0\u4e3a\u6d88\u606f\u961f\u5217\u5177\u6709\u6301\u4e45\u6027\u548c\u53ef\u9760\u6027\u7684\u7279\u6027\uff0c\u786e\u4fdd\u6d88\u606f\u80fd\u591f\u88ab\u6210\u529f\u4f20\u9012\u7ed9\u6d88\u8d39\u8005\u3002\u7136\u800c\uff0c\u8fd9\u4e5f\u4f1a\u5bfc\u81f4\u5ba2\u6237\u7aef\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u91cd\u590d\u6d88\u8d39\u6d88\u606f\uff0c\u4f8b\u5982\u7f51\u7edc\u6545\u969c\uff08\u6216\u5ef6\u8fdf\uff09\u3001\u5ba2\u6237\u7aef\u5d29\u6e83\u3001\u6d88\u606f\u5904\u7406\u5931\u8d25\u7b49\u60c5\u51b5\u3002<\/p>\n\n\n\n<p>\u4e3a\u4e86\u907f\u514d\u8fd9\u79cd\u60c5\u51b5\u53d1\u751f\uff0c\u9700\u8981\u5728\u5ba2\u6237\u7aef\u5b9e\u73b0\u4e00\u4e9b\u673a\u5236\u6765\u786e\u4fdd\u6d88\u606f\u4e0d\u4f1a\u88ab\u91cd\u590d\u6d88\u8d39\uff0c\u4f8b\u5982\u8bb0\u5f55\u6d88\u8d39\u8005\u5df2\u7ecf\u5904\u7406\u7684\u6d88\u606f ID\u3001\u4f7f\u7528\u5206\u5e03\u5f0f\u9501\u6765\u63a7\u5236\u6d88\u8d39\u8fdb\u7a0b\u7684\u552f\u4e00\u6027\u7b49\u3002\u8fd9\u4e9b\u673a\u5236\u80fd\u591f\u4fdd\u8bc1\u6d88\u606f\u88ab\u6210\u529f\u5904\u7406\uff0c\u540c\u65f6\u4e5f\u80fd\u591f\u63d0\u9ad8\u7cfb\u7edf\u7684\u53ef\u9760\u6027\u548c\u7a33\u5b9a\u6027\u3002\u672c\u5c0f\u8282\u5c06\u63a2\u8ba8\u5982\u4f55\u786e\u4fdd\u6d88\u606f\u961f\u5217\u4e2d\u7684\u6d88\u606f\u4e0d\u4f1a\u88ab\u91cd\u590d\u6d88\u8d39\uff0c\u4e0b\u6587\u5c06\u4ee5 RocketMQ \u4e3a\u4f8b\u8bf4\u660e\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6d88\u606f\u5e42\u7b49\u6027<\/h2>\n\n\n\n<p>\u5728\u4f7f\u7528\u6d88\u606f\u961f\u5217 RocketMQ \u5b9e\u73b0\u5f02\u6b65\u5316\u3001\u89e3\u8026\u3001\u524a\u5cf0\u7b49\u529f\u80fd\u7684\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u8ba4\u4e3a\u6d88\u606f\u4e2d\u95f4\u4ef6\u662f\u4e00\u4e2a\u53ef\u9760\u7684\u7ec4\u4ef6\uff0c\u8fd9\u91cc\u7684\u53ef\u9760\u6027\u6307\u7684\u662f\uff0c\u53ea\u8981\u6d88\u606f\u88ab\u6210\u529f\u6295\u9012\u5230\u4e86\u6d88\u606f\u4e2d\u95f4\u4ef6\uff0c\u5b83\u5c31\u4e0d\u4f1a\u4e22\u5931\uff0c\u81f3\u5c11\u80fd\u591f\u88ab\u6d88\u8d39\u8005\u6210\u529f\u6d88\u8d39\u4e00\u6b21\u3002\u8fd9\u662f\u6d88\u606f\u4e2d\u95f4\u4ef6\u6700\u57fa\u672c\u7684\u7279\u6027\u4e4b\u4e00\uff0c\u4e5f\u5c31\u662f\u6211\u4eec\u901a\u5e38\u6240\u8bf4\u7684 <strong>\u201cAT LEAST ONCE\u201d<\/strong>\uff0c\u5373\u6d88\u606f\u81f3\u5c11\u4f1a\u88ab\u6210\u529f\u6d88\u8d39\u4e00\u904d\u3002<\/p>\n\n\n\n<p>\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u5047\u8bbe\u4e00\u4e2a\u6d88\u606f M \u88ab\u53d1\u9001\u5230\u6d88\u606f\u4e2d\u95f4\u4ef6\u5e76\u88ab\u6d88\u8d39\u7a0b\u5e8f A \u63a5\u6536\u5230\uff0cA \u5f00\u59cb\u6d88\u8d39\u8fd9\u4e2a\u6d88\u606f\uff0c\u4f46\u662f\u5728\u6d88\u8d39\u8fc7\u7a0b\u4e2d\u7a0b\u5e8f\u91cd\u542f\u4e86\u3002\u7531\u4e8e\u8fd9\u4e2a\u6d88\u606f\u6ca1\u6709\u88ab\u6807\u8bb0\u4e3a\u5df2\u7ecf\u88ab\u6d88\u8d39\u6210\u529f\uff0c\u6d88\u606f\u4e2d\u95f4\u4ef6\u4f1a\u6301\u7eed\u5730\u5c06\u8fd9\u4e2a\u6d88\u606f\u6295\u9012\u7ed9\u6d88\u8d39\u8005\uff0c\u76f4\u5230\u6d88\u606f\u88ab\u6210\u529f\u6d88\u8d39\u4e3a\u6b62\u3002<\/p>\n\n\n\n<p>\u7136\u800c\uff0c\u8fd9\u79cd\u53ef\u9760\u6027\u7279\u6027\u4e5f\u4f1a\u5bfc\u81f4\u6d88\u606f\u88ab\u591a\u6b21\u6295\u9012\u7684\u60c5\u51b5\u3002\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u4ecd\u7136\u4ee5\u4e4b\u524d\u7684\u4f8b\u5b50\u4e3a\u4f8b\uff0c\u5982\u679c\u6d88\u8d39\u7a0b\u5e8f A \u63a5\u6536\u5e76\u5b8c\u6210\u6d88\u606f M \u7684\u6d88\u8d39\u903b\u8f91\u540e\uff0c\u6b63\u51c6\u5907\u901a\u77e5\u6d88\u606f\u4e2d\u95f4\u4ef6\u201c\u6211\u5df2\u7ecf\u6d88\u8d39\u6210\u529f\u4e86\u201d\uff0c\u4f46\u5728\u6b64\u4e4b\u524d\u7a0b\u5e8fA\u53c8\u91cd\u542f\u4e86\uff0c\u90a3\u4e48\u5bf9\u4e8e\u6d88\u606f\u4e2d\u95f4\u4ef6\u6765\u8bf4\uff0c\u8fd9\u4e2a\u6d88\u606f M \u5e76\u6ca1\u6709\u88ab\u6210\u529f\u6d88\u8d39\u8fc7\uff0c\u56e0\u6b64\u6d88\u606f\u4e2d\u95f4\u4ef6\u4f1a\u7ee7\u7eed\u6295\u9012\u8fd9\u4e2a\u6d88\u606f\u3002\u800c\u5bf9\u4e8e\u6d88\u8d39\u7a0b\u5e8fA\u6765\u8bf4\uff0c\u5c3d\u7ba1\u5b83\u5df2\u7ecf\u6210\u529f\u6d88\u8d39\u4e86\u8fd9\u4e2a\u6d88\u606f\uff0c\u4f46\u7531\u4e8e\u7a0b\u5e8f\u91cd\u542f\u5bfc\u81f4\u6d88\u606f\u4e2d\u95f4\u4ef6\u7ee7\u7eed\u6295\u9012\uff0c\u770b\u8d77\u6765\u5c31\u597d\u50cf\u8fd9\u4e2a\u6d88\u606f\u8fd8\u6ca1\u6709\u88ab\u6210\u529f\u6d88\u8d39\u8fc7\u4e00\u6837\u3002<\/p>\n\n\n\n<p>\u5728 RockectMQ \u7684\u573a\u666f\u4e2d\uff0c\u8fd9\u610f\u5473\u7740\u540c\u4e00\u4e2a messageId \u7684\u6d88\u606f\u4f1a\u88ab\u91cd\u590d\u6295\u9012\u3002\u7531\u4e8e\u6d88\u606f\u7684\u53ef\u9760\u6295\u9012\u662f\u66f4\u91cd\u8981\u7684\uff0c\u6240\u4ee5\u907f\u514d\u6d88\u606f\u91cd\u590d\u6295\u9012\u7684\u4efb\u52a1\u8f6c\u79fb\u7ed9\u4e86\u5e94\u7528\u7a0b\u5e8f\u81ea\u8eab\u6765\u5b9e\u73b0\u3002\u8fd9\u4e5f\u662f RocketMQ \u6587\u6863\u5f3a\u8c03\u6d88\u8d39\u903b\u8f91\u9700\u8981\u81ea\u884c\u5b9e\u73b0\u5e42\u7b49\u6027\u7684\u539f\u56e0\u3002\u5b9e\u9645\u4e0a\uff0c\u8fd9\u80cc\u540e\u7684\u903b\u8f91\u662f\uff1a\u5728\u5206\u5e03\u5f0f\u573a\u666f\u4e0b\uff0c\u4fdd\u8bc1\u6d88\u606f\u4e0d\u4e22\u548c\u907f\u514d\u6d88\u606f\u91cd\u590d\u6295\u9012\u662f\u77db\u76fe\u7684\uff0c\u4f46\u662f\u6d88\u606f\u91cd\u590d\u6295\u9012\u662f\u53ef\u4ee5\u89e3\u51b3\u7684\uff0c\u800c\u6d88\u606f\u4e22\u5931\u5219\u975e\u5e38\u9ebb\u70e6\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240905_dev_coupon-distribute-v4_idempotent_ding.ma<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5e42\u7b49\u8bbe\u8ba1<\/h2>\n\n\n\n<p>\u4e0b\u8ff0\u65b9\u6848\u7684\u4f18\u70b9\u5728\u4e8e\uff0c\u4f7f\u7528 Redis \u6d88\u606f\u53bb\u91cd\u8868\uff0c\u4e0d\u4f9d\u8d56\u4e8b\u52a1\uff0c\u9488\u5bf9\u6d88\u606f\u8868\u672c\u8eab\u505a\u4e86\u72b6\u6001\u7684\u533a\u5206\uff1a\u6d88\u8d39\u4e2d\u3001\u6d88\u8d39\u5b8c\u6210\u3002<\/p>\n\n\n\n<p>\u5982\u679c\u6d88\u606f\u5df2\u7ecf\u5728\u6d88\u8d39\u4e2d\uff0c\u629b\u51fa\u5f02\u5e38\uff0c\u6d88\u606f\u4f1a\u89e6\u53d1\u5ef6\u8fdf\u6d88\u8d39\uff0c\u5728 RocketMQ \u7684\u573a\u666f\u4e0b\u5982\u679c\u6d88\u606f\u6d88\u8d39\u5931\u8d25\uff0c\u4f1a\u95f4\u9694\u65f6\u95f4\u540e\u518d\u6b21\u53d1\u8d77\u6d88\u8d39\u6d41\u7a0b\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240905220757945.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n<p>\u901a\u8fc7\u8be5\u65b9\u6848\u53ef\u4ee5\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898\uff1f<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u6d88\u606f\u5df2\u7ecf\u6d88\u8d39\u6210\u529f\u4e86\uff0c\u7b2c\u4e8c\u6761\u6d88\u606f\u5c06\u88ab\u76f4\u63a5\u5e42\u7b49\u5904\u7406\u6389\uff08\u6d88\u8d39\u6210\u529f\uff09\u3002<\/li>\n\n\n\n<li>2.\u5e76\u53d1\u573a\u666f\u4e0b\u7684\u6d88\u606f\uff0c\u4f9d\u65e7\u80fd\u6ee1\u8db3\u4e0d\u4f1a\u51fa\u73b0\u6d88\u606f\u91cd\u590d\uff0c\u5373\u7a7f\u900f\u5e42\u7b49\u6321\u677f\u7684\u95ee\u9898\u3002<\/li>\n\n\n\n<li>3.\u652f\u6301\u4e0a\u6e38\u4e1a\u52a1\u751f\u4ea7\u8005\u91cd\u53d1\u7684\u4e1a\u52a1\u91cd\u590d\u7684\u6d88\u606f\u5e42\u7b49\u95ee\u9898\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u4e3a\u4ec0\u4e48\u8981\u7ed9\u521d\u59cb\u5316\u7684\u5e42\u7b49\u6807\u8bc6\u65b0\u589e 10 \u5206\u949f\u8fc7\u671f\u65f6\u95f4\uff1f<\/p>\n\n\n\n<p>\u5728\u5e76\u53d1\u573a\u666f\u4e0b\uff0c\u6211\u4eec\u4f7f\u7528\u6d88\u606f\u72b6\u6001\u6765\u5b9e\u73b0\u5e76\u53d1\u63a7\u5236\uff0c\u4ee5\u4f7f\u7b2c\u4e8c\u6761\u6d88\u606f\u88ab\u4e0d\u65ad\u5ef6\u8fdf\u6d88\u8d39\uff08\u5373\u91cd\u8bd5\uff09\u3002\u4f46\u5982\u679c\u5728\u6b64\u671f\u95f4\u7b2c\u4e00\u6761\u6d88\u606f\u4e5f\u56e0\u67d0\u4e9b\u5f02\u5e38\u539f\u56e0\uff08\u4f8b\u5982\u673a\u5668\u91cd\u542f\u6216\u5916\u90e8\u5f02\u5e38\uff09\u672a\u6210\u529f\u6d88\u8d39\uff0c\u8be5\u600e\u4e48\u529e\u5462\uff1f\u56e0\u4e3a\u6bcf\u6b21\u67e5\u8be2\u65f6\u90fd\u4f1a\u663e\u793a\u6d88\u8d39\u4e2d\u7684\u72b6\u6001\uff0c\u6240\u4ee5\u5ef6\u8fdf\u6d88\u8d39\u4f1a\u4e00\u76f4\u8fdb\u884c\u4e0b\u53bb\uff0c\u76f4\u5230\u6700\u7ec8\u88ab\u89c6\u4e3a\u6d88\u8d39\u5931\u8d25\u5e76\u88ab\u6295\u9012\u5230\u6b7b\u4fe1 Topic \u4e2d\uff08RocketMQ \u9ed8\u8ba4\u6700\u591a\u53ef\u4ee5\u91cd\u590d\u6d88\u8d39 16 \u6b21\uff09\u3002<\/p>\n\n\n\n<p>\u9488\u5bf9\u8fd9\u4e2a\u95ee\u9898\uff0c\u6211\u4eec\u91c7\u53d6\u4e86\u4e00\u79cd\u89e3\u51b3\u65b9\u6848\uff1a\u5728\u63d2\u5165\u6d88\u606f\u8868\u65f6\uff0c\u5fc5\u987b\u4e3a\u6bcf\u6761\u6d88\u606f\u8bbe\u7f6e\u4e00\u4e2a\u6700\u957f\u6d88\u8d39\u8fc7\u671f\u65f6\u95f4\uff0c\u4f8b\u5982 10 \u5206\u949f\u3002\u8fd9\u610f\u5473\u7740\uff0c\u5982\u679c\u67d0\u4e2a\u6d88\u606f\u5728\u6d88\u8d39\u8fc7\u7a0b\u4e2d\u8d85\u8fc7\u4e86 10 \u5206\u949f\uff0c\u5c31\u4f1a\u88ab\u89c6\u4e3a\u6d88\u8d39\u5931\u8d25\u5e76\u4ece\u6d88\u606f\u8868\u4e2d\u5220\u9664\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u62bd\u8c61\u901a\u7528\u5e42\u7b49\u7ec4\u4ef6<\/h2>\n\n\n\n<p>\u6d88\u606f\u9632\u91cd\u590d\u6d88\u8d39\u5e42\u7b49\u7ec4\u4ef6\u662f\u901a\u7528\u7684\uff0c\u63a5\u4e0b\u6765\u7684\u4ee3\u7801\u5f00\u53d1\u8fd8\u662f\u4f1a\u653e\u5230 <code>framework<\/code> \u57fa\u7840\u67b6\u6784\u7ec4\u4ef6\u91cc\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240906101941114.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u81ea\u5b9a\u4e49\u5e42\u7b49\u6ce8\u89e3<\/h3>\n\n\n\n<p>\u6211\u4eec\u63d0\u4f9b\u4e86\u4e00\u79cd\u901a\u7528\u7684\u5e42\u7b49\u6ce8\u89e3\uff0c\u5e76\u901a\u8fc7 SpEL \u7684\u5f62\u5f0f\u751f\u6210\u53bb\u91cd\u8868\u5168\u5c40\u552f\u4e00 Key\u3002\u5982\u679c\u5bf9 SpEL \u4e0d\u719f\u6089\u7684\u540c\u5b66\uff0c\u79fb\u6b65\u67e5\u770b <a href=\"https:\/\/t.zsxq.com\/3HKAh\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >\u5386\u53f2\u7ae0\u8282<\/a> \u8fdb\u884c\u5b66\u4e60\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface NoMQDuplicateConsume {\n\u200b\n    \/**\n     * \u8bbe\u7f6e\u9632\u91cd\u4ee4\u724c Key \u524d\u7f00\n     *\/\n    String keyPrefix() default \"\";\n\u200b\n    \/**\n     * \u901a\u8fc7 SpEL \u8868\u8fbe\u5f0f\u751f\u6210\u7684\u552f\u4e00 Key\n     *\/\n    String key();\n\u200b\n    \/**\n     * \u8bbe\u7f6e\u9632\u91cd\u4ee4\u724c Key \u8fc7\u671f\u65f6\u95f4\uff0c\u5355\u4f4d\u79d2\uff0c\u9ed8\u8ba4 1 \u5c0f\u65f6\n     *\/\n    long keyTimeout() default 3600L;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2-aop\">2. \u5b9a\u4e49 AOP \u903b\u8f91\u589e\u5f3a<\/h3>\n\n\n\n<p>\u4e0a\u9762\u6211\u4eec\u6709\u8bf4\u5230\uff0c\u5e42\u7b49\u9700\u8981\u8bbe\u7f6e\u4e24\u4e2a\u72b6\u6001\uff0c\u6d88\u8d39\u4e2d\u548c\u5df2\u6d88\u8d39\uff0c\u521b\u5efa\u5bf9\u5e94\u7684\u679a\u4e3e\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n@RequiredArgsConstructor\npublic enum IdempotentMQConsumeStatusEnum {\n\u200b\n    \/**\n     * \u6d88\u8d39\u4e2d\n     *\/\n    CONSUMING(\"0\"),\n\u200b\n    \/**\n     * \u5df2\u6d88\u8d39\n     *\/\n    CONSUMED(\"1\");\n\u200b\n    @Getter\n    private final String code;\n\u200b\n    \/**\n     * \u5982\u679c\u6d88\u8d39\u72b6\u6001\u7b49\u4e8e\u6d88\u8d39\u4e2d\uff0c\u8fd4\u56de\u5931\u8d25\n     *\n     * @param consumeStatus \u6d88\u8d39\u72b6\u6001\n     * @return \u662f\u5426\u6d88\u8d39\u5931\u8d25\n     *\/\n    public static boolean isError(String consumeStatus) {\n        return Objects.equals(CONSUMING.code, consumeStatus);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\u63a5\u4e0b\u6765\u901a\u8fc7 AOP \u7684\u65b9\u5f0f\u8fdb\u884c\u589e\u5f3a\u6ce8\u89e3\uff0c\u5982\u679c\u8bf4\u65b9\u6cd5\u4e0a\u52a0\u4e86\u6ce8\u89e3\uff0c\u4f1a\u88ab\u8fd9\u6bb5 AOP \u4ee3\u7801\u4ee5\u73af\u7ed5\u589e\u5f3a\u65b9\u5f0f\u6267\u884c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n@Slf4j\n@Aspect\n@RequiredArgsConstructor\npublic final class NoMQDuplicateConsumeAspect {\n\u200b\n    private final StringRedisTemplate stringRedisTemplate;\n\u200b\n    private static final String LUA_SCRIPT = \"\"\"\n            local key = KEYS&#91;1]\n            local value = ARGV&#91;1]\n            local expire_time_ms = ARGV&#91;2]\n            return redis.call('SET', key, value, 'NX', 'GET', 'PX', expire_time_ms)\n            \"\"\";\n\u200b\n    \/**\n     * \u589e\u5f3a\u65b9\u6cd5\u6807\u8bb0 {@link NoMQDuplicateConsume} \u6ce8\u89e3\u903b\u8f91\n     *\/\n    @Around(\"@annotation(com.nageoffer.onecoupon.framework.idempotent.NoMQDuplicateConsume)\")\n    public Object noMQRepeatConsume(ProceedingJoinPoint joinPoint) throws Throwable {\n        NoMQDuplicateConsume noMQDuplicateConsume = getNoMQDuplicateConsumeAnnotation(joinPoint);\n        String uniqueKey = noMQDuplicateConsume.keyPrefix() + SpELUtil.parseKey(noMQDuplicateConsume.key(), ((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getArgs());\n\u200b\n        String absentAndGet = stringRedisTemplate.execute(\n                RedisScript.of(LUA_SCRIPT, String.class),\n                List.of(uniqueKey),\n                IdempotentMQConsumeStatusEnum.CONSUMING.getCode(),\n                String.valueOf(TimeUnit.SECONDS.toMillis(noMQDuplicateConsume.keyTimeout()))\n        );\n\u200b\n        \/\/ \u5982\u679c\u4e0d\u4e3a\u7a7a\u8bc1\u660e\u5df2\u7ecf\u6709\n        if (Objects.nonNull(absentAndGet)) {\n            boolean errorFlag = IdempotentMQConsumeStatusEnum.isError(absentAndGet);\n            log.warn(\"&#91;{}] MQ repeated consumption, {}.\", uniqueKey, errorFlag ? \"Wait for the client to delay consumption\" : \"Status is completed\");\n            if (errorFlag) {\n                throw new ServiceException(String.format(\"\u6d88\u606f\u6d88\u8d39\u8005\u5e42\u7b49\u5f02\u5e38\uff0c\u5e42\u7b49\u6807\u8bc6\uff1a%s\", uniqueKey));\n            }\n            return null;\n        }\n\u200b\n        Object result;\n        try {\n            \/\/ \u6267\u884c\u6807\u8bb0\u4e86\u6d88\u606f\u961f\u5217\u9632\u91cd\u590d\u6d88\u8d39\u6ce8\u89e3\u7684\u65b9\u6cd5\u539f\u903b\u8f91\n            result = joinPoint.proceed();\n\u200b\n            \/\/ \u8bbe\u7f6e\u9632\u91cd\u4ee4\u724c Key \u8fc7\u671f\u65f6\u95f4\uff0c\u5355\u4f4d\u79d2\n            stringRedisTemplate.opsForValue().set(uniqueKey, IdempotentMQConsumeStatusEnum.CONSUMED.getCode(), noMQDuplicateConsume.keyTimeout(), TimeUnit.SECONDS);\n        } catch (Throwable ex) {\n            \/\/ \u5220\u9664\u5e42\u7b49 Key\uff0c\u8ba9\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\u91cd\u8bd5\u903b\u8f91\u8fdb\u884c\u91cd\u65b0\u6d88\u8d39\n            stringRedisTemplate.delete(uniqueKey);\n            throw ex;\n        }\n        return result;\n    }\n\u200b\n    \/**\n     * @return \u8fd4\u56de\u81ea\u5b9a\u4e49\u9632\u91cd\u590d\u6d88\u8d39\u6ce8\u89e3\n     *\/\n    public static NoMQDuplicateConsume getNoMQDuplicateConsumeAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {\n        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();\n        Method targetMethod = joinPoint.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), methodSignature.getMethod().getParameterTypes());\n        return targetMethod.getAnnotation(NoMQDuplicateConsume.class);\n    }\n}<\/code><\/pre>\n\n\n\n<p>\u53ef\u80fd\u6709\u4e9b\u540c\u5b66\u4e0d\u592a\u719f\u6089 Lua \u811a\u672c\u8fd9\u4e2a\u547d\u4ee4\u4ee3\u8868\u7740\u4ec0\u4e48\uff0c\u6211\u4eec\u89e3\u91ca\u4e0b\u8fd9\u4e2a\u6982\u5ff5\uff0c\u8bed\u53e5\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local key =KEYS&#91;1] # \u7b2c\u4e00\u4e2a Key\uff0c\u5373\u5e42\u7b49\u552f\u4e00\u6807\u8bc6 uniqueKey\nlocal value =ARGV&#91;1] # \u7b2c\u4e00\u4e2a\u53c2\u6570\uff0c\u5373\u521d\u59cb\u5316\u5e42\u7b49\u6d88\u8d39\u72b6\u6001\uff0c\u4e3a\u6d88\u8d39\u4e2d\nlocal expire_time_ms =ARGV&#91;2] # \u7b2c\u4e8c\u4e2a\u53c2\u6570\uff0c\u5373\u5e42\u7b49 Key \u8fc7\u671f\u65f6\u95f4\n\u200b\nreturn redis.call('SET', key, value,'NX','GET','PX', expire_time_ms)<\/code><\/pre>\n\n\n\n<p>\u6700\u91cd\u8981\u7684\u662f\u8fd4\u56de\u503c\u90a3\u4e00\u884c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>SET key value<\/code>: \u5728 Redis \u4e2d\u8bbe\u7f6e <code>key<\/code> \u5bf9\u5e94\u7684\u503c\u4e3a <code>value<\/code>\u3002<\/li>\n\n\n\n<li><code>'NX'<\/code>: \u8868\u793a\u53ea\u6709\u5728 <code>key<\/code> \u4e0d\u5b58\u5728\u65f6\u624d\u6267\u884c\u8bbe\u7f6e\u64cd\u4f5c\uff0c\u9632\u6b62\u8986\u76d6\u5df2\u6709\u503c\u3002<\/li>\n\n\n\n<li><code>'GET'<\/code>: \u8868\u793a\u5728\u8bbe\u7f6e\u65b0\u503c\u4e4b\u524d\uff0c\u83b7\u53d6\u5e76\u8fd4\u56de\u8bbe\u7f6e\u524d\u7684\u65e7\u503c\uff08Redis 6.2 \u5f00\u59cb\u652f\u6301 <code>SET<\/code> \u547d\u4ee4\u7684 <code>GET<\/code> \u9009\u9879\uff09\u3002<\/li>\n\n\n\n<li><code>'PX expire_time_ms'<\/code>: \u8bbe\u7f6e <code>key<\/code> \u7684\u8fc7\u671f\u65f6\u95f4\uff0c\u5355\u4f4d\u662f\u6beb\u79d2\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u8be5\u811a\u672c\u7684\u4e3b\u8981\u4f5c\u7528\u662f\uff1a\u5728 Redis \u4e2d\u5c1d\u8bd5\u4ee5 <code>NX<\/code> \u65b9\u5f0f\u8bbe\u7f6e\u4e00\u4e2a\u952e\uff0c\u5373\u5982\u679c\u952e\u4e0d\u5b58\u5728\uff0c\u5219\u8bbe\u7f6e\u65b0\u503c\uff0c\u5e76\u8fd4\u56de\u8bbe\u7f6e\u4e4b\u524d\u7684\u65e7\u503c\uff0c\u540c\u65f6\u4e3a\u8be5\u952e\u8bbe\u7f6e\u8fc7\u671f\u65f6\u95f4\uff08\u4ee5\u6beb\u79d2\u4e3a\u5355\u4f4d\uff09\u3002<\/p>\n\n\n\n<p>\u83b7\u53d6\u5230 Redis \u91cc\u9762\u7684 Key \u503c\u540e\uff0c\u53ef\u80fd\u4f1a\u6709\u4e09\u4e2a\u6d41\u7a0b\u6267\u884c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>absentAndGet<\/code> \u4e3a\u7a7a\uff1a\u4ee3\u8868\u6d88\u606f\u662f\u7b2c\u4e00\u6b21\u5230\u8fbe\uff0c\u6267\u884c\u5b8c LUA \u811a\u672c\u540e\uff0c\u4f1a\u5728 Redis \u8bbe\u7f6e Key \u7684 Value \u503c\u4e3a 0\uff0c\u6d88\u8d39\u4e2d\u72b6\u6001\u3002<\/li>\n\n\n\n<li><code>absentAndGet<\/code> \u4e3a 0\uff1a\u4ee3\u8868\u5df2\u7ecf\u6709\u76f8\u540c\u6d88\u606f\u5230\u8fbe\u5e76\u4e14\u8fd8\u6ca1\u6709\u5904\u7406\u5b8c\uff0c\u4f1a\u901a\u8fc7\u629b\u5f02\u5e38\u7684\u5f62\u5f0f\u8ba9 RocketMQ \u91cd\u8bd5\u3002<\/li>\n\n\n\n<li><code>absentAndGet<\/code> \u4e3a 1\uff1a\u4ee3\u8868\u5df2\u7ecf\u6709\u76f8\u540c\u6d88\u606f\u6d88\u8d39\u5b8c\u6210\uff0c\u8fd4\u56de\u7a7a\u8868\u793a\u4e0d\u6267\u884c\u4efb\u4f55\u5904\u7406\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3-spring-bean\">3. \u6ce8\u518c\u4e3a Spring Bean<\/h3>\n\n\n\n<p>\u56e0\u4e3a\u4e4b\u524d Web \u63a5\u53e3\u9632\u91cd\u590d\u63d0\u4ea4\u6211\u4eec\u5df2\u7ecf\u8bbe\u7f6e\u4e86\u5e42\u7b49\u914d\u7f6e\u7c7b\uff0c\u6240\u4ee5\u8ffd\u52a0\u4e00\u4e2a @Bean \u5c31\u53ef\u4ee5\u4e86\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\npublic class IdempotentConfiguration {\n\u200b\n    \/**\n     * \u9632\u6b62\u7528\u6237\u91cd\u590d\u63d0\u4ea4\u8868\u5355\u4fe1\u606f\u5207\u9762\u63a7\u5236\u5668\n     *\/\n    @Bean\n    public NoDuplicateSubmitAspect noDuplicateSubmitAspect(RedissonClient redissonClient) {\n        return new NoDuplicateSubmitAspect(redissonClient);\n    }\n\u200b\n    \/**\n     * \u9632\u6b62\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\u91cd\u590d\u6d88\u8d39\u6d88\u606f\u5207\u9762\u63a7\u5236\u5668\n     *\/\n    @Bean\n    public NoMQDuplicateConsumeAspect noMQDuplicateConsumeAspect(StringRedisTemplate stringRedisTemplate) {\n        return new NoMQDuplicateConsumeAspect(stringRedisTemplate);\n    }\n}<\/code><\/pre>\n\n\n\n<p><code>org.springframework.boot.autoconfigure.AutoConfiguration.imports<\/code> \u6587\u4ef6\u4fdd\u6301\u4e0d\u53d8\u5c31\u597d\u4e86\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4\">4. \u5b9e\u9645\u4f7f\u7528\u573a\u666f<\/h3>\n\n\n\n<p>\u8fd9\u4e2a\u6d88\u606f\u9632\u91cd\u590d\u6ce8\u89e3\u9700\u8981\u52a0\u5230\u6211\u4eec\u7684 <code>CouponTaskExecuteConsumer<\/code> \u6d88\u8d39\u8005\u4e0a\uff0c\u56e0\u4e3a\u5982\u679c\u89e6\u53d1\u4e86\u91cd\u590d\u6d88\u8d39\uff0c\u610f\u5473\u7740\u4e00\u4e2a\u4f18\u60e0\u5238\u5206\u53d1\u4efb\u52a1\u4f1a\u6267\u884c\u4e24\u6b21\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Component\n@RequiredArgsConstructor\n@RocketMQMessageListener(\n        topic = DistributionRocketMQConstant.TEMPLATE_TASK_EXECUTE_TOPIC_KEY,\n        consumerGroup = DistributionRocketMQConstant.TEMPLATE_TASK_EXECUTE_CG_KEY\n)\n@Slf4j(topic = \"CouponTaskExecuteConsumer\")\npublic class CouponTaskExecuteConsumer implements RocketMQListener&lt;MessageWrapper&lt;CouponTaskExecuteEvent>> {\n\u200b\n    @NoMQDuplicateConsume(\n            keyPrefix = \"coupon_task_execute:idempotent:\",\n            key = \"#messageWrapper.message.couponTaskId\",\n            keyTimeout = 120\n    )\n    @Override\n    public void onMessage(MessageWrapper&lt;CouponTaskExecuteEvent> messageWrapper) {\n        \/\/ ......\n    }\n}<\/code><\/pre>\n\n\n\n<p><code>keyPrefix<\/code> \u548c <code>key<\/code> \u7ec4\u88c5\u6210\u5168\u5c40\u552f\u4e00\u7684\u5e42\u7b49\u6807\u8bc6\uff0ckeyTimeout \u610f\u5473\u7740\u6211\u4eec\u53ef\u4ee5\u4fdd\u6301 2 \u5206\u949f\u7684\u5e42\u7b49\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5e38\u89c1\u95ee\u9898\u7b54\u7591<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-2-10\">1. \u4e3a\u4ec0\u4e48\u8981\u8bbe\u7f6e 2 \u5206\u949f\u5e42\u7b49\uff1f10 \u5206\u949f\u4e0d\u884c\u4e48\uff1f<\/h3>\n\n\n\n<p>\u8fd9\u4e2a 2 \u5206\u949f\u662f\u4e2a\u7ecf\u9a8c\u503c\uff0c\u4e5f\u5c31\u662f\u8bf4\u4f60\u8fd9\u4e2a\u6d88\u606f\u6d88\u8d39\u7684\u65f6\u95f4\u662f\u5426\u80fd\u591f\u5728 2 \u5206\u949f\u5185\u6267\u884c\u5b8c\u6210\uff0c\u5982\u679c\u4e0d\u884c\u9700\u8981\u8bbe\u7f6e\u66f4\u957f\u7684\u65f6\u95f4\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2-2\">2. \u5982\u679c 2 \u5206\u949f\u5e42\u7b49\u7ed3\u675f\u540e\u6709\u65b0\u7684\u4e00\u6a21\u4e00\u6837\u7684\u8bf7\u6c42\u5462\uff1f<\/h3>\n\n\n\n<p>\u8fd9\u662f\u4e2a\u4f2a\u547d\u9898\uff0c\u4e00\u822c\u7684\u5e42\u7b49\u90fd\u662f\u56e0\u4e3a\u7f51\u7edc\u6296\u52a8\u540c\u65f6\u5230\u8fbe\uff0c\u4e0d\u592a\u53ef\u80fd\u4e00\u4e2a\u6d88\u606f\u90fd\u6267\u884c\u5b8c\u4e86\u633a\u957f\u65f6\u95f4\uff0c\u7136\u540e\u53c8\u6709\u4e00\u6a21\u4e00\u6837\u7684\u6d88\u606f\u518d\u6765\u6d88\u8d39\u3002<\/p>\n\n\n\n<p>\u5982\u679c\u9762\u8bd5\u5b98\u975e\u8981\u63ea\u7740\u8fd9\u4e2a\u70b9\u4e0d\u653e\u7684\u8bdd\uff0c\u53ef\u4ee5\u628a\u8fd9\u4e2a\u5e42\u7b49\u6807\u8bc6\u5b58\u653e\u5230 MySQL \u6570\u636e\u5e93\uff0c\u8fdb\u884c\u5206\u8868\u5b58\u50a8\u3002\u8fd9\u6837\u5b58\u4e2a 10 \u5929\u534a\u4e2a\u6708\u4e5f\u4e0d\u6015\u3002\u4f46\u662f\u8981\u6ce8\u610f\uff0cMySQL \u662f\u6ca1\u6709\u5230\u671f\u5220\u9664\u673a\u5236\u7684\uff0c\u8fd8\u5f97\u914d\u5408\u5b9a\u65f6\u4efb\u52a1\u5220\u9664\u4e4b\u524d\u7684\u65e0\u6548\u6570\u636e\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u600e\u4e48\u6d4b\u8bd5\u5e42\u7b49\uff1f<\/h3>\n\n\n\n<p>\u6211\u4eec\u628a Debug \u65ad\u70b9\u6253\u5230 <code>NoMQDuplicateConsumeAspect#noMQRepeatConsume<\/code> \u65b9\u6cd5\u91cc\uff0c\u7136\u540e\u5728\u771f\u6b63\u6267\u884c\u524d\uff0c\u53bb Redis \u53ef\u89c6\u5316\u5de5\u5177\u4e2d\u65b0\u589e\u5e42\u7b49\u503c\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240906102955481.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n<p>\u56e0\u4e3a\u8fd9\u4e2a\u5de5\u5177\u4e0d\u652f\u6301\u521b\u5efa Key \u7684\u65f6\u5019\u8bbe\u7f6e Value\uff0c\u6240\u4ee5\u6211\u4eec\u521b\u5efa\u597d\u540e\uff0c\u8fd8\u9700\u8981\u53bb\u8bbe\u7f6e\u4e0b\u5bf9\u5e94\u7684 Value \u4e3a 0 \u6216\u8005 1\uff0c\u8fd9\u6837\u5c31\u80fd\u6d4b\u8bd5\u5bf9\u5e94\u7684\u6d41\u7a0b\u4e86\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240906103508999.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u66f4\u590d\u6742\u7684\u5e42\u7b49\u573a\u666f<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u5e42\u7b49\u4e0d\u662f\u4e07\u80fd\u7684<\/h3>\n\n\n\n<p>\u5230\u8fd9\u91cc\uff0c\u65b9\u6848\u770b\u8d77\u6765\u975e\u5e38\u5b8c\u7f8e\uff0c\u6240\u6709\u7684\u6d88\u606f\u90fd\u53ef\u4ee5\u5feb\u901f\u63a5\u5165\u53bb\u91cd\uff0c\u800c\u4e14\u4e0e\u5177\u4f53\u4e1a\u52a1\u5b9e\u73b0\u5b8c\u5168\u89e3\u8026\u3002\u4f46\u662f\uff0c\u662f\u5426\u8fd9\u6837\u5c31\u53ef\u4ee5\u5b8c\u7f8e\u5730\u5b8c\u6210\u53bb\u91cd\u7684\u6240\u6709\u4efb\u52a1\u5462\uff1f<\/p>\n\n\n\n<p>\u5f88\u9057\u61be\uff0c\u5b9e\u9645\u4e0a\u5e76\u975e\u5982\u6b64\u3002\u56e0\u4e3a\u9700\u8981\u786e\u4fdd\u6d88\u606f\u81f3\u5c11\u6210\u529f\u6d88\u8d39\u4e00\u6b21\uff0c\u56e0\u6b64\u6d88\u606f\u5728\u6d88\u8d39\u8fc7\u7a0b\u4e2d\u6709\u53ef\u80fd\u5931\u8d25\u5e76\u89e6\u53d1\u91cd\u8bd5\u3002<\/p>\n\n\n\n<p>\u8fd8\u662f\u4ee5\u4e0a\u9762\u7684\u4f8b\u5b50\uff0c\u5047\u8bbe\u6d88\u606f\u6d88\u8d39\u7684\u6d41\u7a0b\u5305\u542b\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u68c0\u67e5\u5e93\u5b58\uff08RPC\uff09<\/li>\n\n\n\n<li>2.\u9501\u5e93\u5b58\uff08RPC\uff09<\/li>\n\n\n\n<li>3.\u5f00\u542f\u4e8b\u52a1\uff0c\u63d2\u5165\u8ba2\u5355\u8868\uff08MySQL\uff09<\/li>\n\n\n\n<li>4.\u8c03\u7528\u67d0\u4e9b\u5176\u4ed6\u4e0b\u6e38\u670d\u52a1\uff08RPC\uff09<\/li>\n\n\n\n<li>5.\u66f4\u65b0\u8ba2\u5355\u72b6\u6001<\/li>\n\n\n\n<li>6.commit \u4e8b\u52a1\uff08MySQL\uff09<\/li>\n<\/ol>\n\n\n\n<p>\u5f53\u6d88\u606f\u6d88\u8d39\u5230\u7b2c\u4e09\u6b65\u7684\u65f6\u5019\u5047\u8bbe MySQL \u5f02\u5e38\u5bfc\u81f4\u5931\u8d25\u4e86\uff0c\u89e6\u53d1\u6d88\u606f\u91cd\u8bd5\u3002\u5728\u91cd\u8bd5\u524d\u6211\u4eec\u4f1a\u5220\u9664\u5e42\u7b49\u8868\u7684\u8bb0\u5f55\uff0c\u6240\u4ee5\u6d88\u606f\u91cd\u8bd5\u7684\u65f6\u5019\u5c31\u4f1a\u91cd\u65b0\u8fdb\u5165\u6d88\u8d39\u4ee3\u7801\uff0c\u90a3\u4e48\u6b65\u9aa4 1 \u548c\u6b65\u9aa4 2 \u5c31\u4f1a\u91cd\u65b0\u518d\u6267\u884c\u4e00\u904d\u3002<\/p>\n\n\n\n<p>\u5982\u679c\u6b65\u9aa4 2 \u672c\u8eab\u4e0d\u662f\u5e42\u7b49\u7684\uff0c\u90a3\u4e48\u8fd9\u4e2a\u4e1a\u52a1\u6d88\u606f\u6d88\u8d39\u4f9d\u65e7\u6ca1\u6709\u505a\u597d\u5b8c\u6574\u7684\u5e42\u7b49\u5904\u7406\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u901a\u7528\u65b9\u6cd5\u5b9e\u73b0\u4ef7\u503c<\/h3>\n\n\n\n<p>\u5c3d\u7ba1\u8fd9\u79cd\u65b9\u5f0f\u5e76\u4e0d\u80fd\u5b8c\u5168\u89e3\u51b3\u6d88\u606f\u5e42\u7b49\u95ee\u9898\uff08\u4e8b\u5b9e\u4e0a\uff0c\u8f6f\u4ef6\u5de5\u7a0b\u9886\u57df\u91cc\u5f88\u5c11\u6709\u94f6\u5f39\u53ef\u4ee5\u5b8c\u5168\u89e3\u51b3\u95ee\u9898\uff09\uff0c\u4f46\u5b83\u4ecd\u7136\u5177\u6709\u5f88\u5927\u7684\u4ef7\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u7b80\u4fbf\u7684\u65b9\u5f0f\uff0c\u6211\u4eec\u80fd\u591f\u89e3\u51b3\u4ee5\u4e0b\u95ee\u9898\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u5404\u79cd\u7531\u4e8e Broker\u3001\u8d1f\u8f7d\u5747\u8861\u7b49\u539f\u56e0\u5bfc\u81f4\u7684\u6d88\u606f\u91cd\u6295\u9012\u7684\u91cd\u590d\u95ee\u9898\u3002<\/li>\n\n\n\n<li>2.\u5404\u79cd\u4e0a\u6e38\u751f\u4ea7\u8005\u5bfc\u81f4\u7684\u4e1a\u52a1\u7ea7\u522b\u6d88\u606f\u91cd\u590d\u95ee\u9898\u3002<\/li>\n\n\n\n<li>3.\u91cd\u590d\u6d88\u606f\u5e76\u53d1\u6d88\u8d39\u7684\u63a7\u5236\u7a97\u53e3\u95ee\u9898\uff0c\u5c31\u7b97\u91cd\u590d\uff0c\u91cd\u590d\u4e5f\u4e0d\u53ef\u80fd\u540c\u4e00\u65f6\u95f4\u8fdb\u5165\u6d88\u8d39\u903b\u8f91\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u4f7f\u7528\u8fd9\u79cd\u65b9\u6cd5\u53ef\u4ee5\u786e\u4fdd\u5728\u6b63\u5e38\u7684\u6d88\u8d39\u903b\u8f91\u573a\u666f\u4e0b\uff08\u65e0\u5f02\u5e38\uff0c\u65e0\u5f02\u5e38\u9000\u51fa\uff09\uff0c\u6d88\u606f\u7684\u5e42\u7b49\u6027\u5168\u90e8\u5f97\u5230\u89e3\u51b3\uff0c\u65e0\u8bba\u662f\u4e1a\u52a1\u91cd\u590d\u8fd8\u662f RocketMQ \u7279\u6027\u5e26\u6765\u7684\u91cd\u590d\u3002\u867d\u7136\u5b83\u4e0d\u662f\u89e3\u51b3\u6d88\u606f\u5e42\u7b49\u6027\u7684\u94f6\u5f39\uff0c\u4f46\u5b83\u4ee5\u4e00\u79cd\u7b80\u5355\u548c\u4fbf\u6377\u7684\u65b9\u5f0f\u63d0\u4f9b\u4e86\u89e3\u51b3\u65b9\u6848\u3002<\/p>\n\n\n\n<p>\u5b9e\u9645\u4e0a\uff0c\u8fd9\u79cd\u65b9\u6cd5\u5df2\u7ecf\u53ef\u4ee5\u89e3\u51b3 99% \u7684\u6d88\u606f\u91cd\u590d\u95ee\u9898\u4e86\uff0c\u56e0\u4e3a\u5f02\u5e38\u3001\u5b95\u673a\u7b49\u60c5\u51b5\u901a\u5e38\u662f\u5c11\u6570\u60c5\u51b5\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>6.2.6\u7684redis.call\u4e0d\u652f\u6301\u90a3\u4e48\u591a\u53c2\u6570\uff0cSET key val PX time NX GET\u4f1a\u62a5\u8bed\u6cd5\u9519\u8bef\uff0c\u53ea\u8ffd\u52a0NX\u6216GET\u4e2d\u7684\u4e00\u4e2a\u662f\u6ca1\u6709\u95ee\u9898\u7684\uff0c\u661f\u7403\u63d0\u4f9b\u76847.2.5\u662f\u53ef\u4ee5\u540c\u65f6\u8ffd\u52a0NX\u548cGET\u7684<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"213\" src=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357740-image-1024x213.png\" alt=\"\" class=\"wp-image-1310\" srcset=\"https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357740-image-1024x213.png 1024w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357740-image-300x62.png 300w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357740-image-768x160.png 768w, https:\/\/eve2333.top\/wp-content\/uploads\/2025\/09\/1758357740-image.png 1526w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\u6211\u561e\u4e2a\u8c46\uff0c\u5e38\u89c1\u95ee\u9898\u7684\u7b2c\u4e8c\u4e2a\u95ee\u9898\uff0c\u5c31\u662f\u5f53\u65f6\u9762\u8bd5\u5b98\u95ee\u6211\u7684\u95ee\u9898\uff08\u77ed\u94fe\u63a5\u7684\u9879\u76ee\uff09\uff0c\u6211\u5f53\u65f6\u786e\u5b9e\u5f80\u8fd9\u65b9\u9762\u60f3\u4e86\uff0c\u89c9\u5f97\u4e0d\u592a\u53ef\u80fd\u4f1a\u51fa\u73b0\u8fd9\u79cd\u60c5\u51b5\uff0c\u4f46\u662f\u5948\u4f55\u5f53\u65f6\u9762\u8bd5\u7684\u65f6\u5019\u7d27\u5f20+\u5634\u7b28\uff0c\u6ca1\u8bf4\u51fa\u6765= =<\/p>\n\n\n\n<p>\uacfc\ubaa9th\ud5c8jlS*&nbsp;\u56de\u590d&nbsp;\u5730\u4fe1\u54e5\uff1a\u5730\u4fe1\u54e5\uff0c\u6211\u770b\u5230rocketmq\u7684\u8d85\u65f6\u65f6\u95f4\u662f15min\uff0c\u5982\u679c\u6d88\u8d39\u8005\u6210\u529f\u6d88\u8d39\uff0c\u4f46\u662f\u6ca1\u6709\u8fd4\u56de\u7ed9broker ack\uff0c15min\u540e\u91cd\u65b0\u6295\u9012\uff0c\u90a3\u4e0d\u662f\u5e42\u7b49\u5931\u6548\u4e86\uff08\u5e42\u7b49\u7ec4\u4ef6\u624d2min\uff09<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u5982\u679c\u53d1\u73b0\u6d88\u606f\u5904\u4e8econsuming\u72b6\u6001\uff0c\u4e0d\u5c31\u8bf4\u660emq\u4e2d\u6709\u4e24\u4e2a\u6216\u4ee5\u4e0a\u7684\u540c\u79cd\u6d88\u606f\u5417\uff0c\u8ba9\u4e00\u6761\u6d88\u606f\u53bb\u6d88\u8d39\u4e0d\u5c31\u53ef\u4ee5\u4e86\uff0c\u53e6\u5916\u7684\u6d88\u606f\u76f4\u63a5\u653e\u5f03\uff0c\u5982\u679c\u4e0d\u653e\u5f03\u53cd\u800c\u91cd\u65b0\u6295\u9012\u7684\u8bdd\u4e0d\u4f1a\u5360\u7528\u8d44\u6e90\u5417\uff0c\u5982\u679c\u7b2c\u4e00\u6761\u6d88\u606f\u6d88\u8d39\u5931\u8d25\u4e86\uff0cmq\u4e5f\u80fd\u91cd\u65b0\u6295\u9012<\/p>\n\n\n\n<p>\u4e01\u82b1\u54e5&nbsp;\u56de\u590d&nbsp;rebcaaaaaa*\uff1a\u4f60\u8fd9\u4e2a\u6709\u903b\u8f91\u6f0f\u6d1e\uff0c\u5149\u770b\u4f60\u8bf4\u7684\u8fd9\u4e2a\u597d\u50cf\u6ca1\u6709\u95ee\u9898\u3002\u524d\u63d0\u6761\u4ef6\uff1a\u5c31\u662f\u4e00\u9047\u5230consuming\u72b6\u6001\u5c31\u8fd4\u56de\u6210\u529f(\u5e94\u8be5\u7406\u89e3\u6ca1\u6709\u9519\u5427)\u3002\u5047\u8bbe\u6d88\u606fM\uff0c\u521a\u88ab\u4e00\u6b21\u6d88\u8d39A\u6d88\u8d39\uff0credis\u72b6\u6001\u6539\u4e3aconsuming\uff0c\u5176\u4ed6\u64cd\u4f5c\u8fd8\u6ca1\u6709\u8fdb\u884c\uff0c\u5982\u679c\u8fd9\u4e2a\u65f6\u5019\u8fd9\u4e2a\u673a\u5668\u5b95\u673a\u4e86\uff0c\u90a3\u4e48\u4e0b\u6b21\u91cd\u65b0\u6295\u9012\u7ed9\u6d88\u8d39B\uff0c\u6d88\u8d39\u65f6redis\u72b6\u6001\u5df2\u7ecf\u662fconsuming\uff0c\u76f4\u63a5\u8fd4\u56de\u6210\u529f\uff0c\u8fd9\u6761\u6d88\u606f\u5c31\u6ca1\u6709\u6d88\u8d39\u8fc7\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u634b\u4e00\u4e0b\u601d\u8def\u3002\u76f4\u63a5\u4eceNoMQDuplicateConsumeAspect\u5207\u9762\u7c7b\u4e2d\u7684\u5f00\u59cb \u5728noMQRepeatConsume\u65b9\u6cd5\u4e2d\u9996\u5148\u6267\u884cgetNoMQDuplicateConsumeAnnotation\u65b9\u6cd5\u83b7\u53d6\u5207\u9762\u65b9\u6cd5\u4e0a\u9762\u7684\u6ce8\u89e3 \u7136\u540e\u5c06\u6ce8\u89e3\u4e0a\u9762\u7684keyPrefix\u548c\u6267\u884cSpELUtil.parseKey\u65b9\u6cd5\u83b7\u53d6\u5230\u7684messageWrapper.message.couponTaskId\u503c\u62fc\u63a5\u8d77\u6765\u4f5c\u4e3auniqueKey \u7136\u540e\u6267\u884clua\u811a\u672c\u83b7\u53d6\u5230redis\u8be5key\u7684\u503c\uff0c\u8be5lua\u811a\u672c\u7684\u6d41\u7a0b\u5c31\u662f\u83b7\u53d6\u539f\u59cb\u7684\u503c\uff0c\u5982\u679c\u6ca1\u6709\u5c31\u8bbe\u7f6e\u65b0\u7684\u503c\u548c\u8fc7\u671f\u65f6\u95f4 \u83b7\u53d6lua\u811a\u672c\u6267\u884c\u540e\u7684\u7ed3\u679c\u8d4b\u503c\u7ed9absentAndGet absentAndGet\u7684\u503c\u6709\u4e09\u79cd\u60c5\u51b5\uff1a \u5982\u679c\u4e3a\u7a7a\uff1a\u4ee3\u8868\u6d88\u606f\u662f\u7b2c\u4e00\u6b21\u5230\u8fbe\uff0c\u6267\u884c\u5b8c LUA \u811a\u672c\u540e\uff0c\u4f1a\u5728 Redis \u8bbe\u7f6e Key \u7684 Value \u503c\u4e3a 0\uff0c\u6d88\u8d39\u4e2d\u72b6\u6001\u3002 \u5982\u679c\u4e3a 0\uff1a\u4ee3\u8868\u5df2\u7ecf\u6709\u76f8\u540c\u6d88\u606f\u5230\u8fbe\u5e76\u4e14\u8fd8\u6ca1\u6709\u5904\u7406\u5b8c\uff0c\u4f1a\u901a\u8fc7\u629b\u5f02\u5e38\u7684\u5f62\u5f0f\u8ba9 RocketMQ \u91cd\u8bd5 \u5982\u679c\u4e3a 1\uff1a\u4ee3\u8868\u5df2\u7ecf\u6709\u76f8\u540c\u6d88\u606f\u6d88\u8d39\u5b8c\u6210\uff0c\u8fd4\u56de\u7a7a\u8868\u793a\u4e0d\u6267\u884c\u4efb\u4f55\u5904\u7406 \u5982\u679c\u4e0d\u4e3a\u7a7a\uff0c\u90a3\u5c31\u8bc1\u660e\u8be5\u6d88\u606f\u6b63\u5728\u6d88\u8d39\u6216\u8005\u6d88\u8d39\u5b8c\u6210\u3002 \u7136\u540e\u5224\u65ad\u662f\u5426\u662f\u6d88\u8d39\u4e2d\uff0c\u5982\u679c\u6d88\u8d39\u4e2d\u5c31\u624b\u52a8\u629b\u51faServiceException \u5982\u679c\u662f\u6d88\u8d39\u6210\u529f\uff0c\u90a3\u5c31\u76f4\u63a5return \u5982\u679c\u4e3a\u7a7a\uff0c\u90a3\u6b64\u65f6\u6d88\u606f\u5c31\u662f\u7b2c\u4e00\u6b21\u5230\u8fbe\uff0c\u90a3\u5c31\u5f00\u59cb\u6267\u884c\u6807\u8bb0\u4e86\u6d88\u606f\u961f\u5217\u9632\u91cd\u590d\u6d88\u8d39\u6ce8\u89e3\u7684\u65b9\u6cd5\u539f\u903b\u8f91 \u7531\u4e8e\u5728lua\u811a\u672c\u4e2d\u5c31\u5df2\u7ecf\u8ba9key\u7684\u503c\u8bbe\u7f6e\u4e3a\u6d88\u8d39\u4e2d\u4e86\uff0c\u6240\u4ee5\u5982\u679c\u5728\u6267\u884c\u7684\u8fc7\u7a0b\u4e2d\u6709\u6d88\u606f\u8fc7\u6765\u5c31\u4fdd\u8bc1\u4e0d\u4f1a\u91cd\u590d\u6d88\u8d39 \u6267\u884c\u5b8c\u4e86\u5c31\u8ba9\u7f13\u5b58\u4e2d\u7684\u503c\u8bbe\u7f6e\u4e3a\u6d88\u8d39\u5b8c\u6210\uff0c\u6267\u884c\u5b8c\u8fd4\u56de\u7ed3\u679c \u8fd9\u91cc\u6ce8\u610f\u4e00\u70b9\uff0c\u5982\u679cabsentAndGet\u4e0d\u4e3a\u7a7a\uff0c\u5e76\u4e14\u662f\u5728\u6d88\u8d39\u4e2d\u7684\u60c5\u51b5\uff0c\u4e0d\u80fd\u76f4\u63a5return\u3002(\u8bc4\u8bba\u533a\u7684\u4e00\u4f4d\u540c\u5b66\u7684\u4f8b\u5b50)\u5047\u8bbe\u6d88\u606fM\u7b2c\u4e00\u6b21\u88ab\u6d88\u8d39\u8005A\u6d88\u8d39\uff0credis\u72b6\u6001\u6539\u4e3aconsuming\uff0c\u5728\u6d88\u606f\u6d88\u8d39\u6210\u529f\u4e4b\u524d\uff0c\u5982\u679c\u8fd9\u4e2a\u65f6\u5019\u670d\u52a1\u5668\u5b95\u673a\u4e86\uff0c\u4e0b\u6b21\u91cd\u65b0\u6295\u9012\u7ed9\u6d88\u8d39\u8005A\uff0c\u7531\u4e8e\u6b64\u65f6redis\u72b6\u6001\u5df2\u7ecf\u662fconsuming\u4e86\uff0c\u90a3\u76f4\u63a5return\u7684\u8bdd\uff0c\u8fd9\u6761\u6d88\u606f\u4e4b\u540e\u5c31\u4e0d\u4f1a\u88ab\u6d88\u8d39\u6210\u529f\uff0c\u8fd9\u5c31\u662f\u4e00\u4e2abug\u3002\u4f46\u662f\u5982\u679c\u5728\u6d88\u8d39\u4e2d\u7684\u60c5\u51b5\u4e0b\u6211\u4eec\u629b\u51fa\u5f02\u5e38\uff0c\u53ef\u4ee5\u6210\u529f\u907f\u514d\u4e0a\u9762\u7684\u95ee\u9898\uff0c\u5e76\u4e14\uff0c\u5982\u679c\u6d88\u8d39\u8005A\u6d88\u8d39\u6210\u529f\u4e86\uff0c\u6839\u636e\u6211\u4eec\u7684\u4ee3\u7801\u53ef\u4ee5\u76f4\u63a5return\uff0c\u4e5f\u4e0d\u4f1a\u51fa\u73b0\u91cd\u590d\u6d88\u8d39\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c23\u5c0f\u8282\uff1a\u5f00\u53d1\u5151\u6362\/\u79d2\u6740\u4f18\u60e0\u5238\u529f\u80fd\uff08\u4e00\uff09<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u901a\u8fc7\u4e4b\u524d\u7684\u7ae0\u8282\uff0c\u6211\u4eec\u5df2\u7ecf\u628a\u4f18\u60e0\u5238\u76f8\u5173\u7684\u4e1a\u52a1\u94fa\u57ab\u7684\u5dee\u4e0d\u591a\u4e86\uff0c\u63a5\u4e0b\u6765\u6211\u4eec\u6b63\u5f0f\u5f00\u542f\u5f15\u64ce\u670d\u52a1\u7684\u4f18\u60e0\u5238\u5151\u6362\/\u79d2\u6740\u4e1a\u52a1\u3002<\/p>\n\n\n\n<p>\u666e\u901a\u5151\u6362\u81ea\u7136\u6ca1\u6709\u90a3\u4e48\u591a\u5f2f\u5f2f\u7ed5\u7ed5\uff0c\u4f46\u662f\u6d89\u53ca\u5230\u4e00\u4e9b\u6bd4\u8f83\u5927\u989d\u6216\u8005\u6709\u5438\u5f15\u529b\u7684\u4f18\u60e0\u5238\u6765\u8bf4\uff0c\u5c31\u4e0d\u4e00\u6837\u4e86\uff0c\u4f1a\u9762\u4e34\u5927\u91cf\u7528\u6237\u62a2\u8d2d\u5c11\u91cf\u7684\u5e93\u5b58\uff0c\u4e5f\u5c31\u662f\u6211\u4eec\u5e38\u8bf4\u7684\u79d2\u6740\u67b6\u6784\u3002\u548c\u5e38\u89c4\u7684\u79d2\u6740\u7cfb\u7edf\u4e00\u6837\uff0c\u6211\u4eec\u4e5f\u662f\u91c7\u7528\u4e86\u7f13\u5b58\u6297\u5e76\u53d1\u3001\u7136\u540e\u6263\u51cf\u7f13\u5b58\u6210\u529f\u7684\u8bf7\u6c42\u53ef\u4ee5\u8fdb\u884c\u6263\u51cf\u6570\u636e\u5e93\uff0c\u5e76\u5c06\u4f18\u60e0\u5238\u6dfb\u52a0\u5230\u7528\u6237\u7684\u9886\u5238\u8bb0\u5f55\u4e2d\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u6709\u4e00\u70b9\u9700\u8981\u548c\u5927\u5bb6\u5148\u8bf4\u660e\u4e0b\uff0c\u56e0\u4e3a\u4f18\u60e0\u5238\u7684\u9886\u53d6\u4e0d\u50cf 12306 \u4e00\u6837\u9700\u8981\u4fdd\u969c\u5f3a\u4e00\u81f4\u6027\uff0c\u6240\u4ee5\uff0c\u7406\u8bba\u4e0a\u53ef\u4ee5\u4ece\u6280\u672f\u65b9\u6848\u4e0a\u505a\u51cf\u6cd5\uff0c\u4f1a\u6709\u4e00\u4e9b\u5bb9\u5fcd\u6545\u969c\u3002<\/em><\/p>\n\n\n\n<p><em>\u518d\u548c\u5927\u5bb6\u591a\u626f\u4e00\u53e5\uff0c\u90a3\u5c31\u662f\u9762\u8bd5\u53ef\u4ee5\u9020\u706b\u7bad\uff0c\u4f46\u662f\u4f60\u5f97\u77e5\u9053\u590d\u6742\u6280\u672f\u65b9\u6848\u5e26\u6765\u7684\u843d\u5730\u96be\u5ea6\u95ee\u9898\u3002\u6709\u65f6\u5019\u9488\u5bf9\u6ca1\u90a3\u4e48\u91cd\u8981\u7684\u573a\u666f\uff0c\u65b9\u6848\u7b80\u5355\u7c97\u66b4\u4e00\u70b9\u5e76\u6ca1\u6709\u95ee\u9898\u3002\u5f88\u591a\u540c\u5b66\u4f1a\u8bf4\u7f13\u5b58\u5b95\u673a\u4e86\u600e\u4e48\u529e\uff1f\u7f13\u5b58\u4e3b\u4ece\u5f02\u6b65\u540c\u6b65\u4e22\u5931\u6570\u636e\u600e\u4e48\u529e\uff1f\u7f13\u5b58\u6263\u51cf\u6210\u529f\u6570\u636e\u5e93\u6ca1\u6263\u51cf\u65f6\u5e94\u7528\u5b95\u673a\u4e86\u600e\u4e48\u529e\uff1f\u8bf8\u5982\u6b64\u7c7b\uff0c\u53ea\u662f\u4e00\u5f20\u4f18\u60e0\u5238\u800c\u5df2\uff0c\u5176\u5b9e\u6ca1\u6709\u5565\u95ee\u9898\u3002<\/em><\/p>\n\n\n\n<p><em>\u867d\u7136\u6211\u4eec\u662f\u8fd9\u4e48\u8bf4\uff0c\u4f46\u8fd8\u662f\u4f1a\u4ee5\u8f83\u4e25\u8c28\u7684\u65b9\u5f0f\u7ed9\u5927\u5bb6\u8bb2\u89e3\u725b\u5238\u7684\u79d2\u6740\u67b6\u6784\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240908_dev_acquire-coupon_seckill_ding.ma<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u79d2\u6740\u4e1a\u52a1\u96be\u70b9<\/h2>\n\n\n\n<p>\u5728\u6211\u4eec\u5151\u6362\/\u79d2\u6740\u4f18\u60e0\u5238\u6a21\u677f\u7684\u63a5\u53e3\u4e2d\uff0c\u53ef\u80fd\u4f1a\u5b58\u5728\u4ee5\u4e0b\u4e09\u4e2a\u96be\u70b9\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9ad8\u5e76\u53d1\u6d41\u91cf\u538b\u529b\uff1a\u79d2\u6740\u6d3b\u52a8\u5f80\u5f80\u4f1a\u77ac\u95f4\u5438\u5f15\u5927\u91cf\u7528\u6237\u8bbf\u95ee\u7cfb\u7edf\uff0c\u5bfc\u81f4\u6d41\u91cf\u9aa4\u589e\uff0c\u5982\u679c\u76f4\u63a5\u8bbf\u95ee\u6570\u636e\u5e93\uff0c\u53ef\u80fd\u4f1a\u8ba9\u6570\u636e\u5e93\u8d1f\u8f7d\u8fc7\u91cd\uff0c\u751a\u81f3\u5bfc\u81f4\u5b95\u673a\u3002<\/li>\n\n\n\n<li>\u5e93\u5b58\u8d85\u5356\u95ee\u9898\uff1a\u7531\u4e8e\u5e76\u53d1\u8bf7\u6c42\uff0c\u591a\u4e2a\u7528\u6237\u540c\u65f6\u62a2\u8d2d\u53ef\u80fd\u4f1a\u5bfc\u81f4\u7cfb\u7edf\u8d85\u5356\uff0c\u5373\u591a\u4e2a\u7528\u6237\u540c\u65f6\u8d2d\u4e70\u5230\u540c\u4e00\u5e93\u5b58\u3002<\/li>\n\n\n\n<li>\u7528\u6237\u8d85\u9886\u95ee\u9898\uff1a\u4f18\u60e0\u5238\u4e2d\u4f1a\u6709\u4e00\u4e2a\u9650\u5236\uff0c\u6bcf\u4e2a\u7528\u6237\u9650\u6d41\u51e0\u5f20\uff0c\u5e94\u8be5\u5982\u4f55\u907f\u514d\u7528\u6237\u9886\u53d6\u8d85\u8fc7\u8fd9\u4e2a\u9650\u5236\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u5728\u63a5\u4e0b\u6765\u7684\u8bb2\u89e3\u4e2d\uff0c\u6211\u4eec\u4f1a\u9010\u4e00\u5b8c\u6210\u8fd9\u4e9b\u96be\u70b9\u8bf4\u660e\u548c\u89e3\u51b3\u65b9\u6848\u8bb2\u89e3\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4f18\u60e0\u5238\u79d2\u6740\u524d\u7f6e\u62e6\u622a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u9a8c\u8bc1\u4f18\u60e0\u5238<\/h3>\n\n\n\n<p>\u9996\u5148\u5462\uff0c\u6211\u4eec\u5e94\u8be5\u5bf9\u524d\u7aef\u4f20\u6765\u7684\u6570\u636e\u79c9\u627f\u7740\u5b8c\u5168\u4e0d\u53ef\u4fe1\u539f\u5219\uff0c\u9996\u5148\u9a8c\u8bc1\u662f\u5426\u5b58\u5728\uff0c\u5176\u6b21\u5462\u9a8c\u8bc1\u4f18\u60e0\u5238\u662f\u5426\u6709\u6548\u6d3b\u52a8\u671f\u95f4\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ \u9a8c\u8bc1\u7f13\u5b58\u662f\u5426\u5b58\u5728\uff0c\u4fdd\u969c\u6570\u636e\u5b58\u5728\u5e76\u4e14\u7f13\u5b58\u4e2d\u5b58\u5728CouponTemplateQueryRespDTO couponTemplate = couponTemplateService.findCouponTemplate(BeanUtil.toBean(requestParam,CouponTemplateQueryReqDTO.class));\n\u200b\n &nbsp; &nbsp;\/\/ \u9a8c\u8bc1\u9886\u53d6\u7684\u4f18\u60e0\u5238\u662f\u5426\u5728\u6d3b\u52a8\u6709\u6548\u65f6\u95f4boolean isInTime =DateUtil.isIn(newDate(), couponTemplate.getValidStartTime(), couponTemplate.getValidEndTime());if(!isInTime){\/\/ \u4e00\u822c\u6765\u8bf4\u4f18\u60e0\u5238\u9886\u53d6\u65f6\u95f4\u4e0d\u5230\u7684\u65f6\u5019\uff0c\u524d\u7aef\u4e0d\u4f1a\u653e\u5f00\u8c03\u7528\u8bf7\u6c42\uff0c\u53ef\u4ee5\u7406\u89e3\u8fd9\u662f\u7528\u6237\u8c03\u7528\u63a5\u53e3\u5728\u201c\u653b\u51fb\u201dthrownewClientException(\"\u4e0d\u6ee1\u8db3\u4f18\u60e0\u5238\u9886\u53d6\u65f6\u95f4\");}}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u6263\u51cf\u7f13\u5b58<\/h3>\n\n\n\n<p>\u5982\u679c\u9a8c\u8bc1\u4f18\u60e0\u5238\u6a21\u677f\u6ca1\u6709\u95ee\u9898\uff0c\u90a3\u6211\u4eec\u5f00\u59cb\u8fdb\u884c\u5e93\u5b58\u6263\u51cf\u548c\u9a8c\u8bc1\u7528\u6237\u662f\u5426\u9886\u53d6\u4f18\u60e0\u5238\u8d85\u989d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>privatefinalstaticStringSTOCK_DECREMENT_AND_SAVE_USER_RECEIVE_LUA_PATH=\"lua\/stock_decrement_and_save_user_receive.lua\";@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\/\/ \u83b7\u53d6 LUA \u811a\u672c\uff0c\u5e76\u4fdd\u5b58\u5230 Hutool \u7684\u5355\u4f8b\u7ba1\u7406\u5bb9\u5668\uff0c\u4e0b\u6b21\u76f4\u63a5\u83b7\u53d6\u4e0d\u9700\u8981\u52a0\u8f7dDefaultRedisScript&lt;Long&gt; buildLuaScript =Singleton.get(STOCK_DECREMENT_AND_SAVE_USER_RECEIVE_LUA_PATH,()-&gt;{DefaultRedisScript&lt;Long&gt; redisScript =newDefaultRedisScript&lt;&gt;();\n        redisScript.setScriptSource(newResourceScriptSource(newClassPathResource(STOCK_DECREMENT_AND_SAVE_USER_RECEIVE_LUA_PATH)));\n        redisScript.setResultType(Long.class);return redisScript;});\/\/ \u9a8c\u8bc1\u7528\u6237\u662f\u5426\u7b26\u5408\u4f18\u60e0\u5238\u9886\u53d6\u6761\u4ef6JSONObject receiveRule =JSON.parseObject(couponTemplate.getReceiveRule());String limitPerPerson = receiveRule.getString(\"limitPerPerson\");\/\/ \u6267\u884c LUA \u811a\u672c\u8fdb\u884c\u6263\u51cf\u5e93\u5b58\u4ee5\u53ca\u589e\u52a0 Redis \u7528\u6237\u9886\u5238\u8bb0\u5f55\u6b21\u6570String couponTemplateCacheKey =String.format(EngineRedisConstant.COUPON_TEMPLATE_KEY, requestParam.getCouponTemplateId());String userCouponTemplateLimitCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIMIT_KEY,UserContext.getUserId(), requestParam.getCouponTemplateId());Long stockDecrementLuaResult = stringRedisTemplate.execute(\n            buildLuaScript,ListUtil.of(couponTemplateCacheKey, userCouponTemplateLimitCacheKey),String.valueOf(couponTemplate.getValidEndTime().getTime()), limitPerPerson\n    );\/\/ \u5224\u65ad LUA \u811a\u672c\u6267\u884c\u8fd4\u56de\u7c7b\uff0c\u5982\u679c\u5931\u8d25\u6839\u636e\u7c7b\u578b\u8fd4\u56de\u62a5\u9519\u63d0\u793along firstField =StockDecrementReturnCombinedUtil.extractFirstField(stockDecrementLuaResult);if(RedisStockDecrementErrorEnum.isFail(firstField)){thrownewServiceException(RedisStockDecrementErrorEnum.fromType(firstField));}}<\/code><\/pre>\n\n\n\n<p>\u4e3a\u4e86\u907f\u514d\u8bbf\u95ee\u5e93\u5b58\u6263\u51cf\u548c\u5224\u65ad\u7528\u6237\u662f\u5426\u5df2\u8d85\u989d\u9886\u53d6\u4f18\u60e0\u5238\u591a\u6b21 Redis \u8bf7\u6c42\uff0c\u6240\u4ee5\u6211\u4eec\u8fd8\u662f\u4f9d\u7136\u91c7\u7528 Redis Lua \u811a\u672c\u6267\u884c\u3002<\/p>\n\n\n\n<p>Lua \u811a\u672c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>--Lua \u811a\u672c: \u68c0\u67e5\u7528\u6237\u662f\u5426\u8fbe\u5230\u4f18\u60e0\u5238\u9886\u53d6\u4e0a\u9650\u5e76\u8bb0\u5f55\u9886\u53d6\u6b21\u6570\n\n-- \u53c2\u6570\u5217\u8868\uff1a\n--KEYS&#91;1]: \u4f18\u60e0\u5238\u5e93\u5b58\u952e (coupon_stock_key)--KEYS&#91;2]: \u7528\u6237\u9886\u53d6\u8bb0\u5f55\u952e (user_coupon_key)--ARGV&#91;1]: \u4f18\u60e0\u5238\u6709\u6548\u671f\u7ed3\u675f\u65f6\u95f4 (timestamp)--ARGV&#91;2]: \u7528\u6237\u9886\u53d6\u4e0a\u9650 (limit)\n\nlocal function combineFields(firstField, secondField)-- \u786e\u5b9a SECOND_FIELD_BITS \u4e3a 14\uff0c\u56e0\u4e3a secondField \u6700\u5927\u4e3a 9999\n    local SECOND_FIELD_BITS=14-- \u6839\u636e firstField \u7684\u5b9e\u9645\u503c\uff0c\u8ba1\u7b97\u5176\u5bf9\u5e94\u7684\u4e8c\u8fdb\u5236\u8868\u793a\n    -- \u7531\u4e8e firstField \u7684\u8303\u56f4\u662f0-2\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5b83\u7684\u503c\n    local firstFieldValue = firstField\n\n    -- \u6a21\u62df\u4f4d\u79fb\u64cd\u4f5c\uff0c\u5c06 firstField \u7684\u503c\u5de6\u79fb SECOND_FIELD_BITS \u4f4d\n    local shiftedFirstField = firstFieldValue *(2^SECOND_FIELD_BITS)-- \u5c06 secondField \u7684\u503c\u4e0e\u4f4d\u79fb\u540e\u7684 firstField \u503c\u76f8\u52a0\n    return shiftedFirstField + secondField\nend\n\n-- \u83b7\u53d6\u5f53\u524d\u5e93\u5b58\nlocal stock =tonumber(redis.call('HGET',KEYS&#91;1],'stock'))-- \u5224\u65ad\u5e93\u5b58\u662f\u5426\u5927\u4e8e 0if stock &lt;=0 then\n    returncombineFields(1,0)-- \u5e93\u5b58\u4e0d\u8db3\nend\n\n-- \u83b7\u53d6\u7528\u6237\u9886\u53d6\u7684\u4f18\u60e0\u5238\u6b21\u6570\nlocal userCouponCount =tonumber(redis.call('GET',KEYS&#91;2]))-- \u5982\u679c\u7528\u6237\u9886\u53d6\u6b21\u6570\u4e0d\u5b58\u5728\uff0c\u5219\u521d\u59cb\u5316\u4e3a 0if userCouponCount == nil then\n    userCouponCount =0\nend\n\n-- \u5224\u65ad\u7528\u6237\u662f\u5426\u5df2\u7ecf\u8fbe\u5230\u9886\u53d6\u4e0a\u9650\nif userCouponCount &gt;=tonumber(ARGV&#91;2]) then\n    returncombineFields(2, userCouponCount)-- \u7528\u6237\u5df2\u7ecf\u8fbe\u5230\u9886\u53d6\u4e0a\u9650\nend\n\n-- \u589e\u52a0\u7528\u6237\u9886\u53d6\u7684\u4f18\u60e0\u5238\u6b21\u6570\nif userCouponCount ==0 then\n    -- \u5982\u679c\u7528\u6237\u7b2c\u4e00\u6b21\u9886\u53d6\uff0c\u5219\u9700\u8981\u6dfb\u52a0\u8fc7\u671f\u65f6\u95f4\n    redis.call('SET',KEYS&#91;2],1)\n    redis.call('EXPIRE',KEYS&#91;2],ARGV&#91;1])else-- \u56e0\u4e3a\u7b2c\u4e00\u6b21\u9886\u53d6\u5df2\u7ecf\u8bbe\u7f6e\u4e86\u8fc7\u671f\u65f6\u95f4\uff0c\u7b2c\u4e8c\u6b21\u9886\u53d6\u6cbf\u7528\u4e4b\u524d\u5373\u53ef\n    redis.call('INCR',KEYS&#91;2])\nend\n\n-- \u51cf\u5c11\u4f18\u60e0\u5238\u5e93\u5b58\nredis.call('HINCRBY',KEYS&#91;1],'stock',-1)returncombineFields(0, userCouponCount)<\/code><\/pre>\n\n\n\n<p>\u8fd9\u91cc\u6211\u4eec\u8fd8\u662f\u91c7\u7528\u4e86\u4e4b\u524d\u7684\u7b56\u7565\uff0c\u5c06\u8fd4\u56de\u7684\u4e24\u4e2a\u53c2\u6570\u5305\u88c5\u4e3a\u4e00\u4e2a long \u7c7b\u578b\u7684\u6570\u636e\uff0c\u5e76\u8fdb\u884c\u62c6\u5206\u3002\u4e24\u4e2a\u53c2\u6570\u5206\u522b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u8bf7\u6c42\u662f\u5426\u6210\u529f\uff1a\u6709 3 \u4e2a\u53c2\u6570\uff0c0 \u4ee3\u8868\u8bf7\u6c42\u6210\u529f\uff0c1 \u4ee3\u8868\u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u5566\uff0c2 \u4ee3\u8868\u7528\u6237\u5df2\u7ecf\u8fbe\u5230\u9886\u53d6\u4e0a\u9650\u3002<\/li>\n\n\n\n<li>\u7528\u6237\u9886\u53d6\u6b21\u6570\uff1a\u521d\u59cb\u5316\u4e3a 0\uff0c\u6bcf\u6b21\u9886\u53d6\u6210\u529f\u540e\u81ea\u589e\u52a0 1\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u5982\u679c\u8fd4\u56de 0,x \u4ee3\u8868\u8bf7\u6c42\u6210\u529f\uff0cx \u5c31\u662f\u76ee\u524d\u7528\u6237\u5df2\u9886\u53d6\u4f18\u60e0\u5238\u7684\u6b21\u6570\uff0c\u4f1a\u628a\u8fd9\u4e2a x \u4fdd\u5b58\u5230\u6570\u636e\u5e93\u8868 <code>t_user_coupon<\/code> \u7684\u9886\u53d6\u6b21\u6570 <code>receive_count \u5b57\u6bb5\u4e2d\u3002<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4f18\u60e0\u5238\u4fdd\u5b58\u6570\u636e\u5e93<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-my-sql\">1. \u6263\u51cf MySQL \u4f18\u60e0\u5238\u5e93\u5b58<\/h3>\n\n\n\n<p>\u56e0\u4e3a\u6211\u4eec\u8981\u52a0\u4e8b\u52a1\uff0c\u4e2d\u95f4\u9047\u5230\u95ee\u9898\u53ef\u4ee5\u56de\u6eda\u6570\u636e\u5e93\u4f18\u60e0\u5238\u6a21\u677f\u5e93\u5b58\uff0c\u4f46\u662f\u5982\u679c\u52a0\u5230\u6574\u4e2a\u65b9\u6cd5\u611f\u89c9\u53c8\u4e0d\u662f\u5f88\u5408\u9002\uff0c\u56e0\u4e3a\u524d\u9762\u7684\u9a8c\u8bc1\u662f\u4e0d\u9700\u8981\u4e8b\u52a1\u7684\u3002\u6240\u4ee5\uff0c\u6211\u4eec\u91c7\u7528\u7f16\u7a0b\u5f0f\u4e8b\u52a1\uff0c\u81ea\u5df1\u5f00\u542f\u3001\u63d0\u4ea4\u548c\u56de\u6eda\u4e8b\u52a1\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>privatefinalTransactionTemplate transactionTemplate;@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u6267\u884c\u4f18\u60e0\u5238\u5e93\u5b58\u81ea\u51cf\u4ee5\u53ca\u589e\u52a0\u7528\u6237\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55long extractSecondField =StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult);\n    transactionTemplate.executeWithoutResult(status -&gt;{try{int decremented = couponTemplateMapper.decrementCouponTemplateStock(Long.parseLong(requestParam.getShopNumber()),Long.parseLong(requestParam.getCouponTemplateId()),1L);if(!SqlHelper.retBool(decremented)){thrownewServiceException(\"\u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u5566\");}\/\/ \u6dfb\u52a0 Redis \u7528\u6237\u9886\u53d6\u7684\u4f18\u60e0\u5238\u8bb0\u5f55\u5217\u8868Date now =newDate();DateTime validEndTime =DateUtil.offsetHour(now,JSON.parseObject(couponTemplate.getConsumeRule()).getInteger(\"validityPeriod\"));UserCouponDO userCouponDO =UserCouponDO.builder().couponTemplateId(Long.parseLong(requestParam.getCouponTemplateId())).userId(Long.parseLong(UserContext.getUserId())).source(requestParam.getSource()).receiveCount(Long.valueOf(extractSecondField).intValue()).status(UserCouponStatusEnum.UNUSED.getCode()).receiveTime(now).validStartTime(now).validEndTime(validEndTime).build();\n            userCouponMapper.insert(userCouponDO);}catch(Exception ex){\n            status.setRollbackOnly();\/\/ \u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u4e1a\u52a1\u5f02\u5e38if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n                log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}});}<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u5728\u8fdb\u884c\u5e93\u5b58\u6263\u51cf\u65f6\uff0c\u91c7\u7528 MySQL \u7684\u884c\u8bb0\u5f55\u9501\u673a\u5236\u8fdb\u884c\u6263\u51cf\u3002\u5e76\u4e14\u5728\u6263\u51cf\u7684\u57fa\u7840\u4e0a\uff0c\u4e3a\u4e86\u907f\u514d\u88ab\u591a\u6263\uff0c\u5728\u5224\u65ad\u6761\u4ef6\u91cc\uff0c\u6211\u4eec\u52a0\u4e0a\u4e86\u5fc5\u987b\u5927\u4e8e\u7b49\u4e8e\u5f53\u524d\u5e93\u5b58\u624d\u53ef\u4ee5\u6263\u51cf\u6210\u529f\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u4ece\u96f6\u5230\u4e00\u5206\u652f\u91cc\u6ce8\u91ca\u5199\u9519\u4e86\uff0c\u4ee5\u672c\u7ae0\u8282\u6ce8\u91ca\u4e3a\u4e3b\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>SQL \u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- \u901a\u8fc7 MySQL \u7684\u884c\u8bb0\u5f55\u9501\u673a\u5236\u539f\u5b50\u6263\u51cf\u4f18\u60e0\u5238\u6a21\u677f\u5e93\u5b58 --&gt;&lt;update id=\"decrementCouponTemplateStock\"&gt;UPDATE t_coupon_template\n    SET stock = stock - #{decrementStock}WHERE shop_number = #{shopNumber}AND id = #{couponTemplateId}AND stock &gt;= #{decrementStock}&lt;\/update&gt;<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u4e4b\u524d\u7684\u7ae0\u8282\u8bc1\u660e\uff0c\u8fd9\u4e2a SQL \u8bb0\u5f55\u672c\u8d28\u4e0a\u5e95\u5c42\u8fd8\u662f MySQL \u884c\u9501\uff0c\u907f\u514d\u6263\u51cf\u51b2\u7a81\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u8be6\u60c5\u67e5\u770b\u725b\u5238\u4e4b\u524d\u7684 <a href=\"https:\/\/t.zsxq.com\/LxDx8\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >\u5386\u53f2\u6587\u7ae0<\/a> \u6587\u672b\u5185\u5bb9\uff0c\u6709\u8be6\u7ec6\u7684\u56fe\u6587\u8bb2\u89e3\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u6dfb\u52a0\u7528\u6237\u9886\u5238\u8bb0\u5f55<\/h3>\n\n\n\n<p>\u5982\u679c\u6263\u51cf\u6570\u636e\u5e93\u6210\u529f\uff0c\u90a3\u6211\u4eec\u5219\u5c06\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55\u4fdd\u5b58\u5230 <code>t_user_coupon<\/code> \u8868\u4e2d\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u6e29\u99a8\u63d0\u793a\uff0c\u56e0\u4e3a\u6211\u4eec\u662f\u5728\u914d\u7f6e\u4e2d\u56fa\u5b9a\u5199\u7684\u7528\u6237 ID\uff0c\u6240\u4ee5\u6570\u636e\u90fd\u4f1a\u5199\u5230 0 \u5e93\u7684 <code>t_user_coupon_13<\/code> \u8868\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u52a0\u4e86\u4e00\u4e9b\u4f18\u5316\uff0c\u90a3\u5c31\u662f\u6dfb\u52a0\u4f18\u60e0\u5238\u65f6\uff0c\u53ef\u80fd\u4f1a\u6709\u7528\u6237\u91cd\u590d\u9886\u5238\u51b2\u7a81\u3001\u518d\u6bd4\u5982\u6570\u636e\u5e93\u5b95\u673a\u4e4b\u7c7b\u7684\u95ee\u9898\uff0c\u6240\u4ee5\u6211\u4eec\u9488\u5bf9\u4e0d\u540c\u7684\u5f02\u5e38\u8fdb\u884c\u4e86\u524d\u7aef\u62a5\u9519\u4fe1\u606f\u63d0\u793a\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n    log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u4fdd\u5b58\u7528\u6237\u9886\u5238\u7f13\u5b58<\/h3>\n\n\n\n<p>\u6dfb\u52a0\u6570\u636e\u5e93\u5982\u679c\u6ca1\u6709\u5f02\u5e38\u7684\u8bdd\uff0c\u90a3\u6211\u4eec\u5e94\u8be5\u5c06\u7528\u6237\u5df2\u9886\u53d6\u7684\u4f18\u60e0\u5238\u6dfb\u52a0\u5230 Redis \u7f13\u5b58\u4e2d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>privatefinalTransactionTemplate transactionTemplate;@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u6267\u884c\u4f18\u60e0\u5238\u5e93\u5b58\u81ea\u51cf\u4ee5\u53ca\u589e\u52a0\u7528\u6237\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55long extractSecondField =StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult);\n    transactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ ......\/\/ \u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u8bb0\u5f55String userCouponListCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIST_KEY,UserContext.getUserId());String userCouponItemCacheKey =StrUtil.builder().append(requestParam.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\n            stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}catch(Exception ex){\n            status.setRollbackOnly();\/\/ \u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u4e1a\u52a1\u5f02\u5e38if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n                log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}});}<\/code><\/pre>\n\n\n\n<p>\u5927\u5bb6\u90fd\u77e5\u9053\uff0c\u5982\u679c\u4fdd\u5b58 Redis \u540e\uff0cRedis \u5373\u4f7f\u8fd4\u56de\u7ed9\u4f60\u6210\u529f\uff0c\u4f46\u662f\u6570\u636e\u4e0d\u4e00\u5b9a\u662f\u80fd\u6301\u4e45\u5316\u6210\u529f\u7684\uff0c\u56e0\u4e3a\u5728\u6781\u7aef\u5b95\u673a\u60c5\u51b5\u4e0b\uff0c\u6301\u4e45\u5316\u914d\u7f6e\u4e2d AOF \u6700\u4f18\u7ed3\u679c\u4e0b\uff0c\u4e5f\u662f\u4f1a\u4e22\u4e00\u6761\u6570\u636e\u7684\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u8be6\u60c5\u67e5\u770b\uff1a<a href=\"https:\/\/open8gu.com\/redis\/persistent\/oegct3ayo729baqc\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >\u5927\u8bdd\u9762\u8bd5\uff1aRedis\u5b95\u673a\u6570\u636e\u4f1a\u4e22\u5931\u4e48\uff1f<\/a><\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u9664\u4e86\u6301\u4e45\u5316\u914d\u7f6e\uff0cRedis \u5982\u679c\u662f\u4e3b\u4ece\u914d\u7f6e\uff0c\u4e3b\u4ece\u6570\u636e\u540c\u6b65\u662f\u5f02\u6b65\u7684\uff0c\u5982\u679c\u4e3b\u8282\u70b9\u5199\u5165\u6210\u529f\uff0c\u8fd4\u56de\u5ba2\u6237\u7aef\u6210\u529f\uff0c\u8fd8\u6ca1\u6765\u5f97\u53ca\u540c\u6b65\u4ece\u8282\u70b9\u5b95\u673a\u4e86\uff0c\u4ece\u8282\u70b9\u6210\u4e3a\u4e3b\u8282\u70b9\uff0c\u90a3\u4e48\u8fd9\u4e2a\u6570\u636e\u5c31\u6210\u7cca\u6d82\u8d26\u4e86\u3002<\/p>\n\n\n\n<p>\u4e3a\u6b64\uff0c\u6211\u4eec\u5199\u4e86\u4e00\u4e2a\u5f88\u516b\u80a1\u7684\u5199\u6cd5\uff0c\u90a3\u5c31\u662f\u901a\u8fc7\u5148\u5199\u518d\u67e5\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>privatefinalTransactionTemplate transactionTemplate;@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u6267\u884c\u4f18\u60e0\u5238\u5e93\u5b58\u81ea\u51cf\u4ee5\u53ca\u589e\u52a0\u7528\u6237\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55long extractSecondField =StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult);\n    transactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ ......\/\/ \u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u8bb0\u5f55String userCouponListCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIST_KEY,UserContext.getUserId());String userCouponItemCacheKey =StrUtil.builder().append(requestParam.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\n            stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());\/\/ \u7531\u4e8e Redis \u5728\u6301\u4e45\u5316\u6216\u4e3b\u4ece\u590d\u5236\u7684\u6781\u7aef\u60c5\u51b5\u4e0b\u53ef\u80fd\u4f1a\u51fa\u73b0\u6570\u636e\u4e22\u5931\uff0c\u800c\u6211\u4eec\u5bf9\u6307\u4ee4\u4e22\u5931\u51e0\u4e4e\u65e0\u6cd5\u5bb9\u5fcd\uff0c\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u7ecf\u5178\u7684\u5199\u540e\u67e5\u8be2\u7b56\u7565\u6765\u5e94\u5bf9\u8fd9\u4e00\u95ee\u9898Double scored;try{\n                scored = stringRedisTemplate.opsForZSet().score(userCouponListCacheKey, userCouponItemCacheKey);\/\/ scored \u4e3a\u7a7a\u610f\u5473\u7740\u53ef\u80fd Redis Cluster \u4e3b\u4ece\u540c\u6b65\u4e22\u5931\u4e86\u6570\u636e\uff0c\u6bd4\u5982 Redis \u4e3b\u8282\u70b9\u8fd8\u6ca1\u6709\u540c\u6b65\u5230\u4ece\u8282\u70b9\u5c31\u5b95\u673a\u4e86\uff0c\u89e3\u51b3\u65b9\u6848\u5c31\u662f\u518d\u65b0\u589e\u4e00\u6b21if(scored ==null){\/\/ \u5982\u679c\u8fd9\u91cc\u4e5f\u65b0\u589e\u5931\u8d25\u4e86\u600e\u4e48\u529e\uff1f\u6211\u4eec\u5927\u6982\u7387\u505a\u4e0d\u5230\u7edd\u5bf9\u7684\u4e07\u65e0\u4e00\u5931\uff0c\u53ea\u80fd\u5c3d\u53ef\u80fd\u589e\u52a0\u6210\u529f\u7387\n                    stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}}catch(Throwable ex){\n                log.warn(\"\u67e5\u8be2Redis\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u4e3a\u7a7a\u6216\u629b\u5f02\u5e38\uff0c\u53ef\u80fdRedis\u5b95\u673a\u6216\u4e3b\u4ece\u590d\u5236\u6570\u636e\u4e22\u5931\uff0c\u57fa\u7840\u9519\u8bef\u4fe1\u606f\uff1a{}\", ex.getMessage());\/\/ \u5982\u679c\u76f4\u63a5\u629b\u5f02\u5e38\u5927\u6982\u7387 Redis \u5b95\u673a\u4e86\uff0c\u6240\u4ee5\u5e94\u8be5\u5199\u4e2a\u5ef6\u65f6\u961f\u5217\u5411 Redis \u91cd\u8bd5\u653e\u5165\u503c\u3002\u4e3a\u4e86\u907f\u514d\u4ee3\u7801\u590d\u6742\u6027\uff0c\u8fd9\u91cc\u76f4\u63a5\u5199\u65b0\u589e\uff0c\u5927\u5bb6\u77e5\u9053\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5373\u53ef\n                stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}}catch(Exception ex){\n            status.setRollbackOnly();\/\/ \u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u4e1a\u52a1\u5f02\u5e38if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n                log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}});}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4\">4. \u53d1\u9001\u4f18\u60e0\u5238\u5230\u671f\u4e8b\u4ef6<\/h3>\n\n\n\n<p>\u5728\u4e0a\u9762\u4ee3\u7801\u7684\u57fa\u7840\u4e0a\uff0c\u5982\u679c\u90fd\u6267\u884c\u6210\u529f\uff0c\u6211\u4eec\u9700\u8981\u53d1\u9001\u4e2a RocketMQ \u5ef6\u65f6\u961f\u5217\uff0c\u5728\u6307\u5b9a\u65f6\u95f4\u540e\u5c06\u4f18\u60e0\u5238\u6a21\u677f\u7684\u72b6\u6001\u8bbe\u7f6e\u4e3a\u5df2\u8fc7\u671f\u72b6\u6001\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>privatefinalTransactionTemplate transactionTemplate;\n\u200b\n@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\n\u200b\n &nbsp; &nbsp;\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u6267\u884c\u4f18\u60e0\u5238\u5e93\u5b58\u81ea\u51cf\u4ee5\u53ca\u589e\u52a0\u7528\u6237\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55long extractSecondField =StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult);\n &nbsp; &nbsp;transactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ ......\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u8bb0\u5f55String userCouponListCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIST_KEY,UserContext.getUserId());String userCouponItemCacheKey =StrUtil.builder().append(requestParam.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u7531\u4e8e Redis \u5728\u6301\u4e45\u5316\u6216\u4e3b\u4ece\u590d\u5236\u7684\u6781\u7aef\u60c5\u51b5\u4e0b\u53ef\u80fd\u4f1a\u51fa\u73b0\u6570\u636e\u4e22\u5931\uff0c\u800c\u6211\u4eec\u5bf9\u6307\u4ee4\u4e22\u5931\u51e0\u4e4e\u65e0\u6cd5\u5bb9\u5fcd\uff0c\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u7ecf\u5178\u7684\u5199\u540e\u67e5\u8be2\u7b56\u7565\u6765\u5e94\u5bf9\u8fd9\u4e00\u95ee\u9898Double scored;try{\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;scored = stringRedisTemplate.opsForZSet().score(userCouponListCacheKey, userCouponItemCacheKey);\/\/ scored \u4e3a\u7a7a\u610f\u5473\u7740\u53ef\u80fd Redis Cluster \u4e3b\u4ece\u540c\u6b65\u4e22\u5931\u4e86\u6570\u636e\uff0c\u6bd4\u5982 Redis \u4e3b\u8282\u70b9\u8fd8\u6ca1\u6709\u540c\u6b65\u5230\u4ece\u8282\u70b9\u5c31\u5b95\u673a\u4e86\uff0c\u89e3\u51b3\u65b9\u6848\u5c31\u662f\u518d\u65b0\u589e\u4e00\u6b21if(scored ==null){\/\/ \u5982\u679c\u8fd9\u91cc\u4e5f\u65b0\u589e\u5931\u8d25\u4e86\u600e\u4e48\u529e\uff1f\u6211\u4eec\u5927\u6982\u7387\u505a\u4e0d\u5230\u7edd\u5bf9\u7684\u4e07\u65e0\u4e00\u5931\uff0c\u53ea\u80fd\u5c3d\u53ef\u80fd\u589e\u52a0\u6210\u529f\u7387\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}}catch(Throwable ex){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"\u67e5\u8be2Redis\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u4e3a\u7a7a\u6216\u629b\u5f02\u5e38\uff0c\u53ef\u80fdRedis\u5b95\u673a\u6216\u4e3b\u4ece\u590d\u5236\u6570\u636e\u4e22\u5931\uff0c\u57fa\u7840\u9519\u8bef\u4fe1\u606f\uff1a{}\", ex.getMessage());\/\/ \u5982\u679c\u76f4\u63a5\u629b\u5f02\u5e38\u5927\u6982\u7387 Redis \u5b95\u673a\u4e86\uff0c\u6240\u4ee5\u5e94\u8be5\u5199\u4e2a\u5ef6\u65f6\u961f\u5217\u5411 Redis \u91cd\u8bd5\u653e\u5165\u503c\u3002\u4e3a\u4e86\u907f\u514d\u4ee3\u7801\u590d\u6742\u6027\uff0c\u8fd9\u91cc\u76f4\u63a5\u5199\u65b0\u589e\uff0c\u5927\u5bb6\u77e5\u9053\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5373\u53ef\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u5ef6\u65f6\u6d88\u606f\u961f\u5217\uff0c\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\uff0c\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664UserCouponDelayCloseEvent userCouponDelayCloseEvent =UserCouponDelayCloseEvent.builder().couponTemplateId(requestParam.getCouponTemplateId()).userCouponId(String.valueOf(userCouponDO.getId())).userId(UserContext.getUserId()).delayTime(validEndTime.getTime()).build();SendResult sendResult = couponDelayCloseProducer.sendMessage(userCouponDelayCloseEvent);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u6d88\u606f\u5931\u8d25\u89e3\u51b3\u65b9\u6848\u7b80\u5355\u4e14\u9ad8\u6548\u7684\u903b\u8f91\u4e4b\u4e00\uff1a\u6253\u5370\u65e5\u5fd7\u5e76\u62a5\u8b66\uff0c\u901a\u8fc7\u65e5\u5fd7\u641c\u96c6\u5e76\u91cd\u65b0\u6295\u9012if(ObjectUtil.notEqual(sendResult.getSendStatus().name(),\"SEND_OK\")){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"\u53d1\u9001\u4f18\u60e0\u5238\u5173\u95ed\u5ef6\u65f6\u961f\u5217\u5931\u8d25\uff0c\u6d88\u606f\u53c2\u6570\uff1a{}\",JSON.toJSONString(userCouponDelayCloseEvent));}}catch(Exception ex){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status.setRollbackOnly();\/\/ \u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u4e1a\u52a1\u5f02\u5e38if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}});}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u91cd\u6784\u4f18\u60e0\u5238\u79d2\u6740\u65b9\u6848<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u73b0\u6709\u6280\u672f\u65b9\u6848\u95ee\u9898<\/h3>\n\n\n\n<p>\u7ec6\u5fc3\u7684\u540c\u5b66\u53ef\u80fd\u53d1\u73b0\u4e86\u4e00\u4e2a\u95ee\u9898\uff0c\u5728\u5982\u6b64\u9ad8\u5e76\u53d1\u7684\u573a\u666f\u4e0b\uff0c\u5728\u4e00\u4e2a\u4e8b\u52a1\u4e2d\u64cd\u4f5c\u4e86\u8fd9\u4e48\u591a Redis \u548c RocketMQ\uff0c\u5c31\u4f1a\u5bfc\u81f4\u4e8b\u52a1\u65f6\u95f4\u5ef6\u957f\u4ee5\u53ca\u63a5\u53e3\u54cd\u5e94\u901f\u5ea6\u53d8\u6162\u7b49\u95ee\u9898\u3002<\/p>\n\n\n\n<p>\u6211\u4eec\u5728\u5151\u6362\/\u79d2\u6740\u4f18\u60e0\u5238\u63a5\u53e3\u7684\u4e8b\u52a1\u4e2d\u5171\u6267\u884c\u4e86\u4ee5\u4e0b\u903b\u8f91\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u64cd\u4f5c\u4f18\u60e0\u5238\u5e93\u5b58\u8868\u8fdb\u884c\u6263\u51cf\u5e93\u5b58\uff1b<\/li>\n\n\n\n<li>2.\u6dfb\u52a0\u4f18\u60e0\u5238\u6a21\u677f\u5230\u7528\u6237\u9886\u5238\u8868\uff1b<\/li>\n\n\n\n<li>3.\u4fdd\u5b58\u4f18\u60e0\u5238\u6a21\u677f\u5230\u7528\u6237 Redis \u9886\u5238\u8bb0\u5f55\u4e2d\uff1b<\/li>\n\n\n\n<li>4.\u67e5\u8be2\u7528\u6237 Redis \u9886\u5238\u8bb0\u5f55\u662f\u5426\u6301\u4e45\u5316\u6210\u529f\uff1b<\/li>\n\n\n\n<li>5.\u53d1\u9001 RocketMQ \u6d88\u606f\u961f\u5217\u5ef6\u65f6\u6d88\u606f\uff0c\u5230\u671f\u4fee\u6539\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u5176\u4e2d 3\u30014\u30015 \u6b65\u9aa4\u903b\u8f91\u90fd\u662f\u5728\u6570\u636e\u5e93\u64cd\u4f5c\u6210\u529f\u7684\u57fa\u7840\u4e0a\u6267\u884c\u7684\uff0c\u90a3\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7 Canal \u76d1\u542c Binlog \u673a\u5236\uff0c\u5f02\u6b65\u6267\u884c\u8fd9\u4e9b\u903b\u8f91\u5c31\u597d\u4e86\uff0c\u8fd9\u6837\u5c31\u80fd\u4e0d\u5360\u7528\u4e3b\u903b\u8f91\u7684\u4e8b\u52a1\u548c\u54cd\u5e94\u65f6\u95f4\u4e86\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2-canal\">2. Canal \u6539\u9020\u73b0\u6709\u79d2\u6740\u67b6\u6784<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-1-canal\">2.1 \u4ec0\u4e48\u662f Canal<\/h4>\n\n\n\n<p>\u8bd1\u610f\u4e3a\u6c34\u9053\/\u7ba1\u9053\/\u6c9f\u6e20\uff0c\u4e3b\u8981\u7528\u9014\u662f\u57fa\u4e8e MySQL \u6570\u636e\u5e93\u589e\u91cf\u65e5\u5fd7\u89e3\u6790\uff0c\u63d0\u4f9b\u589e\u91cf\u6570\u636e\u8ba2\u9605\u548c\u6d88\u8d39\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303139313130343130313733353934372e706e67.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<p>\u57fa\u4e8e\u65e5\u5fd7\u589e\u91cf\u8ba2\u9605\u548c\u6d88\u8d39\u7684\u4e1a\u52a1\u5305\u62ec\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6570\u636e\u5e93\u955c\u50cf<\/li>\n\n\n\n<li>\u6570\u636e\u5e93\u5b9e\u65f6\u5907\u4efd<\/li>\n\n\n\n<li>\u7d22\u5f15\u6784\u5efa\u548c\u5b9e\u65f6\u7ef4\u62a4(\u62c6\u5206\u5f02\u6784\u7d22\u5f15\u3001\u5012\u6392\u7d22\u5f15\u7b49)<\/li>\n\n\n\n<li>\u4e1a\u52a1 cache \u5237\u65b0<\/li>\n\n\n\n<li>\u5e26\u4e1a\u52a1\u903b\u8f91\u7684\u589e\u91cf\u6570\u636e\u5904\u7406<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-2-my-sql-binlog\">2.2 MySQL \u5f00\u542f Binlog \u76d1\u542c<\/h4>\n\n\n\n<p>\u5bf9\u4e8e\u81ea\u5efa MySQL , \u9700\u8981\u5148\u5f00\u542f Binlog \u5199\u5165\u529f\u80fd\uff0cmy.cnf \u4e2d\u914d\u7f6e\u9700\u8981\u5305\u542b\u5982\u4e0b\u4fe1\u606f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;mysqld]\nlog-bin=mysql-bin # \u5f00\u542f binlog\nbinlog-format=ROW# \u9009\u62e9 ROW \u6a21\u5f0f\nserver_id=1# \u914d\u7f6e MySQL replaction \u9700\u8981\u5b9a\u4e49\uff0c\u4e0d\u8981\u548c canal \u7684 slaveId \u91cd\u590d<\/code><\/pre>\n\n\n\n<p>\u914d\u7f6e\u4fee\u6539\u6210\u529f\u540e\uff0c\u91cd\u542f\u4e00\u4e0b MySQL\uff0c\u786e\u4fdd\u6240\u6709\u7684\u914d\u7f6e\u751f\u6548\u3002\u7136\u540e\u6267\u884c MySQL \u6267\u884c\u547d\u4ee4\u67e5\u770b\u662f\u5426\u4fee\u6539 Binlog \u6210\u529f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u67e5\u770b binlog \u65e5\u5fd7\u662f\u5426\u5f00\u542fshow variables like'log_%';<\/code><\/pre>\n\n\n\n<p>\u5982\u679c\u67e5\u8be2\u51fa\u7684\u9009\u578b log_bin \u6570\u636e\u4e3a ON\uff0cBinlog \u5373\u4e3a\u5f00\u542f\u72b6\u6001\u3002\u8f93\u51fa\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql&gt;show variables like'log_%';+----------------------------------------+-----------------------------------------+| Variable_name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |Value|+----------------------------------------+-----------------------------------------+| log_bin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |ON|| log_bin_basename &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |\/opt\/homebrew\/var\/mysql\/mysql-bin &nbsp; &nbsp; &nbsp; || log_bin_index &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |\/opt\/homebrew\/var\/mysql\/mysql-bin.index|| log_bin_trust_function_creators &nbsp; &nbsp; &nbsp;  |OFF|| log_bin_use_v1_row_events &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |OFF|| log_builtin_as_identified_by_password  |OFF|| log_error &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |.\/bogon.err &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || log_error_verbosity &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |3|| log_output &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |FILE|| log_queries_not_using_indexes &nbsp; &nbsp; &nbsp; &nbsp;  |OFF|| log_slave_updates &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |OFF|| log_slow_admin_statements &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |OFF|| log_slow_slave_statements &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |OFF|| log_statements_unsafe_for_binlog &nbsp; &nbsp; &nbsp; |ON|| log_syslog &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |OFF|| log_syslog_facility &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  | daemon &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  || log_syslog_include_pid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |ON|| log_syslog_tag &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ||| log_throttle_queries_not_using_indexes |0|| log_timestamps &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | UTC &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || log_warnings &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |2|+----------------------------------------+-----------------------------------------+21rowsinset(0.00 sec)<\/code><\/pre>\n\n\n\n<p>\u6700\u540e\uff0cMySQL \u6267\u884c SQL \u8bed\u53e5\u521b\u5efa canal \u5355\u72ec\u4f7f\u7528\u7684\u8d26\u53f7\uff0c\u7528\u6765\u8fdb\u884c Binlog \u7684\u540c\u6b65\u548c\u76d1\u542c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATEUSER canal IDENTIFIED BY'canal';GRANTSELECT,REPLICATION SLAVE,REPLICATION CLIENT ON*.*TO'canal'@'%';\nFLUSH PRIVILEGES;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-3-canal\">2.3 \u5b89\u88c5 Canal \u4e2d\u95f4\u4ef6<\/h4>\n\n\n\n<p>\u63a5\u4e0b\u6765\u5f00\u59cb\u914d\u7f6e Canal \u4e2d\u95f4\u4ef6\uff0c\u4e0b\u8f7d Canal \u5b89\u88c5\u5305\uff0c\u5176\u4e2d\u7684\u4e00\u4e9b\u914d\u7f6e\u90fd\u662f\u6211\u8c03\u8bd5\u540e\u7684\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u7f51\u76d8\u5206\u4eab\u7684\u6587\u4ef6\uff1acanal.deployer-1.1.6-oneCoupon.zip \u94fe\u63a5: <a href=\"https:\/\/pan.baidu.com\/s\/1h9dLEl2g7oSdz9YuNC70rw?pwd=9tfb\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >https:\/\/pan.baidu.com\/s\/1h9dLEl2g7oSdz9YuNC70rw?pwd=9tfb<\/a> \u63d0\u53d6\u7801: 9tfb<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u5982\u679c\u672c\u5730 MySQL \u4e0d\u662f <code>127.0.0.1:3306<\/code> \u914d\u7f6e\uff0c\u9700\u8981\u5c06 <code>instance.properties<\/code> \u914d\u7f6e\u6587\u4ef6\u4e2d\u7684 <code>canal.instance.master.address<\/code> \u914d\u7f6e\u9879\u66ff\u6362\u4e3a\u771f\u5b9e\u7684 MySQL \u5730\u5740\u548c\u7aef\u53e3\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/1693188412856-1ee64d6f-1340-48c0-85c6-bec5962e3974.png\" alt=\"img\" title=\"img\"\/><\/figure>\n\n\n\n\n\n<p>\u5982\u679c\u4f60\u662f\u81ea\u5df1\u672c\u5730\u542f\u52a8\u7684 RocketMQ\uff0c\u5c06 <code>canal.properties<\/code>\u6587\u4ef6\u4e2d\u7684 <code>rocketmq.namesrv.addr<\/code> \u914d\u7f6e\u9879\u53d8\u66f4\u4e3a\u81ea\u5df1\u672c\u5730\u7684 RocketMQ \u914d\u7f6e\uff0c\u9ed8\u8ba4\u4e3a\u516c\u6709\u4e91\u4e2d\u95f4\u4ef6\u5730\u5740\u3002<\/p>\n\n\n\n<p>\u5982\u679c\u4f60\u6b63\u5728\u4f7f\u7528\u516c\u6709\u4e91 RocketMQ\uff0c<code>instance.properties<\/code> \u914d\u7f6e\u6587\u4ef6\u4e2d\u7684 <code>canal.mq.topic<\/code> \u4e5f\u9700\u8981\u53d8\u66f4\uff0c\u914d\u7f6e\u4e2d\u9ed8\u8ba4\u4e3a <code>one-coupon_canal_engine-service_common-sync_topic-mading<\/code>\uff0c<code>-mading<\/code> \u9700\u8981\u5927\u5bb6\u53d8\u66f4\u4e3a\u81ea\u5df1\u5728\u9879\u76ee\u542f\u52a8 VM \u53c2\u6570\u91cc\u7684\u503c\u3002\u5404\u81ea\u68c0\u67e5\u5e76\u8fdb\u884c\u66ff\u6362\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-Dunique-name=-mading<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u5982\u679c\u8fd9\u4e00\u6b65\u6709\u95ee\u9898\uff0c\u662f\u6ca1\u6709\u529e\u6cd5\u53d1\u9001\u5230 RocketMQ \u987a\u5229\u6d88\u8d39\u7684\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u5168\u90e8\u4e0a\u8ff0\u914d\u7f6e\u5927\u5bb6\u5168\u90fd\u641e\u5b9a\u540e\uff0c\u5f00\u59cb\u542f\u52a8 Canal \u8fdb\u884c\u6d4b\u8bd5\u3002\u5982\u679c\u662f Windows \u7cfb\u7edf\uff0c\u76f4\u63a5\u53cc\u51fb Canal \u6587\u4ef6\u5939\u4e0b bin \u76ee\u5f55\u7684 <code>startup.bat<\/code> \u811a\u672c\u5373\u53ef\uff0c\u8981\u505c\u6b62 Canal \u5173\u95ed\u811a\u672c\u5f39\u6846\u3002\u5982\u679c\u662f Linux \u6216\u8005 Mac \u7cfb\u7edf\uff0c\u8fdb\u5165 bin \u76ee\u5f55\u4e0b\u6267\u884c <code>sh startup.sh<\/code> \u547d\u4ee4\u3002\u5982\u679c\u662f Linux \u6216\u8005 Mac \u7cfb\u7edf\u8981\u505c\u6b62\u6267\u884c <code>sh stop.sh<\/code>\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u6ce8\u610f\uff0cCanal \u5b89\u88c5\u8def\u5f84\u4e2d\u4e0d\u8981\u6709\u6587\u4ef6\u5939\u540d\u79f0\u662f\u4e2d\u6587\u3002\u9700\u8981\u4f7f\u7528 JDK8 \u542f\u52a8 Canal \u670d\u52a1\uff0c\u4e0d\u8981\u4f7f\u7528 JDK17\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u542f\u52a8\u5b8c\u6210\u540e\uff0c\u6253\u5f00 logs \u6587\u4ef6\u5939\u76ee\u5f55\u4e0b\u7684 canal\/canal.log \u6587\u4ef6\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/1692516470662-57239ae0-69bd-422e-a565-c2ec8f10fdc8.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<p>\u67e5\u770b\u662f\u5426\u542f\u52a8\u6210\u529f\uff0c\u5982\u679c\u8f93\u51fa\u6253\u5370\u5982\u4e0b <code>the canal server is running now<\/code>\uff0c\u5373\u4e3a\u6210\u529f\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/1692516510577-0d0a3cda-ed76-4214-9880-0588bdb98d1a.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<p>\u7136\u540e\uff0c\u6211\u4eec\u53d8\u66f4\u6570\u636e\u5e93 <code>t_user_coupon<\/code> \u8868\u4e2d\u4efb\u610f\u4e00\u6761\u8bb0\u5f55\u7684 status \u503c\uff0c\u6bd4\u5982\u4ece 0 \u53d8\u4e3a 1\uff0c\u6216\u8005\u4ece 1 \u53d8\u4e3a 0\u3002<\/p>\n\n\n\n<p>\u63a5\u4e0b\u6765\u67e5\u770b RocketMQ \u63a7\u5236\u53f0\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u8bbf\u95ee\u5730\u5740\uff1a<a href=\"http:\/\/common-rocketmq-dev.magestack.cn:8088\/#\/message\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >http:\/\/common-rocketmq-dev.magestack.cn:8088\/#\/message<\/a><\/li>\n<\/ul>\n\n\n\n<p>\u9875\u9762\u914d\u7f6e\u67e5\u8be2\u5982\u4e0b\uff0c\u9009\u62e9\u597d\u4e3b\u9898\u548c\u5f00\u59cb\u7ed3\u675f\u65f6\u95f4\uff08\u9ed8\u8ba4\u4f1a\u586b\u5145\uff09\u540e\uff0c\u70b9\u51fb\u641c\u7d22\u6309\u94ae\u3002<\/p>\n\n\n\n\n\n<p>\u6d88\u606f\u4f53\u683c\u5f0f\u4e3a JSON \u7c7b\u578b\u6570\u636e\uff0c\u793a\u4f8b\u6570\u636e\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"data\":&#91;{\"id\":\"1832782304792027137\",\"user_id\":\"1810518709471555585\",\"coupon_template_id\":\"1832782251755053058\",\"receive_time\":\"2024-09-08 22:05:28\",\"receive_count\":\"1\",\"valid_start_time\":\"2024-09-08 22:05:28\",\"valid_end_time\":\"2024-09-10 22:05:28\",\"use_time\":null,\"source\":\"0\",\"status\":\"1\",\"create_time\":\"2024-09-08 22:05:28\",\"update_time\":\"2024-09-08 22:05:28\",\"del_flag\":\"0\"}],\"database\":\"one_coupon_0\",\"es\":1725881100000,\"id\":2,\"isDdl\":false,\"mysqlType\":{\"id\":\"bigint(20)\",\"user_id\":\"bigint(20)\",\"coupon_template_id\":\"bigint(20)\",\"receive_time\":\"datetime\",\"receive_count\":\"int(3)\",\"valid_start_time\":\"datetime\",\"valid_end_time\":\"datetime\",\"use_time\":\"datetime\",\"source\":\"tinyint(1)\",\"status\":\"tinyint(1)\",\"create_time\":\"datetime\",\"update_time\":\"datetime\",\"del_flag\":\"tinyint(1)\"},\"old\":&#91;{\"status\":\"0\"}],\"pkNames\":&#91;\"id\"],\"sql\":\"\",\"sqlType\":{\"id\":-5,\"user_id\":-5,\"coupon_template_id\":-5,\"receive_time\":93,\"receive_count\":4,\"valid_start_time\":93,\"valid_end_time\":93,\"use_time\":93,\"source\":-6,\"status\":-6,\"create_time\":93,\"update_time\":93,\"del_flag\":-6},\"table\":\"t_user_coupon_13\",\"ts\":1725881101080,\"type\":\"UPDATE\"}<\/code><\/pre>\n\n\n\n<p>\u5bf9\u5e94\u914d\u7f6e\u5b57\u6bb5\u4fe1\u606f\u7684\u8bed\u610f\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * Canal Binlog \u76d1\u542c\u89e6\u53d1\u4e8b\u4ef6\n *\/@DatapublicclassCanalBinlogEvent{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u53d8\u66f4\u6570\u636e\n &nbsp; &nbsp; *\/privateList&lt;Map&lt;String, Object&gt;&gt; data;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u6570\u636e\u5e93\u540d\u79f0\n &nbsp; &nbsp; *\/privateString database;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * es \u662f\u6307 Mysql Binlog \u91cc\u539f\u59cb\u7684\u65f6\u95f4\u6233\uff0c\u4e5f\u5c31\u662f\u6570\u636e\u539f\u59cb\u53d8\u66f4\u7684\u65f6\u95f4\n &nbsp; &nbsp; * Canal \u7684\u6d88\u8d39\u5ef6\u8fdf = ts - es\n &nbsp; &nbsp; *\/privateLong es;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u9012\u589e ID\uff0c\u4ece 1 \u5f00\u59cb\n &nbsp; &nbsp; *\/privateLong id;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u5f53\u524d\u53d8\u66f4\u662f\u5426\u662f DDL \u8bed\u53e5\n &nbsp; &nbsp; *\/privateBoolean isDdl;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u8868\u7ed3\u6784\u5b57\u6bb5\u7c7b\u578b\n &nbsp; &nbsp; *\/privateMap&lt;String, Object&gt; mysqlType;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * UPDATE \u6a21\u5f0f\u4e0b\u65e7\u6570\u636e\n &nbsp; &nbsp; *\/privateList&lt;Map&lt;String, Object&gt;&gt; old;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u4e3b\u952e\u540d\u79f0\n &nbsp; &nbsp; *\/privateList&lt;String&gt; pkNames;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * SQL \u8bed\u53e5\n &nbsp; &nbsp; *\/privateString sql;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * SQL \u7c7b\u578b\n &nbsp; &nbsp; *\/privateMap&lt;String, Object&gt; sqlType;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u8868\u540d\n &nbsp; &nbsp; *\/privateString table;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * ts \u662f\u6307 Canal \u6536\u5230\u8fd9\u4e2a Binlog\uff0c\u6784\u9020\u4e3a\u81ea\u5df1\u534f\u8bae\u5bf9\u8c61\u7684\u65f6\u95f4\n &nbsp; &nbsp; * \u5e94\u7528\u6d88\u8d39\u7684\u5ef6\u8fdf = now - ts\n &nbsp; &nbsp; *\/privateLong ts;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * INSERT\uff08\u65b0\u589e\uff09\u3001UPDATE\uff08\u66f4\u65b0\uff09\u3001DELETE\uff08\u5220\u9664\uff09\u7b49\u7b49\n &nbsp; &nbsp; *\/privateString type;}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-4-canal-rocket-mq-topic\">2.4 \u76d1\u542c Canal RocketMQ Topic<\/h4>\n\n\n\n<p>\u4e00\u822c\u6765\u8bf4\uff0c\u9488\u5bf9\u9ad8\u5e76\u53d1\u7684 Binlog \u76d1\u542c\uff0c\u6211\u4eec\u90fd\u662f\u5c06 Canal \u7684 Binlog \u6570\u636e\u4e22\u5230\u6d88\u606f\u961f\u5217\u4e2d\u3002Canal \u4f1a\u5c06 Binlog \u7684\u53d8\u66f4\u5185\u5bb9\u63a8\u9001\u5230\u6307\u5b9a\u7684 RocketMQ Topic\u3002\u56e0\u6b64\uff0c\u5728 Spring Boot \u5e94\u7528\u4e2d\uff0c\u6211\u4eec\u53ea\u9700\u8981\u4e0e RocketMQ \u8fdb\u884c\u5bf9\u63a5\u5373\u53ef\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>packagecom.nageoffer.onecoupon.engine.mq.consumer;\n\u200b\nimportcn.hutool.core.collection.CollUtil;importcn.hutool.core.date.DateUtil;importcn.hutool.core.util.ObjectUtil;importcn.hutool.core.util.StrUtil;importcom.alibaba.fastjson2.JSON;importcom.nageoffer.onecoupon.engine.common.constant.EngineRedisConstant;importcom.nageoffer.onecoupon.engine.common.constant.EngineRockerMQConstant;importcom.nageoffer.onecoupon.engine.mq.event.CanalBinlogEvent;importcom.nageoffer.onecoupon.engine.mq.event.UserCouponDelayCloseEvent;importcom.nageoffer.onecoupon.engine.mq.producer.UserCouponDelayCloseProducer;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.apache.rocketmq.client.producer.SendResult;importorg.apache.rocketmq.spring.annotation.RocketMQMessageListener;importorg.apache.rocketmq.spring.core.RocketMQListener;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Component;\n\u200b\nimportjava.util.Date;importjava.util.Map;\n\u200b\n\/**\n * \u901a\u8fc7 Canal \u76d1\u542c\u7528\u6237\u4f18\u60e0\u5238\u8868 Binlog \u6295\u9012\u6d88\u606f\u961f\u5217\u6d88\u8d39\n * &lt;p&gt;\n * \u4f5c\u8005\uff1a\u9a6c\u4e01\n * \u52a0\u9879\u76ee\u7fa4\uff1a\u65e9\u52a0\u5165\u5c31\u662f\u4f18\u52bf\uff01500\u4eba\u5185\u90e8\u6c9f\u901a\u7fa4\uff0c\u5206\u4eab\u7684\u77e5\u8bc6\u603b\u6709\u4f60\u9700\u8981\u7684 &lt;a href=\"https:\/\/t.zsxq.com\/cw7b9\" \/&gt;\n * \u5f00\u53d1\u65f6\u95f4\uff1a2024-07-25\n *\/@Slf4j@Component@RequiredArgsConstructor@RocketMQMessageListener(\n &nbsp; &nbsp; &nbsp; &nbsp;topic =\"one-coupon_canal_engine-service_common-sync_topic${unique-name:}\",\n &nbsp; &nbsp; &nbsp; &nbsp;consumerGroup =\"one-coupon_canal_engine-service_common-sync_cg${unique-name:}\")publicclassCanalBinlogSyncUserCouponConsumerimplementsRocketMQListener&lt;CanalBinlogEvent&gt;{\n\u200b\n &nbsp; &nbsp;privatefinalStringRedisTemplate stringRedisTemplate;privatefinalUserCouponDelayCloseProducer couponDelayCloseProducer;\n\u200b\n &nbsp; &nbsp;@OverridepublicvoidonMessage(CanalBinlogEvent canalBinlogEvent){Map&lt;String, Object&gt; first =CollUtil.getFirst(canalBinlogEvent.getData());String couponTemplateId = first.get(\"coupon_template_id\").toString();String userCouponId = first.get(\"id\").toString();\/\/ \u7528\u6237\u4f18\u60e0\u5238\u521b\u5efa\u4e8b\u4ef6if(ObjectUtil.equal(canalBinlogEvent.getType(),\"INSERT\")){\/\/ \u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u8bb0\u5f55String userCouponListCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIST_KEY, first.get(\"user_id\").toString());String userCouponItemCacheKey =StrUtil.builder().append(couponTemplateId).append(\"_\").append(userCouponId).toString();Date receiveTime =DateUtil.parse(first.get(\"receive_time\").toString());\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, receiveTime.getTime());\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u7531\u4e8e Redis \u5728\u6301\u4e45\u5316\u6216\u4e3b\u4ece\u590d\u5236\u7684\u6781\u7aef\u60c5\u51b5\u4e0b\u53ef\u80fd\u4f1a\u51fa\u73b0\u6570\u636e\u4e22\u5931\uff0c\u800c\u6211\u4eec\u5bf9\u6307\u4ee4\u4e22\u5931\u51e0\u4e4e\u65e0\u6cd5\u5bb9\u5fcd\uff0c\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u7ecf\u5178\u7684\u5199\u540e\u67e5\u8be2\u7b56\u7565\u6765\u5e94\u5bf9\u8fd9\u4e00\u95ee\u9898Double scored;try{\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;scored = stringRedisTemplate.opsForZSet().score(userCouponListCacheKey, userCouponItemCacheKey);\/\/ scored \u4e3a\u7a7a\u610f\u5473\u7740\u53ef\u80fd Redis Cluster \u4e3b\u4ece\u540c\u6b65\u4e22\u5931\u4e86\u6570\u636e\uff0c\u6bd4\u5982 Redis \u4e3b\u8282\u70b9\u8fd8\u6ca1\u6709\u540c\u6b65\u5230\u4ece\u8282\u70b9\u5c31\u5b95\u673a\u4e86\uff0c\u89e3\u51b3\u65b9\u6848\u5c31\u662f\u518d\u65b0\u589e\u4e00\u6b21if(scored ==null){\/\/ \u5982\u679c\u8fd9\u91cc\u4e5f\u65b0\u589e\u5931\u8d25\u4e86\u600e\u4e48\u529e\uff1f\u6211\u4eec\u5927\u6982\u7387\u505a\u4e0d\u5230\u7edd\u5bf9\u7684\u4e07\u65e0\u4e00\u5931\uff0c\u53ea\u80fd\u5c3d\u53ef\u80fd\u589e\u52a0\u6210\u529f\u7387\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, receiveTime.getTime());}}catch(Throwable ex){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"\u67e5\u8be2Redis\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u4e3a\u7a7a\u6216\u629b\u5f02\u5e38\uff0c\u53ef\u80fdRedis\u5b95\u673a\u6216\u4e3b\u4ece\u590d\u5236\u6570\u636e\u4e22\u5931\uff0c\u57fa\u7840\u9519\u8bef\u4fe1\u606f\uff1a{}\", ex.getMessage());\/\/ \u5982\u679c\u76f4\u63a5\u629b\u5f02\u5e38\u5927\u6982\u7387 Redis \u5b95\u673a\u4e86\uff0c\u6240\u4ee5\u5e94\u8be5\u5199\u4e2a\u5ef6\u65f6\u961f\u5217\u5411 Redis \u91cd\u8bd5\u653e\u5165\u503c\u3002\u4e3a\u4e86\u907f\u514d\u4ee3\u7801\u590d\u6742\u6027\uff0c\u8fd9\u91cc\u76f4\u63a5\u5199\u65b0\u589e\uff0c\u5927\u5bb6\u77e5\u9053\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5373\u53ef\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, receiveTime.getTime());}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u5ef6\u65f6\u6d88\u606f\u961f\u5217\uff0c\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\uff0c\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664UserCouponDelayCloseEvent userCouponDelayCloseEvent =UserCouponDelayCloseEvent.builder().couponTemplateId(couponTemplateId).userCouponId(userCouponId).userId(first.get(\"user_id\").toString()).delayTime(DateUtil.parse(first.get(\"valid_end_time\").toString()).getTime()).build();SendResult sendResult = couponDelayCloseProducer.sendMessage(userCouponDelayCloseEvent);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u6d88\u606f\u5931\u8d25\u89e3\u51b3\u65b9\u6848\u7b80\u5355\u4e14\u9ad8\u6548\u7684\u903b\u8f91\u4e4b\u4e00\uff1a\u6253\u5370\u65e5\u5fd7\u5e76\u62a5\u8b66\uff0c\u901a\u8fc7\u65e5\u5fd7\u641c\u96c6\u5e76\u91cd\u65b0\u6295\u9012if(ObjectUtil.notEqual(sendResult.getSendStatus().name(),\"SEND_OK\")){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"\u53d1\u9001\u4f18\u60e0\u5238\u5173\u95ed\u5ef6\u65f6\u961f\u5217\u5931\u8d25\uff0c\u6d88\u606f\u53c2\u6570\uff1a{}\",JSON.toJSONString(userCouponDelayCloseEvent));}}}}<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u6211\u4eec\u5c31\u80fd\u5c06\u63a5\u53e3\u7684\u541e\u5410\u91cf\u5927\u5e45\u5ea6\u63d0\u9ad8\u4e86\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3-canal\">3. \u7b80\u5316 Canal \u6d41\u7a0b<\/h3>\n\n\n\n<p>\u8003\u8651\u5230\u5f88\u591a\u540c\u5b66\u662f\u60f3\u5feb\u901f\u542f\u52a8\u725b\u5238\u9879\u76ee\uff0c\u4e3a\u4e86\u4e0d\u8ba9 Canal \u6210\u4e3a\u5f3a\u5236\u4f9d\u8d56\u7684\u7ec4\u4ef6\uff0c\u6211\u4eec\u6dfb\u52a0\u4e00\u4e2a\u914d\u7f6e\u3002<\/p>\n\n\n\n<p>application.yaml \u914d\u7f6e\u6587\u4ef6\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>one-coupon:user-coupon-list:\n &nbsp;  save-cache:\n &nbsp; &nbsp;  type: direct # \u6709\u4e24\u4e2a\u9009\u9879\uff1adirect \u5728\u6d41\u7a0b\u91cc\u76f4\u63a5\u64cd\u4f5c\uff0cbinlog \u901a\u8fc7\u89e3\u6790\u6570\u636e\u5e93\u65e5\u5fd7\u540e\u64cd\u4f5c<\/code><\/pre>\n\n\n\n<p>\u5728 Service \u4ee3\u7801\u4e2d\u6dfb\u52a0\u4e00\u4e2a\u5224\u65ad\u5c31\u597d\uff0c\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@OverridepublicvoidredeemUserCoupon(CouponTemplateRedeemReqDTO requestParam){\/\/ ......\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u6267\u884c\u4f18\u60e0\u5238\u5e93\u5b58\u81ea\u51cf\u4ee5\u53ca\u589e\u52a0\u7528\u6237\u4f18\u60e0\u5238\u9886\u53d6\u8bb0\u5f55long extractSecondField =StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult);\n &nbsp; &nbsp;transactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ ......\/\/ \u4fdd\u5b58\u4f18\u60e0\u5238\u7f13\u5b58\u96c6\u5408\u6709\u4e24\u4e2a\u9009\u9879\uff1adirect \u5728\u6d41\u7a0b\u91cc\u76f4\u63a5\u64cd\u4f5c\uff0cbinlog \u901a\u8fc7\u89e3\u6790\u6570\u636e\u5e93\u65e5\u5fd7\u540e\u64cd\u4f5cif(StrUtil.equals(userCouponListSaveCacheType,\"direct\")){\/\/ \u64cd\u4f5c\u7f13\u5b58\u3001\u64cd\u4f5c\u6d88\u606f\u961f\u5217\/\/ ......}}catch(Exception ex){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status.setRollbackOnly();\/\/ \u4f18\u60e0\u5238\u5df2\u88ab\u9886\u53d6\u5b8c\u4e1a\u52a1\u5f02\u5e38if(ex instanceofServiceException){throw(ServiceException) ex;}if(ex instanceofDuplicateKeyException){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\uff0c\u7528\u6237ID\uff1a{}\uff0c\u4f18\u60e0\u5238\u6a21\u677fID\uff1a{}\",UserContext.getUserId(), requestParam.getCouponTemplateId());thrownewServiceException(\"\u7528\u6237\u91cd\u590d\u9886\u53d6\u4f18\u60e0\u5238\");}thrownewServiceException(\"\u4f18\u60e0\u5238\u9886\u53d6\u5f02\u5e38\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}});}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"redis\">Redis \u7f13\u5b58\u5e8f\u5217\u5316\u5668<\/h2>\n\n\n\n<p>\u56e0\u4e3a\u54b1\u4eec\u7684\u7528\u6237\u4fe1\u606f\u662f\u56fa\u5b9a\u5199\u5165\u7684\uff0c\u6240\u4ee5\uff0c\u5982\u679c\u7528\u6237\u9886\u53d6\u4e86\u4f18\u60e0\u5238\uff0c\u5927\u5bb6\u7684\u4f18\u60e0\u5238\u4fe1\u606f\u90fd\u662f\u5199\u5230\u4e00\u4e2a Redis\uff08\u5982\u679c\u7528\u4e86\u4e91 Redis \u7684\u8bdd\uff09\u7f13\u5b58\u7684\u3002\u8fd9\u6837\u7684\u8bdd\u5c31\u4e0d\u592a\u597d\u5206\u8fa8\u548c\u6d4b\u8bd5\uff0c\u4e3a\u6b64\u6211\u4eec\u901a\u8fc7\u81ea\u5b9a\u4e49 Redis \u7f13\u5b58\u7684\u5e8f\u5217\u5316\u5668\u505a\u4e2a\u6807\u8bc6\u3002<\/p>\n\n\n\n<p>\u53d8\u66f4\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240909195703640.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<p>\u903b\u8f91\u6bd4\u8f83\u7b80\u5355\uff0c\u901a\u8fc7\u81ea\u5b9a\u4e49\u4e00\u4e2a <code>RedisKeySerializer<\/code> \u66ff\u6362\u9ed8\u8ba4\u7684 Key \u5e8f\u5217\u5316\u5668\u5c31\u597d\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@RequiredArgsConstructor@EnableConfigurationProperties(RedisDistributedProperties.class)publicclassCacheConfigurationimplementsInitializingBean{\n\u200b\n &nbsp; &nbsp;privatefinalRedisDistributedProperties redisDistributedProperties;privatefinalStringRedisTemplate stringRedisTemplate;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u521b\u5efa Redis Key \u5e8f\u5217\u5316\u5668\uff0c\u53ef\u81ea\u5b9a\u4e49 Key Prefix\n &nbsp; &nbsp; *\/@BeanpublicRedisKeySerializerredisKeySerializer(){String prefix =Optional.ofNullable(redisDistributedProperties.getPrefix()).orElse(\"\");String prefixCharset = redisDistributedProperties.getPrefixCharset();returnnewRedisKeySerializer(prefix, prefixCharset);}\n\u200b\n &nbsp; &nbsp;@OverridepublicvoidafterPropertiesSet()throwsException{\n &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.setKeySerializer(redisKeySerializer());}}<\/code><\/pre>\n\n\n\n<p>\u7136\u540e\u6211\u4eec\u5728 VM \u53c2\u6570\u91cc\u6dfb\u52a0\u4e00\u4e2a\u65b0\u7684\u53c2\u6570\uff0c\u56e0\u4e3a\u6211\u53ea\u7528\u4e86\u516c\u6709\u4e91 RocketMQ\uff0c\u6240\u4ee5\u52a0\u4e0a\u540e\u4e00\u5171\u662f\u4e09\u4e2a\u53c2\u6570\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240909200653218.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<p>\u4f46\u662f\u6709\u4e2a\u70b9\uff0c\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u521b\u5efa\u5e76\u4e0d\u53d7\u8fd9\u4e2a\u7ba1\u63a7\uff0c\u6240\u4ee5\u6211\u4eec\u8981\u624b\u52a8\u8ffd\u52a0\u3002\u9700\u8981\u4fee\u6539\u540e\u7ba1\u548c\u5f15\u64ce\u7684\u5e03\u9686\u8fc7\u6ee4\u5668\u521b\u5efa\u914d\u7f6e\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@ConfigurationpublicclassRBloomFilterConfiguration{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u4f18\u60e0\u5238\u67e5\u8be2\u7f13\u5b58\u7a7f\u900f\u5e03\u9686\u8fc7\u6ee4\u5668\n &nbsp; &nbsp; *\/@BeanpublicRBloomFilter&lt;String&gt;couponTemplateQueryBloomFilter(RedissonClient redissonClient,@Value(\"${framework.cache.redis.prefix:}\")String cachePrefix){RBloomFilter&lt;String&gt; bloomFilter = redissonClient.getBloomFilter(cachePrefix +\"couponTemplateQueryBloomFilter\");\n &nbsp; &nbsp; &nbsp; &nbsp;bloomFilter.tryInit(640L,0.001);return bloomFilter;}}<\/code><\/pre>\n\n\n\n<p>\u7136\u540e\u6211\u4eec\u91cd\u542f\u540e\u7ba1\u548c\u5f15\u64ce\u670d\u52a1\uff0c\u6267\u884c\u65b0\u589e\u548c\u9886\u53d6\u4f18\u60e0\u5238\u4e1a\u52a1\uff0c\u5c31\u53ef\u4ee5\u770b\u5230\u9ed8\u8ba4\u7684 Key \u524d\u9762\u4f1a\u8ffd\u52a0\u6211\u4eec\u81ea\u5b9a\u4e49\u7684 prefix\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240909205027009.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">\u6267\u884c\u4f18\u60e0\u5238\u5151\u6362<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u521b\u5efa\u4f18\u60e0\u5238\u6a21\u677f<\/h3>\n\n\n\n<p>\u521b\u5efa\u4f18\u60e0\u5238\u6a21\u677f\u63a5\u53e3\u5730\u5740\uff1a<a href=\"http:\/\/127.0.0.1:10010\/doc.html#\/default\/%E4%BC%98%E6%83%A0%E5%88%B8%E6%A8%A1%E6%9D%BF%E7%AE%A1%E7%90%86\/createCouponTemplate\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >\u70b9\u51fb\u8df3\u8f6c<\/a><\/p>\n\n\n\n<p>\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u4f18\u60e0\u5238\u6a21\u677f\uff0c\u7136\u540e\u7528\u6237\u9650\u9886\u6b21\u6570 <code>limitPerPerson<\/code> \u8bbe\u7f6e\u4e3a 2 \u6b21\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"name\":\"\u7528\u6237\u4e0b\u5355\u6ee110\u51cf3\u7279\u5927\u4f18\u60e0\",\"source\":0,\"target\":1,\"goods\":\"\",\"type\":0,\"validStartTime\":\"2024-07-08 12:00:00\",\"validEndTime\":\"2025-06-30 13:59:59\",\"stock\":4998,\"receiveRule\":\"{\\\"limitPerPerson\\\":2,\\\"usageInstructions\\\":\\\"3\\\"}\",\"consumeRule\":\"{\\\"termsOfUse\\\":10,\\\"maximumDiscountAmount\\\":3,\\\"explanationOfUnmetConditions\\\":\\\"3\\\",\\\"validityPeriod\\\":\\\"48\\\"}\"}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u5151\u6362\u4f18\u60e0\u5238<\/h3>\n\n\n\n<p>\u5151\u6362\u4f18\u60e0\u5238\u6a21\u677f\u63a5\u53e3\u5730\u5740\uff1a<a href=\"http:\/\/127.0.0.1:10020\/doc.html#\/default\/%E7%94%A8%E6%88%B7%E4%BC%98%E6%83%A0%E5%88%B8%E7%AE%A1%E7%90%86\/redeemUserCoupon\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >\u70b9\u51fb\u8df3\u8f6c<\/a><\/p>\n\n\n\n<p>\u4ece\u6570\u636e\u5e93 <code>one_coupon_rebuild_1<\/code> \u4e2d\u67e5\u8be2 <code>t_coupon_template_15<\/code> \u6700\u65b0\u7684\u521b\u5efa\u4f18\u60e0\u5238\u6a21\u677f ID\uff0c\u7136\u540e\u8fdb\u5165 API \u5730\u5740\u5f00\u59cb\u8fdb\u884c\u5151\u6362\u3002<\/p>\n\n\n\n<p><code>shopNumber<\/code> \u662f\u56fa\u5b9a\u7684\uff0c\u4f18\u60e0\u5238\u6a21\u677f ID \u590d\u5236\u521a\u521b\u5efa\u7684\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"source\":0,\"shopNumber\":\"1810714735922956666\",\"couponTemplateId\":\"1833125314830544897\"}<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u8c03\u7528\u4e24\u6b21\u6570\u636e\u662f\u6b63\u5e38\u7684\uff0c\u5982\u679c\u8c03\u7528\u7b2c\u4e09\u6b21\uff0c\u5c31\u4f1a\u89e6\u53d1\u7528\u6237\u9650\u9886\u5f02\u5e38\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"code\":\"B000001\",\"message\":\"\u7528\u6237\u5df2\u7ecf\u8fbe\u5230\u9886\u53d6\u4e0a\u9650\",\"data\":null,\"requestId\":null,\"success\":false}<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u67e5\u770b Redis \u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u7f13\u5b58\u6570\u636e\uff0c\u4f7f\u7528 ZSet \u5b58\u50a8\u4e24\u6761\u8bb0\u5f55\uff0c\u521a\u597d\u7b26\u5408\u6211\u4eec\u7684\u9884\u671f\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/oss.open8gu.com\/image-20240909212458538.png\" alt=\"\" title=\"\"\/><\/figure>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u5728\u4f18\u60e0\u5238\u5151\u6362\u548c\u79d2\u6740\u4e1a\u52a1\u4e2d\uff0c\u6211\u4eec\u5b9e\u73b0\u4e86\u5173\u952e\u6280\u672f\u4f18\u5316\u3002\u9996\u5148\uff0c\u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u786e\u4fdd\u4e86\u6570\u636e\u7684\u6b63\u786e\u6027\uff0c\u7ed3\u5408 Redis \u548c RocketMQ \u8fdb\u884c\u6d88\u606f\u5904\u7406\uff0c\u6ee1\u8db3\u4e86\u79d2\u6740\u573a\u666f\u5bf9\u9ad8\u541e\u5410\u91cf\u7684\u8981\u6c42\u3002\u7136\u800c\uff0c\u5728\u65e9\u671f\u7248\u672c\u4e2d\uff0c\u7cfb\u7edf\u7684\u541e\u5410\u91cf\u672a\u80fd\u8fbe\u5230\u9884\u671f\uff0c\u5e76\u4e14\u5728\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b\u5bb9\u6613\u51fa\u73b0\u5f02\u5e38\u3002\u4e3a\u6b64\uff0c\u6211\u4eec\u63a8\u51fa\u4e86 v2 \u7248\u672c\u7684\u67b6\u6784\u4f18\u5316\uff0c\u901a\u8fc7 Canal Binlog \u76d1\u542c\u6570\u636e\u5e93\u53d8\u66f4\u4e8b\u4ef6\uff0c\u5b9e\u73b0\u5bf9\u6570\u636e\u66f4\u65b0\u7684\u53ca\u65f6\u6355\u83b7\u548c\u5904\u7406\u3002\u8fd9\u79cd\u65b9\u5f0f\u5927\u5e45\u63d0\u5347\u4e86\u7cfb\u7edf\u7684\u541e\u5410\u91cf\uff0c\u5e76\u51cf\u5c11\u4e86\u5f02\u5e38\u7684\u53d1\u751f\u6982\u7387\uff0c\u6781\u5927\u5730\u63d0\u9ad8\u4e86\u7cfb\u7edf\u7684\u7a33\u5b9a\u6027\u548c\u6027\u80fd\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c24\u5c0f\u8282\uff1a\u5f00\u53d1\u5151\u6362\/\u79d2\u6740\u4f18\u60e0\u5238\u529f\u80fd\uff08\u4e8c\uff09<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5728\u4e0a\u4e00\u8282\u4e2d\uff0c\u6211\u4eec\u4ecb\u7ecd\u4e86\u901a\u8fc7\u6570\u636e\u5e93\u6263\u51cf\u5b8c\u6210\u7528\u6237\u5151\u6362\u4f18\u60e0\u5238\u7684\u903b\u8f91\uff0c\u8fd9\u79cd\u65b9\u5f0f\u867d\u7136\u7a33\u59a5\uff0c\u4f46\u6027\u80fd\u6709\u6240\u4e0d\u8db3\uff0c\u56e0\u4e3a\u4e3b\u6d41\u7a0b\u7684\u64cd\u4f5c\u662f\u540c\u6b65\u6267\u884c\u7684\uff0c\u5bfc\u81f4\u54cd\u5e94\u65f6\u95f4\u53d8\u957f\uff0c\u541e\u5410\u91cf\u4e0b\u964d\u3002\u5728\u672c\u7ae0\u8282\u4e2d\uff0c\u6211\u4eec\u901a\u8fc7\u5f15\u5165\u6d88\u606f\u961f\u5217\u8fdb\u884c\u5f02\u6b65\u89e3\u8026\uff0c\u4e3b\u6d41\u7a0b\u4ec5\u540c\u6b65\u64cd\u4f5c Redis\uff0c\u540e\u7eed\u7684\u6570\u636e\u5e93\u8017\u65f6\u64cd\u4f5c\u5219\u4ea4\u7531\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\u6765\u6267\u884c\uff0c\u4ece\u800c\u63d0\u5347\u6574\u4f53\u6027\u80fd\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240910_dev_acquire-coupon-v2_seckill_ding.ma<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5f00\u53d1\u57fa\u4e8e\u6d88\u606f\u961f\u5217\u79d2\u6740\u903b\u8f91<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-v2\">1. \u7f16\u5199\u5151\u6362\u4f18\u60e0\u5238 v2 \u63a5\u53e3<\/h3>\n\n\n\n<p>\u4fdd\u6301\u539f\u6709\u4ee3\u7801\u4e0d\u53d8\uff0c\u6211\u4eec\u5f00\u53d1\u4e00\u4e2a v2 \u7248\u672c\u7684\u65b9\u6cd5\u3002\u524d\u7f6e\u6821\u9a8c\u90e8\u5206\u53ef\u4ee5\u76f4\u63a5\u590d\u7528 v1 \u7248\u672c\u7684\u901a\u7528\u903b\u8f91\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@OverridepublicvoidredeemUserCouponByMQ(CouponTemplateRedeemReqDTO requestParam){\/\/ \u9a8c\u8bc1\u7f13\u5b58\u662f\u5426\u5b58\u5728\uff0c\u4fdd\u969c\u6570\u636e\u5b58\u5728\u5e76\u4e14\u7f13\u5b58\u4e2d\u5b58\u5728CouponTemplateQueryRespDTO couponTemplate = couponTemplateService.findCouponTemplate(BeanUtil.toBean(requestParam,CouponTemplateQueryReqDTO.class));\n\u200b\n &nbsp; &nbsp;\/\/ \u9a8c\u8bc1\u9886\u53d6\u7684\u4f18\u60e0\u5238\u662f\u5426\u5728\u6d3b\u52a8\u6709\u6548\u65f6\u95f4boolean isInTime =DateUtil.isIn(newDate(), couponTemplate.getValidStartTime(), couponTemplate.getValidEndTime());if(!isInTime){\/\/ \u4e00\u822c\u6765\u8bf4\u4f18\u60e0\u5238\u9886\u53d6\u65f6\u95f4\u4e0d\u5230\u7684\u65f6\u5019\uff0c\u524d\u7aef\u4e0d\u4f1a\u653e\u5f00\u8c03\u7528\u8bf7\u6c42\uff0c\u53ef\u4ee5\u7406\u89e3\u8fd9\u662f\u7528\u6237\u8c03\u7528\u63a5\u53e3\u5728\u201c\u653b\u51fb\u201dthrownewClientException(\"\u4e0d\u6ee1\u8db3\u4f18\u60e0\u5238\u9886\u53d6\u65f6\u95f4\");}\n\u200b\n &nbsp; &nbsp;\/\/ \u83b7\u53d6 LUA \u811a\u672c\uff0c\u5e76\u4fdd\u5b58\u5230 Hutool \u7684\u5355\u4f8b\u7ba1\u7406\u5bb9\u5668\uff0c\u4e0b\u6b21\u76f4\u63a5\u83b7\u53d6\u4e0d\u9700\u8981\u52a0\u8f7dDefaultRedisScript&lt;Long&gt; buildLuaScript =Singleton.get(STOCK_DECREMENT_AND_SAVE_USER_RECEIVE_LUA_PATH,()-&gt;{DefaultRedisScript&lt;Long&gt; redisScript =newDefaultRedisScript&lt;&gt;();\n &nbsp; &nbsp; &nbsp; &nbsp;redisScript.setScriptSource(newResourceScriptSource(newClassPathResource(STOCK_DECREMENT_AND_SAVE_USER_RECEIVE_LUA_PATH)));\n &nbsp; &nbsp; &nbsp; &nbsp;redisScript.setResultType(Long.class);return redisScript;});\n\u200b\n &nbsp; &nbsp;\/\/ \u9a8c\u8bc1\u7528\u6237\u662f\u5426\u7b26\u5408\u4f18\u60e0\u5238\u9886\u53d6\u6761\u4ef6JSONObject receiveRule =JSON.parseObject(couponTemplate.getReceiveRule());String limitPerPerson = receiveRule.getString(\"limitPerPerson\");\n\u200b\n &nbsp; &nbsp;\/\/ \u6267\u884c LUA \u811a\u672c\u8fdb\u884c\u6263\u51cf\u5e93\u5b58\u4ee5\u53ca\u589e\u52a0 Redis \u7528\u6237\u9886\u5238\u8bb0\u5f55\u6b21\u6570String couponTemplateCacheKey =String.format(EngineRedisConstant.COUPON_TEMPLATE_KEY, requestParam.getCouponTemplateId());String userCouponTemplateLimitCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIMIT_KEY,UserContext.getUserId(), requestParam.getCouponTemplateId());Long stockDecrementLuaResult = stringRedisTemplate.execute(\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;buildLuaScript,ListUtil.of(couponTemplateCacheKey, userCouponTemplateLimitCacheKey),String.valueOf(couponTemplate.getValidEndTime().getTime()), limitPerPerson\n &nbsp;  );\n\u200b\n &nbsp; &nbsp;\/\/ \u5224\u65ad LUA \u811a\u672c\u6267\u884c\u8fd4\u56de\u7c7b\uff0c\u5982\u679c\u5931\u8d25\u6839\u636e\u7c7b\u578b\u8fd4\u56de\u62a5\u9519\u63d0\u793along firstField =StockDecrementReturnCombinedUtil.extractFirstField(stockDecrementLuaResult);if(RedisStockDecrementErrorEnum.isFail(firstField)){thrownewServiceException(RedisStockDecrementErrorEnum.fromType(firstField));}\n\u200b\n &nbsp; &nbsp;UserCouponRedeemEvent userCouponRedeemEvent =UserCouponRedeemEvent.builder().requestParam(requestParam).receiveCount((int)StockDecrementReturnCombinedUtil.extractSecondField(stockDecrementLuaResult)).couponTemplate(couponTemplate).userId(UserContext.getUserId()).build();SendResult sendResult = userCouponRedeemProducer.sendMessage(userCouponRedeemEvent);\/\/ \u53d1\u9001\u6d88\u606f\u5931\u8d25\u89e3\u51b3\u65b9\u6848\u7b80\u5355\u4e14\u9ad8\u6548\u7684\u903b\u8f91\u4e4b\u4e00\uff1a\u6253\u5370\u65e5\u5fd7\u5e76\u62a5\u8b66\uff0c\u901a\u8fc7\u65e5\u5fd7\u641c\u96c6\u5e76\u91cd\u65b0\u6295\u9012if(ObjectUtil.notEqual(sendResult.getSendStatus().name(),\"SEND_OK\")){\n &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"\u53d1\u9001\u4f18\u60e0\u5238\u5151\u6362\u6d88\u606f\u5931\u8d25\uff0c\u6d88\u606f\u53c2\u6570\uff1a{}\",JSON.toJSONString(userCouponRedeemEvent));}}<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u7684 Event \u4e8b\u4ef6\u4ec5\u4fdd\u7559\u5fc5\u987b\u7684\uff0c\u4e5f\u5c31\u662f v1 \u63a5\u53e3\u540e\u534a\u90e8\u5206\u9700\u8981\u65b0\u589e\u6570\u636e\u5e93\u3001\u7f13\u5b58\u7684\u5185\u5bb9\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Data@Builder@NoArgsConstructor@AllArgsConstructorpublicclassUserCouponRedeemEvent{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * Web \u8bf7\u6c42\u53c2\u6570\n &nbsp; &nbsp; *\/privateCouponTemplateRedeemReqDTO requestParam;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u9886\u53d6\u6b21\u6570\n &nbsp; &nbsp; *\/privateInteger receiveCount;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u4f18\u60e0\u5238\u6a21\u677f\n &nbsp; &nbsp; *\/privateCouponTemplateQueryRespDTO couponTemplate;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u7528\u6237 ID\n &nbsp; &nbsp; *\/privateString userId;}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u6d88\u606f\u6d88\u8d39\u8005<\/h3>\n\n\n\n<p>\u5f00\u53d1\u7528\u6237\u5151\u6362\u4f18\u60e0\u5238\u6d88\u606f\u6d88\u8d39\u8005\uff0c\u5e76\u901a\u8fc7\u5e42\u7b49\u6ce8\u89e3\u907f\u514d\u6d88\u606f\u91cd\u590d\u6d88\u8d39\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u7528\u6237\u5151\u6362\u4f18\u60e0\u5238\u6d88\u606f\u6d88\u8d39\u8005\n * &lt;p&gt;\n * \u4f5c\u8005\uff1a\u9a6c\u4e01\n * \u52a0\u9879\u76ee\u7fa4\uff1a\u65e9\u52a0\u5165\u5c31\u662f\u4f18\u52bf\uff01500\u4eba\u5185\u90e8\u6c9f\u901a\u7fa4\uff0c\u5206\u4eab\u7684\u77e5\u8bc6\u603b\u6709\u4f60\u9700\u8981\u7684 &lt;a href=\"https:\/\/t.zsxq.com\/cw7b9\" \/&gt;\n * \u5f00\u53d1\u65f6\u95f4\uff1a2024-09-10\n *\/@Component@RequiredArgsConstructor@RocketMQMessageListener(\n &nbsp; &nbsp; &nbsp; &nbsp;topic =EngineRockerMQConstant.COUPON_TEMPLATE_REDEEM_TOPIC_KEY,\n &nbsp; &nbsp; &nbsp; &nbsp;consumerGroup =EngineRockerMQConstant.COUPON_TEMPLATE_REDEEM_CG_KEY)@Slf4j(topic =\"UserCouponRedeemConsumer\")publicclassUserCouponRedeemConsumerimplementsRocketMQListener&lt;MessageWrapper&lt;UserCouponRedeemEvent&gt;&gt;{\n\u200b\n &nbsp; &nbsp;privatefinalUserCouponMapper userCouponMapper;privatefinalCouponTemplateMapper couponTemplateMapper;privatefinalUserCouponDelayCloseProducer couponDelayCloseProducer;privatefinalStringRedisTemplate stringRedisTemplate;\n\u200b\n &nbsp; &nbsp;@NoMQDuplicateConsume(\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;keyPrefix =\"user-coupon-redeem:\",\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;key =\"#messageWrapper.keys\",\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;keyTimeout =600)@Transactional(rollbackFor =Exception.class)@OverridepublicvoidonMessage(MessageWrapper&lt;UserCouponRedeemEvent&gt; messageWrapper){\/\/ \u5f00\u5934\u6253\u5370\u65e5\u5fd7\uff0c\u5e73\u5e38\u53ef Debug \u770b\u4efb\u52a1\u53c2\u6570\uff0c\u7ebf\u4e0a\u53ef\u62a5\u5e73\u5b89\uff08\u6bd4\u5982\u6d88\u606f\u662f\u5426\u6d88\u8d39\uff0c\u91cd\u65b0\u6295\u9012\u65f6\u83b7\u53d6\u53c2\u6570\u7b49\uff09\n &nbsp; &nbsp; &nbsp; &nbsp;log.info(\"&#91;\u6d88\u8d39\u8005] \u7528\u6237\u5151\u6362\u4f18\u60e0\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u6d88\u606f\u4f53\uff1a{}\",JSON.toJSONString(messageWrapper));\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;CouponTemplateRedeemReqDTO requestParam = messageWrapper.getMessage().getRequestParam();CouponTemplateQueryRespDTO couponTemplate = messageWrapper.getMessage().getCouponTemplate();String userId = messageWrapper.getMessage().getUserId();\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;int decremented = couponTemplateMapper.decrementCouponTemplateStock(Long.parseLong(requestParam.getShopNumber()),Long.parseLong(requestParam.getCouponTemplateId()),1L);if(!SqlHelper.retBool(decremented)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"&#91;\u6d88\u8d39\u8005] \u7528\u6237\u5151\u6362\u4f18\u60e0\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u6263\u51cf\u4f18\u60e0\u5238\u6570\u636e\u5e93\u5e93\u5b58\u5931\u8d25\uff0c\u6d88\u606f\u4f53\uff1a{}\",JSON.toJSONString(messageWrapper));return;}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6dfb\u52a0 Redis \u7528\u6237\u9886\u53d6\u7684\u4f18\u60e0\u5238\u8bb0\u5f55\u5217\u8868Date now =newDate();DateTime validEndTime =DateUtil.offsetHour(now,JSON.parseObject(couponTemplate.getConsumeRule()).getInteger(\"validityPeriod\"));UserCouponDO userCouponDO =UserCouponDO.builder().couponTemplateId(Long.parseLong(requestParam.getCouponTemplateId())).userId(Long.parseLong(userId)).source(requestParam.getSource()).receiveCount(messageWrapper.getMessage().getReceiveCount()).status(UserCouponStatusEnum.UNUSED.getCode()).receiveTime(now).validStartTime(now).validEndTime(validEndTime).build();\n &nbsp; &nbsp; &nbsp; &nbsp;userCouponMapper.insert(userCouponDO);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u8bb0\u5f55String userCouponListCacheKey =String.format(EngineRedisConstant.USER_COUPON_TEMPLATE_LIST_KEY, userId);String userCouponItemCacheKey =StrUtil.builder().append(requestParam.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\n &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u7531\u4e8e Redis \u5728\u6301\u4e45\u5316\u6216\u4e3b\u4ece\u590d\u5236\u7684\u6781\u7aef\u60c5\u51b5\u4e0b\u53ef\u80fd\u4f1a\u51fa\u73b0\u6570\u636e\u4e22\u5931\uff0c\u800c\u6211\u4eec\u5bf9\u6307\u4ee4\u4e22\u5931\u51e0\u4e4e\u65e0\u6cd5\u5bb9\u5fcd\uff0c\u56e0\u6b64\u6211\u4eec\u91c7\u7528\u7ecf\u5178\u7684\u5199\u540e\u67e5\u8be2\u7b56\u7565\u6765\u5e94\u5bf9\u8fd9\u4e00\u95ee\u9898Double scored;try{\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;scored = stringRedisTemplate.opsForZSet().score(userCouponListCacheKey, userCouponItemCacheKey);\/\/ scored \u4e3a\u7a7a\u610f\u5473\u7740\u53ef\u80fd Redis Cluster \u4e3b\u4ece\u540c\u6b65\u4e22\u5931\u4e86\u6570\u636e\uff0c\u6bd4\u5982 Redis \u4e3b\u8282\u70b9\u8fd8\u6ca1\u6709\u540c\u6b65\u5230\u4ece\u8282\u70b9\u5c31\u5b95\u673a\u4e86\uff0c\u89e3\u51b3\u65b9\u6848\u5c31\u662f\u518d\u65b0\u589e\u4e00\u6b21if(scored ==null){\/\/ \u5982\u679c\u8fd9\u91cc\u4e5f\u65b0\u589e\u5931\u8d25\u4e86\u600e\u4e48\u529e\uff1f\u6211\u4eec\u5927\u6982\u7387\u505a\u4e0d\u5230\u7edd\u5bf9\u7684\u4e07\u65e0\u4e00\u5931\uff0c\u53ea\u80fd\u5c3d\u53ef\u80fd\u589e\u52a0\u6210\u529f\u7387\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}}catch(Throwable ex){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"&#91;\u6d88\u8d39\u8005] \u7528\u6237\u5151\u6362\u4f18\u60e0\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u67e5\u8be2Redis\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u4e3a\u7a7a\u6216\u629b\u5f02\u5e38\uff0c\u53ef\u80fdRedis\u5b95\u673a\u6216\u4e3b\u4ece\u590d\u5236\u6570\u636e\u4e22\u5931\uff0c\u57fa\u7840\u9519\u8bef\u4fe1\u606f\uff1a{}\", ex.getMessage());\/\/ \u5982\u679c\u76f4\u63a5\u629b\u5f02\u5e38\u5927\u6982\u7387 Redis \u5b95\u673a\u4e86\uff0c\u6240\u4ee5\u5e94\u8be5\u5199\u4e2a\u5ef6\u65f6\u961f\u5217\u5411 Redis \u91cd\u8bd5\u653e\u5165\u503c\u3002\u4e3a\u4e86\u907f\u514d\u4ee3\u7801\u590d\u6742\u6027\uff0c\u8fd9\u91cc\u76f4\u63a5\u5199\u65b0\u589e\uff0c\u5927\u5bb6\u77e5\u9053\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5373\u53ef\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForZSet().add(userCouponListCacheKey, userCouponItemCacheKey, now.getTime());}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u5ef6\u65f6\u6d88\u606f\u961f\u5217\uff0c\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\uff0c\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664UserCouponDelayCloseEvent userCouponDelayCloseEvent =UserCouponDelayCloseEvent.builder().couponTemplateId(requestParam.getCouponTemplateId()).userCouponId(String.valueOf(userCouponDO.getId())).userId(userId).delayTime(validEndTime.getTime()).build();SendResult sendResult = couponDelayCloseProducer.sendMessage(userCouponDelayCloseEvent);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d1\u9001\u6d88\u606f\u5931\u8d25\u89e3\u51b3\u65b9\u6848\u7b80\u5355\u4e14\u9ad8\u6548\u7684\u903b\u8f91\u4e4b\u4e00\uff1a\u6253\u5370\u65e5\u5fd7\u5e76\u62a5\u8b66\uff0c\u901a\u8fc7\u65e5\u5fd7\u641c\u96c6\u5e76\u91cd\u65b0\u6295\u9012if(ObjectUtil.notEqual(sendResult.getSendStatus().name(),\"SEND_OK\")){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.warn(\"&#91;\u6d88\u8d39\u8005] \u7528\u6237\u5151\u6362\u4f18\u60e0\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u53d1\u9001\u4f18\u60e0\u5238\u5173\u95ed\u5ef6\u65f6\u961f\u5217\u5931\u8d25\uff0c\u6d88\u606f\u53c2\u6570\uff1a{}\",JSON.toJSONString(userCouponDelayCloseEvent));}}}<\/code><\/pre>\n\n\n\n<p>\u4ee3\u7801\u903b\u8f91\u548c v1 \u57fa\u672c\u4e00\u81f4\uff0c\u8fd9\u4e5f\u4e5f\u5c31\u4e0d\u518d\u8d58\u8ff0\u3002\u503c\u5f97\u4e00\u8bf4\u7684\uff0c\u56e0\u4e3a\u6574\u6bb5\u903b\u8f91\u5df2\u7ecf\u901a\u8fc7\u6d88\u606f\u961f\u5217\u5f02\u6b65\u89e3\u8026\uff0c\u5c31\u6ca1\u6709\u901a\u8fc7 Canal \u8fdb\u884c\u8ba2\u9605\u6d88\u8d39\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u65b9\u6848\u5b58\u5728\u7684\u95ee\u9898<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-redis\">1. Redis \u6781\u7aef\u573a\u666f<\/h3>\n\n\n\n<p>Redis \u63d0\u4f9b\u4e86\u4e24\u5957\u6301\u4e45\u5316\u673a\u5236\uff0cRDB \u5feb\u7167\u548c AOF \u65e5\u5fd7\u6587\u4ef6\u8ffd\u52a0\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>RDB \u5b83\u4f1a\u6839\u636e\u60c5\u51b5\u5b9a\u671f\u7684 Fork \u51fa\u4e00\u4e2a\u5b50\u8fdb\u7a0b\uff0c\u751f\u6210\u5f53\u524d\u6570\u636e\u5e93\u7684\u5168\u91cf\u5feb\u7167\u3002\u5bf9\u4e8e RDB \u5feb\u7167\uff0c<strong>\u5047\u5982\u6211\u4eec\u5728 RDB \u5feb\u7167\u751f\u6210\u540e\u5b95\u673a\uff0c\u90a3\u4e48\u4f1a\u4e22\u5931\u5feb\u7167\u751f\u6210\u671f\u95f4\u5168\u90e8\u589e\u91cf\u6570\u636e\uff0c\u5982\u679c\u5728\u8fde\u5feb\u7167\u90fd\u6ca1\u6210\u529f\u751f\u6210\uff0c\u90a3\u4e48\u5c31\u4f1a\u4e22\u6389\u5168\u90e8\u6570\u636e<\/strong>\u3002<\/li>\n\n\n\n<li>\u53e6\u4e00\u4e2a\u662f AOF\uff0c\u5b83\u901a\u8fc7\u5411 AOF \u65e5\u5fd7\u6587\u4ef6\u8ffd\u52a0\u6bcf\u4e00\u6761\u6267\u884c\u8fc7\u7684\u6307\u4ee4\u5b9e\u73b0\u3002\u800c\u5f53\u6211\u4eec\u4ec5\u5f00\u542f\u4e86 AOF \u65f6\uff0c<strong>\u4e22\u5931\u6570\u636e\u7684\u591a\u5c11\u53d6\u51b3\u4e8e\u6211\u4eec\u8bbe\u7f6e\u7684\u5237\u76d8\u7b56\u7565<\/strong>\uff1a\u5f53\u8bbe\u7f6e\u4e3a\u6bcf\u6761\u6307\u4ee4\u6267\u884c\u540e\u90fd\u5237\u76d8 <code>Always<\/code>\uff0c\u6211\u4eec\u6700\u591a\u4e22\u5931\u4e00\u6761\u6307\u4ee4\uff1b\u5f53\u8bbe\u7f6e\u4e3a\u6bcf\u79d2\u5237\u4e00\u6b21\u76d8\u7684 <code>Eversec<\/code> \u65f6\uff0c\u6700\u591a\u4e22\u5931\u4e00\u79d2\u5185\u7684\u6570\u636e\uff1b\u5f53\u8bbe\u7f6e\u4e3a\u975e\u4e3b\u52a8\u5237\u76d8\u7684 <code>No<\/code> \u65f6\uff0c\u5219\u53ef\u80fd\u4e22\u5931\u4e0a\u6b21\u5237\u76d8\u540e\u5230\u73b0\u5728\u7684\u5168\u90e8\u6570\u636e\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u4ece\u6301\u4e45\u5316\u7684\u89d2\u5ea6\u4e0a\uff0c\u6211\u4eec\u54ea\u6015\u4f7f\u7528\u4e86 AOF \u7684\u6700\u591a\u4e22\u5931\u4e00\u6761\u6307\u4ee4\u914d\u7f6e\uff0c\u4f9d\u7136\u53ef\u80fd\u4f1a\u4e22\u6570\u636e\u573a\u666f\u3002\u8fd9\u91cc\u53ea\u8bf4\u4e22\u6570\u636e\u7684\u573a\u666f\uff0c\u5177\u4f53\u6620\u5c04\u5230\u9879\u76ee\u4e1a\u52a1\u4e2d\u7684\u95ee\u9898\uff0c\u6211\u4eec\u5728\u4e0b\u9762\u7684\u5185\u5bb9\u4e2d\u8bf4\u660e\u3002<\/p>\n\n\n\n<p>\u9664\u6301\u4e45\u5316\u5916\uff0cRedis \u9ed8\u8ba4\u4f7f\u7528\u5f02\u6b65\u590d\u5236\u65b9\u5f0f\u5c06\u4e3b\u8282\u70b9\u7684\u6570\u636e\u4f20\u9012\u7ed9\u4ece\u8282\u70b9\u3002\u8fd9\u610f\u5473\u7740\u5728\u4e3b\u8282\u70b9\u6210\u529f\u5199\u5165\u6570\u636e\u540e\uff0c\u53ef\u80fd\u4f1a\u56e0\u4e3a\u4ece\u8282\u70b9\u6ca1\u6709\u53ca\u65f6\u63a5\u6536\u5230\u8be5\u6570\u636e\u800c\u9020\u6210\u6570\u636e\u4e22\u5931\u3002\u7279\u522b\u662f\u5728\u4e3b\u8282\u70b9\u5d29\u6e83\u6216\u91cd\u542f\u65f6\uff0c\u5982\u679c\u4ece\u8282\u70b9\u5c1a\u672a\u5b8c\u6210\u6570\u636e\u540c\u6b65\uff0c\u6700\u65b0\u7684\u6570\u636e\u5c06\u4f1a\u4e22\u5931\u3002Redis \u7684\u4e09\u79cd\u96c6\u7fa4\u6a21\u5f0f\uff1a\u4e3b\u4ece\u3001\u54e8\u5175\u4ee5\u53ca Cluster \u6a21\u5f0f\u90fd\u4f1a\u6709\u8fd9\u79cd\u95ee\u9898\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7 Redis \u4e22\u6570\u636e\u7684\u573a\u666f\uff0c\u6211\u4eec\u8054\u60f3\u5230\u521a\u597d\u5728\u7528\u6237\u5151\u6362\u4f18\u60e0\u5238\u65f6\uff0cRedis \u4e22\u6570\u636e\u4e86\u4f1a\u5bf9\u4e1a\u52a1\u9020\u6210\u4ec0\u4e48\u5f71\u54cd\uff1f<\/p>\n\n\n\n<p>\u5047\u8bbe\u5f53\u524d Redis \u67d0\u4e2a\u4f18\u60e0\u5238\u6a21\u677f\u5e93\u5b58\u4e3a 1\u3002\u5f53\u5f20\u4e09\u7528\u6237\u5151\u6362\u4f18\u60e0\u5238\uff0cRedis \u6263\u51cf\u8fd4\u56de\u6210\u529f\uff0c\u8fd9\u65f6 Redis \u5e93\u5b58\u5e94\u8be5\u662f 0\uff0c\u7136\u540e\u7a0b\u5e8f\u5f00\u59cb\u53d1\u9001 RocketMQ \u6d88\u606f\u961f\u5217\u6267\u884c\u540e\u7eed\u4fdd\u5b58\u6570\u636e\u5e93\u6d41\u7a0b\u3002\u5f88\u4e0d\u5de7\uff0c\u867d\u7136 Redis \u8fd4\u56de\u4e86\u6210\u529f\uff0c\u4f46\u6301\u4e45\u5316\u5931\u8d25\u6216\u8005 Redis \u4e3b\u8282\u70b9\u5b95\u673a\uff0c\u9020\u6210\u8fd9\u4e2a\u8bb0\u5f55\u5e76\u6ca1\u6709\u771f\u6b63\u610f\u4e49\u4e0a\u6267\u884c\u5b8c\u6210\u3002\u8fd9\u4e2a\u65f6\u5019\u674e\u56db\u6765\u5151\u6362\u4f18\u60e0\u5238\uff0c\u53d1\u73b0 Redis \u4f18\u60e0\u5238\u6a21\u677f\u8fd8\u662f 1\uff0c\u6263\u51cf\u7136\u540e\u53d1\u9001 RocketMQ\u3002<\/p>\n\n\n\n<p>\u622a\u6b62\u76ee\u524d\uff0c\u5f20\u4e09\u548c\u674e\u56db\u7684\u4f18\u60e0\u5238\u5151\u6362\u90fd\u662f\u8fd4\u56de\u6210\u529f\u7684\u3002\u4f46\u662f RocketMQ \u6d88\u8d39\u8005\u6d88\u8d39\u65f6\u53ea\u6709\u4e00\u4e2a\u80fd\u6210\u529f\uff0c\u8fd9\u5c31\u9020\u6210\u4e86\u95ee\u9898\uff0c\u674e\u56db\u5728\u4f7f\u7528\u7684\u65f6\u5019\u53d1\u73b0\u4f18\u60e0\u5238\u7528\u4e0d\u4e86\uff0c\u56e0\u4e3a\u53d7\u6d88\u8d39\u8005\u5e93\u5b58\u6821\u9a8c\uff0c\u5e76\u6ca1\u6709\u5c06\u4f18\u60e0\u5238\u8bb0\u5f55\u65b0\u589e\u5230\u6570\u636e\u5e93\u4e2d\u3002\u8be5\u65b9\u6848 <strong>\u9020\u6210\u7684\u5f71\u54cd\u5c31\u662f\u7528\u6237\u770b\u5230\u8fd4\u56de\u4f18\u60e0\u5238\u6210\u529f\uff0c\u4f46\u662f\u5b9e\u9645\u4e0a\u6ca1\u6709\u529e\u6cd5\u4f7f\u7528<\/strong>\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u5e93\u5b58\u6263\u51cf\u7684\u51e0\u79cd\u573a\u666f<\/h3>\n\n\n\n<p>\u5728\u5e94\u5bf9\u4e8e\u4f01\u4e1a\u4e2d\u4e0d\u540c\u573a\u666f\u7684\u5e93\u5b58\u6263\u51cf\u9700\u6c42\uff0c\u8fd9\u91cc\u5206\u6790\u4e0b\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5728\u5546\u54c1\u6d41\u91cf\u8f83\u4f4e\u7684\u60c5\u51b5\u4e0b\uff0c\u901a\u5e38\u4e0d\u4f1a\u51fa\u73b0\u5927\u91cf\u8bf7\u6c42\u540c\u65f6\u8bbf\u95ee\u5355\u4e2a\u5546\u54c1\u8fdb\u884c\u5e93\u5b58\u6263\u51cf\u3002\u6b64\u65f6\uff0c\u53ef\u4ee5\u4f7f\u7528 Redis \u8fdb\u884c\u9632\u62a4\uff0c\u5e76\u76f4\u63a5\u540c\u6b65\u5230 MySQL \u8fdb\u884c\u5e93\u5b58\u6263\u51cf\uff0c\u4ee5\u9632\u6b62\u5546\u54c1\u8d85\u5356\u3002\u867d\u7136\u5728\u6b64\u573a\u666f\u4e2d\u6d89\u53ca\u591a\u4e2a\u5546\u54c1\u7684\u6570\u636e\u6263\u51cf\uff0c\u53ef\u80fd\u4f1a\u51fa\u73b0\u9501\u7ade\u4e89\uff0c\u4f46\u7ade\u4e89\u7a0b\u5ea6\u901a\u5e38\u4e0d\u4f1a\u5f88\u6fc0\u70c8\u3002<\/li>\n\n\n\n<li>\u5bf9\u4e8e\u79d2\u6740\u5546\u54c1\uff0c\u901a\u5e38\u4f1a\u5728\u77ed\u65f6\u95f4\u5185\u51fa\u73b0\u5927\u91cf\u8bf7\u6c42\u540c\u65f6\u8bbf\u95ee\u5355\u4e2a\u5546\u54c1\u8fdb\u884c\u5e93\u5b58\u6263\u51cf\u3002\u4e3a\u6b64\uff0c\u53ef\u4ee5\u4f7f\u7528 Redis \u8fdb\u884c\u9632\u62a4\uff0c\u5e76\u76f4\u63a5\u5c06\u5e93\u5b58\u6263\u51cf\u540c\u6b65\u5230 MySQL\uff0c\u4ee5\u9632\u6b62\u5546\u54c1\u8d85\u5356\u3002\u7531\u4e8e\u79d2\u6740\u5546\u54c1\u7684\u5e93\u5b58\u4e00\u822c\u8f83\u5c11\uff0c\u56e0\u6b64\u9020\u6210\u7684\u9501\u7ade\u4e89\u76f8\u5bf9\u53ef\u63a7\u3002\u5047\u8bbe\u5e93\u5b58\u6263\u51cf\u91c7\u7528\u4e32\u884c\u65b9\u5f0f\uff0c\u6bcf\u6b21\u6263\u51cf\u8017\u65f6 5 \u6beb\u79d2\uff0c\u5904\u7406 100 \u4e2a\u5e93\u5b58\u4e5f\u4ec5\u9700 500 \u6beb\u79d2\u3002<\/li>\n\n\n\n<li>\u67d0\u4e9b\u79d2\u6740\u5546\u54c1\u7684\u5e93\u5b58\u8f83\u591a\uff0c\u6216\u540c\u65f6\u8fdb\u884c\u591a\u4e2a\u70ed\u95e8\u5546\u54c1\u7684\u79d2\u6740\uff08\u5982\u76f4\u64ad\u95f4\u5546\u54c1\uff09\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u76f4\u63a5\u6263\u51cf\u6570\u636e\u5e93\u5e93\u5b58\u4f1a\u7ed9\u7cfb\u7edf\u5e26\u6765\u8f83\u5927\u538b\u529b\uff0c\u5bfc\u81f4\u63a5\u53e3\u54cd\u5e94\u5ef6\u8fdf\u3002\u4e3a\u5e94\u5bf9\u8fd9\u79cd\u573a\u666f\uff0c\u6211\u4eec\u8bbe\u8ba1\u4e86\u4f18\u60e0\u5238\u79d2\u6740 v2 \u63a5\u53e3\u3002\u867d\u7136\u57fa\u4e8e Redis \u6263\u51cf\u5e93\u5b58\u548c\u6d88\u606f\u961f\u5217\u5f02\u6b65\u5904\u7406\u7684\u65b9\u6848\u53ef\u80fd\u4f1a\u5f15\u53d1\u524d\u540e\u4e0d\u4e00\u81f4\u7684\u95ee\u9898\uff0c\u4f46\u5b83\u80fd\u663e\u8457\u63d0\u5347\u6027\u80fd\u3002\u6b64\u5916\uff0cRedis \u7684\u6301\u4e45\u5316\u548c\u4e3b\u4ece\u5b95\u673a\u7684\u98ce\u9669\u76f8\u5bf9\u8f83\u5c0f\u3002\u5373\u4f7f\u53d1\u751f\u5b95\u673a\uff0c\u5bf9\u5e73\u53f0\u6216\u5546\u5bb6\u6765\u8bf4\uff0c\u4e5f\u4e0d\u4f1a\u9020\u6210\u76f4\u63a5\u7684\u635f\u5931\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u6211\u60f3\u5f3a\u8c03\u7684\u662f\uff0c\u4e0d\u5b58\u5728\u7edd\u5bf9\u7684\u94f6\u5f39\u3002Redis \u4e4b\u6240\u4ee5\u80fd\u5feb\u901f\u54cd\u5e94\uff0c\u662f\u56e0\u4e3a\u5b83\u76f4\u63a5\u4e0e\u5185\u5b58\u4ea4\u4e92\uff0c\u4f5c\u4e3a\u7f13\u5b58\u4e2d\u95f4\u4ef6\uff0c\u5982\u679c\u6bcf\u6b21\u90fd\u4e3a\u4e86\u6570\u636e\u4e00\u81f4\u6027\u800c\u4e0e\u78c1\u76d8\u4ea4\u4e92\uff0c\u90a3\u5c31\u672c\u672b\u5012\u7f6e\u4e86\u3002\u6211\u7814\u7a76\u4e86\u5e02\u573a\u4e0a\u7684\u4e91 Redis\uff0c\u5305\u62ec\u817e\u8baf Redis \u548c\u963f\u91cc\u4e91 Tair\uff0c\u53d1\u73b0\u5b83\u4eec\u7684\u6301\u4e45\u5316\u548c\u4e3b\u4ece\u590d\u5236\u672c\u8d28\u4e0a\u90fd\u662f\u5f02\u6b65\u7684\u3002<\/p>\n\n\n\n<p>\u5728\u63d0\u5230 Redis \u6263\u51cf\u5e93\u5b58\u548c RocketMQ \u5f02\u6b65\u573a\u666f\u65f6\uff0c\u5982\u679c Redis \u771f\u7684\u4e22\u5931\u4e86\u6570\u636e\uff0c\u5e94\u8be5\u600e\u4e48\u5904\u7406\u5462\uff1f\u6211\u60f3\u5230\u4e86\u4e00\u79cd\u79d2\u6740\u7684\u601d\u8def\u3002\u7c7b\u4f3c\u4e8e\u5728 12306 \u8d2d\u7968\u6216\u94f6\u884c\u8f6c\u8d26\u65f6\uff0c\u5f53\u4f60\u63d0\u4ea4\u8bf7\u6c42\u540e\u5e76\u4e0d\u4f1a\u7acb\u5373\u5f97\u5230\u6210\u529f\u7684\u53cd\u9988\uff0c\u800c\u662f\u4f1a\u770b\u5230\u4e00\u4e2a\u7b49\u5f85\u754c\u9762\uff0c\u7136\u540e\u5728\u4e00\u6bb5\u65f6\u95f4\u540e\u518d\u544a\u77e5\u4f60\u7ed3\u679c\u3002\u5982\u679c\u5c06\u8fd9\u4e2a\u6a21\u5f0f\u5e94\u7528\u5230\u79d2\u6740\u573a\u666f\u4e2d\uff0c\u53ef\u4ee5\u8bbe\u60f3\u5728 Redis \u4e2d\u6210\u529f\u6263\u51cf\u5e93\u5b58\u5e76\u6295\u9012\u6d88\u606f\u5230\u961f\u5217\u540e\uff0c\u8fd4\u56de\u7ed9\u7528\u6237\u4e00\u4e2a\u201c\u7b49\u5f85\u5b8c\u6210\u201d\u7684\u9875\u9762\u3002\u5927\u90e8\u5206\u60c5\u51b5\u4e0b\uff0c\u8fd4\u56de\u8fd9\u4e2a\u9875\u9762\u7684\u7528\u6237\u6709 99.9999% \u7684\u6982\u7387\u662f\u6210\u529f\u7684\u3002\u968f\u540e\uff0c\u524d\u7aef\u53ef\u4ee5\u5411\u540e\u7aef\u8bf7\u6c42\u5177\u4f53\u7ed3\u679c\uff0c\u53ea\u6709\u5728\u6d88\u606f\u961f\u5217\u7684\u6d88\u8d39\u8005\u6210\u529f\u6263\u51cf\u6570\u636e\u5e93\u540e\uff0c\u624d\u4f1a\u8fd4\u56de\u771f\u6b63\u7684\u6210\u529f\u901a\u77e5\u3002<\/p>\n\n\n\n<p>\u8fd9\u79cd\u65b9\u6cd5\u9002\u5408\u5f3a\u7ed1\u5b9a\u7684\u4e1a\u52a1\uff0c\u6bd4\u5982 12306 \u6216\u94f6\u884c\uff0c\u56e0\u4e3a\u7528\u6237\u5fc5\u987b\u4f7f\u7528\u5b83\u4eec\u7684 App\u3002\u76f8\u5bf9\u800c\u8a00\uff0c\u5982\u679c\u662f\u7535\u5546\u573a\u666f\uff0c\u7528\u6237\u53ef\u80fd\u5bf9\u8fd9\u79cd\u4ea4\u4e92\u4e0d\u592a\u53cb\u597d\uff0c\u56e0\u6b64\u4e0d\u592a\u613f\u610f\u4f7f\u7528\u4f60\u7684\u5e73\u53f0\u3002\u8fd9\u4e2a\u65b9\u6cd5\u53ef\u4ee5\u4f5c\u4e3a\u9762\u8bd5\u65f6\u7684\u8ba8\u8bba\u70b9\uff0c\u4f46\u5728\u5b9e\u9645\u7535\u5546\u73af\u5883\u4e2d\uff0c\u8865\u507f\u673a\u5236\u7684\u5e94\u7528\u53ef\u80fd\u66f4\u4e3a\u666e\u904d\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u6280\u672f\u67b6\u6784\u5e76\u975e\u4e00\u6210\u4e0d\u53d8\uff0c\u5408\u9002\u7684\u4e1a\u52a1\u573a\u666f\u914d\u5408\u5bf9\u5e94\u7684\u67b6\u6784\u5f80\u5f80\u80fd\u53d1\u6325\u6700\u5927\u7684\u6548\u7528\u3002\u5bf9\u4e8e\u7c7b\u4f3c\u8ba2\u5355\u6216 12306 \u62a2\u7968\u8fd9\u6837\u7684\u573a\u666f\uff0c\u6bcf\u4e00\u7b14\u6570\u636e\u90fd\u5fc5\u987b\u7cbe\u786e\u65e0\u8bef\uff0c\u8fd9\u79cd\u60c5\u51b5\u4e0b\u5982\u679c\u4e0d\u4f9d\u8d56\u6570\u636e\u5e93\u4fdd\u969c\u4e00\u81f4\u6027\uff0c\u5355\u7eaf\u4f9d\u8d56 Redis \u7f13\u5b58\u4f1a\u5b58\u5728\u4e00\u5b9a\u7684\u4e0d\u8db3\u3002<\/p>\n\n\n\n<p>\u4f46\u5bf9\u4e8e\u7528\u6237\u4f18\u60e0\u5238\u573a\u666f\uff0c\u5076\u5c14\u591a\u53d1\u4e00\u5f20\u4f18\u60e0\u5238\u95ee\u9898\u4e0d\u5927\uff0c\u56e0\u6b64\u6ca1\u5fc5\u8981\u5c06\u538b\u529b\u8fc7\u591a\u8f6c\u79fb\u5230\u6570\u636e\u5e93\uff0c\u6bd5\u7adf\u6570\u636e\u5e93\u662f\u5b9d\u8d35\u7684\u8d44\u6e90\u3002\u901a\u8fc7\u6d88\u606f\u961f\u5217\u8fdb\u884c\u5f02\u6b65\u89e3\u8026\uff0c\u4e0d\u4ec5\u53ef\u4ee5\u51cf\u5c11\u6570\u636e\u5e93\u7684\u538b\u529b\uff0c\u8fd8\u80fd\u63d0\u9ad8\u7cfb\u7edf\u7684\u541e\u5410\u91cf\uff0c\u80af\u5b9a\u66f4\u4e3a\u5408\u9002\u3002<\/p>\n\n\n\n<p>\u5982\u679c\u4e0d\u60f3\u591a\u53d1\u4f18\u60e0\u5238\uff0c\u90a3\u6211\u4eec\u53ef\u4ee5\u5728\u7528\u6237\u4f7f\u7528\u4f18\u60e0\u5238\u65f6\uff0c\u53d1\u73b0\u6570\u636e\u5e93\u4e2d\u6ca1\u6709\u8fd9\u4e2a\u8bb0\u5f55\uff0c\u5c31\u5c06\u7528\u6237\u7684\u4f18\u60e0\u5238\u7f13\u5b58\u5220\u9664\uff0c\u6765\u786e\u4fdd\u6570\u636e\u7684\u51c6\u786e\u6027\u3002\u5f53\u7136\u8fd9\u79cd\u53ef\u80fd\u4f1a\u5f15\u8d77\u7528\u6237\u53cd\u611f\uff0c\u5177\u4f53\u53ef\u4ee5\u548c\u4ea7\u54c1\u6c9f\u901a\u8fd9\u79cd\u65b9\u6848\u600e\u4e48\u89e3\u51b3\uff0c\u8bbe\u7f6e\u4e0d\u53ef\u7528\u7684\u6807\u8bb0\uff0c\u6216\u8005\u76f4\u63a5\u7ed9\u7528\u6237\u8865\u4e0a\u90fd\u53ef\u4ee5\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<p>\u5927\u4f6c\u4eec\uff0c\u9a6c\u54e5\u8bf4\u5355\u7eaf\u4f9d\u8d56 Redis \u7f13\u5b58\u4f1a\u5b58\u5728\u4e00\u5b9a\u7684\u4e0d\u8db3\uff0c\u53ef\u80fd\u9020\u6210\u5076\u5c14\u591a\u53d1\u4e00\u5f20\u4f18\u60e0\u5238\u95ee\u9898\u3002\u8bf7\u95ee\u5728\u4ec0\u4e48\u60c5\u51b5\u4e0b\uff0c\u4f1a\u5bfc\u81f4\u591a\u53d1\u4e00\u5f20\u4f18\u60e0\u5238\u5462<br>\u7ea2\u7ea2\u706b\u706b \u56de\u590d Dam\uff1a\u79d2\u6740\u903b\u8f91\u7684\u7b2c\u4e00\u6b65\u5c31\u662f\u5728redis\u4e2d\u5224\u65ad\u4f18\u60e0\u5377\u662f\u5426\u6709\u5e93\u5b58\u4ee5\u53ca\u7528\u6237\u5df2\u9886\u53d6\u8fd9\u5f20\u4f18\u60e0\u5377\u7684\u6b21\u6570\uff0c\u5982\u679c\u6ca1\u5e93\u5b58\u4e86\u6216\u8005\u9886\u53d6\u5df2\u8fbe\u4e0a\u9650\u5c31\u76f4\u63a5\u8fd4\u56de\u3002\u5f53\u7f13\u5b58\u8fd9\u5173\u901a\u8fc7\u4e4b\u540e\uff0c\u9700\u8981\u4fee\u6539\u6570\u636e\u5e93\uff0c\u5e76\u5c06\u7528\u6237\u5df2\u9886\u53d6\u6b21\u6570\u5237\u65b0\u5230\u7f13\u5b58\u4e2d\uff0c\u4f46\u662f\u56e0\u4e3a\u8fd9\u6b65\u662f\u4f7f\u7528\u6d88\u606f\u961f\u5217\u5f02\u6b65\u6267\u884c\u7684\uff0c\u5982\u679c\u8fd9\u6761\u6d88\u606f\u8fd8\u6ca1\u6267\u884c\u5b8c\u65f6\uff0c\u8fd9\u4e2a\u7528\u6237\u53c8\u51c6\u5907\u9886\u53d6\u4f18\u60e0\u5377\uff0c\u5728redis\u4e2d\u6821\u9a8c\u5df2\u9886\u53d6\u6b21\u6570\u65f6\u5c31\u4f1a\u51fa\u73b0\u4e0d\u4e00\u81f4\u7684\u95ee\u9898\u4e86\uff0credis\u4e2d\u8bb0\u5f55\u7684\u5df2\u9886\u53d6\u6b21\u6570\u6bd4\u6570\u636e\u5e93\u4e2d\u7684\u5c11\uff0c\u53ef\u80fd\u4f1a\u591a\u9886\u3002<br><br>Young \u56de\u590d \u7ea2\u7ea2\u706b\u706b\uff1a\u4f60\u8fd9\u4e2a\u8bf4\u6cd5\u6709\u70b9\u95ee\u9898\uff0c\u7528\u6237\u5df2\u9886\u53d6\u6b21\u6570\u7684\u6539\u53d8\u662f\u5728LUA\u811a\u672c\u4e2d\u5b8c\u6210\u7684<br>\u674e\u6e29\u5019 \u56de\u590d Dam\uff1a\u674e\u6e29\u5019 \u56de\u590d Dam\uff1a\u6211\u7684\u7406\u89e3\uff1a\u64cd\u4f5c\u6d41\u7a0b\u662f\u8fd9\u6837\u7684\uff0c\u5148\u64cd\u4f5credis\uff0c\u518d\u5f02\u6b65\u64cd\u4f5cmysql, \u4e5f\u5c31\u662f\u8bf4\u64cd\u4f5c\u5b8creids\u4e4b\u540e\uff0c\u53d1\u5b8c\u4fe1\u606f\u5c31\u76f4\u63a5\u8fd4\u56de\u4e86\u7136\u540e\u540e\u9762\u518d\u64cd\u4f5cmysql\u6263\u51cf\u5e93\u5b58\u5565\u7684\uff0c\u4f46\u662f\u5982\u679credis\u5b95\u673a\u4e86\uff0c\u7136\u540e\u4e22\u5931\u4e86\u6211\u4eec\u5728lua\u811a\u672c\u91cc\u9762\u7684\u547d\u4ee4\uff08\u76f8\u5f53\u4e8e\u6263\u51cf\u5e93\u5b58\u6ca1\u6210\u529f\uff09\uff0c\u8fd9\u65f6\u5019redis\u7684\u5e93\u5b58\u5c31\u6bd4\u5b9e\u73b0\u7684\u5e93\u5b58\u591a\uff0c\u8fd9\u6837\u5c31\u5bfc\u81f4\u591a\u53d1\u4f18\u60e0\u5238\u60c5\u51b5<br>\u9a6c\u4e01 \u56de\u590d Dam\uff1a\u5df2\u66f4\u65b0\u6587\u6863\uff0c\u8bf7\u67e5\u770b\u3010\u65b9\u6848\u5b58\u5728\u7684\u95ee\u9898\u3011\u7ae0\u8282<br><br>\u3002 \u56de\u590d Dam\uff1a\u6211\u89c9\u5f97\u5927\u6982\u7387\u662f\uff1aRedis\u4e3b\u5b58\u540c\u6b65\u95ee\u9898\uff0cLUA\u6267\u884c\u6210\u529f\uff0c\u4e3b\u8282\u70b9\u5b95\u673a\u4f46\u4ece\u8282\u70b9\u672a\u540c\u6b65\uff0c\u5bfc\u81f4\u6570\u636e\u4e0d\u4e00\u81f4\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>II\uff1a\u9a6c\u54e5\uff0c\u8fd9\u7b2c\u4e8c\u79cd\u65b9\u5f0f\u5982\u4f55\u4fdd\u969cmysql\u548credis\u7684\u6570\u636e\u4e00\u81f4\u6027\u95ee\u9898\uff1f<br>\u65b9\u5377 \u56de\u590d II\uff1a\u4f7f\u7528\u8fd9\u79cd\u65b9\u6848\u7684\u524d\u63d0\u662f\u53ef\u4ee5\u63a5\u53d7\u5c11\u91cf\u7684\u4f18\u60e0\u5238\u591a\u9886\u6216\u8005\u5c11\u9886\uff0c\u4e5f\u5c31\u662f\u4e0d\u90a3\u4e48\u5f3a\u8c03\u4e00\u81f4\u6027\u95ee\u9898<\/p>\n\n\n\n<p>Tiam. \u56de\u590d II\uff1a\u5b9e\u5728\u88ab\u9762\u8bd5\u5b98\u5201\u96be\u7684\u65f6\u5019,\u53ef\u4ee5\u8bf4\u5982\u679c\u4e22\u5931redis\u547d\u4ee4,\u7528\u6237\u663e\u793a\u6263\u51cf\u6210\u529f,\u4f46\u662f\u56e0\u4e3amysql\u6700\u7ec8\u5224\u65ad\u5e93\u5b58\u5df2\u4e3a\u96f6\u6267\u884c\u5931\u8d25,\u4f1a\u6839\u636e\u5931\u8d25\u65e5\u5fd7\u6253\u5370,\u8fdb\u884c\u8865\u507f\u673a\u5236,\u867d\u7136\u8fd9\u4e2a\u6982\u7387\u5f88\u4f4e \u4ec5\u5b58\u5728redis\u5b95\u673a\u8fd9\u79cd\u6761\u4ef6<br><\/p>\n\n\n\n<p>\u5495\u565c\u7075\u6ce2\uff1a\u8fd9\u91cc\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6b21\u6570\uff0c\u8ddf\u4f18\u60e0\u5238\u5206\u53d1\u91cc\u9762\u7684\u6ca1\u6709\u51b2\u7a81\u5417\uff0c\u5206\u53d1\u91cc\u5206\u53d1\u7684\u4f18\u60e0\u5238\u6ca1\u6709\u8bbe\u7f6e\u9886\u53d6\u6b21\u6570\u7684key\u3002<br>\u9a6c\u4e01 \u56de\u590d \u5495\u565c\u7075\u6ce2\uff1a\u8fd9\u4e2a\u63d0\u7684\u5f88\u597d\uff0c\u5e94\u8be5\u8981\u5728\u5206\u53d1\u7684 Lua [stock_decrement_and_batch_save_user_record.lua] \u91cc\u52a0\u4e0a\u5bf9\u5e94\u7684\u9886\u53d6 Key \u9650\u5236<\/p>\n\n\n\n<p>\u9884\u5907Mser\uff1a\u9a6c\u54e5\uff0c\u786e\u5b9e\u89c1\u8fc7\u95ee\u7f13\u5b58\u8fd9\u8fb9\u4e3b\u4ece\u67b6\u6784\uff0c\u4e3b\u6302\u4e86\u4e14\u5c1a\u672a\u540c\u6b65\uff0c\u5bfc\u81f4\u6570\u636e\u4e0d\u4e00\u81f4\u4e14\u4e00\u5b9a\u8981\u5728redis\u8fd9\u89e3\u51b3\u95ee\u9898\u7684\u9762\u8bd5\u5b98\u3002\u5982\u679c\u786c\u8981\u56de\u7b54\u8bdd\u662f\u8bf4\u7528\u4e3b\u4ece\u7684\u534a\u540c\u6b65\u673a\u5236\u8fd8\u662f\u8bf4\u6ca1\u6cd5\u89e3\u51b3\uff0c\u53ea\u80fd\u4f9d\u9760\u6700\u7ec8\u7ed3\u679c\u7528mysql\u548credis\u5bf9\u8d26\u6700\u540e\u8865\u507f<br>o_0 \u56de\u590d \u9884\u5907Mser\uff1a\u53ef\u4ee5\u770b\u770bcache key\u9009\u62e9\u6027\u8bfb\u4e3b\u4ece\u65b9\u6848<\/p>\n\n\n\n<p>\u6ce1\u9762\u5927\u738b\uff1a\u5bf9\u4e8e\u4f18\u60e0\u5238\u8d85\u53d1\u8865\u507f\uff0c\u5b9e\u9645\u5de5\u4f5c\u4e2d\u600e\u4e48\u8865\u507f\u7684\uff0c\u80fd\u4e3e\u4e2a\u4f8b\u5b50\u5417\uff1f<\/p>\n\n\n\n<p>\u8c46\u7c73\uff1a\u5927\u4f6c\u4eec\uff0c\u5982\u679c\u51fa\u73b0\u4e86redis\u6263\u51cf\u5e93\u5b58\u4e86\uff0c\u7136\u540e\u5f02\u6b65\u5904\u7406mysql\u7684\u65f6\u5019\u51fa\u9519\uff0c\u4e8b\u52a1\u56de\u6eda\u4e86\uff0c\u90a3\u5c82\u4e0d\u662f\u90a3\u4e2a\u7528\u6237\u4f9d\u7136\u6ca1\u6709\u79d2\u6740\u6210\u529f\uff1f<br>\u6276\u4e0d\u4e0a\u5899 \u56de\u590d \u8c46\u7c73\uff1a\u8fd9\u79cd\u4e00\u822c\u6765\u8bf4<br>1 \u5982\u679c\u91cd\u8bd5\u53ef\u89e3\u51b3\u6700\u540e\u662fmq\u91cd\u8bd5\u89e3\u51b3\u4e00\u81f4\u6027\u95ee\u9898<br>2 \u4f46\u5982\u679c\u4e00\u76f4\u91cd\u8bd5\u4e0d\u6210\u529f\uff0c \u5e94\u8be5\u8fd8\u662f\u7528\u5b9a\u65f6\u4efb\u52a1 \u8fdb\u884c\u5b9e\u65f6\u6570\u636e\u5bf9\u8d26 \u4fdd\u8bc1\u6700\u7ec8\u4e00\u81f4\u6027<\/p>\n\n\n\n<p>\u82b1\u5f00\u5bcc\u8d35\uff1a\u603b\u7ed3\u4e00\u4e0bv1\u548cv2\u3002<br>v1\u4e2d\u901a\u8fc7lua\u811a\u672c\u6263\u51cf\u4e86\u7f13\u5b58\u4e2d\u7684\u5e93\u5b58\uff0c\u5982\u679c\u6263\u51cf\u6210\u529f\u90a3\u5c31\u8ba9\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u8bb0\u5f55\u5b58\u5165\u6570\u636e\u5e93\uff0c\u5728v1\u4e2d\u6dfb\u52a0\u8bb0\u5f55\u7684\u64cd\u4f5c\u662f\u987a\u5e8f\u6267\u884c\u7684\uff0c\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u8bb0\u5f55\u6210\u529f\u63d2\u6570\u636e\u5e93\u4e4b\u540e\uff0c\u5982\u679cuserCouponListSaveCacheType\u662fdirect\uff0c\u90a3\u5c31\u987a\u5e8f\u6267\u884c\u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u5230redis\u4e2d\u4ee5\u53ca\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\u5230mq\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664\u7684\u64cd\u4f5c\uff0c\u5982\u679cuserCouponListSaveCacheType\u662fbinlog\uff0c\u4e5f\u5c31\u662f\u901a\u8fc7canal\u76d1\u542c\u6570\u636e\u5e93\uff0c\u90a3\u5c31\u7528\u4e00\u4e2a\u6d88\u606f\u6d88\u8d39\u8005\u6765\u5f02\u6b65\u6267\u884c\u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u5230redis\u4ee5\u53ca\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\u5230mq\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664\u7684\u64cd\u4f5c\u3002<br>v2\u5176\u5b9e\u6700\u4e3b\u8981\u7684\u53d8\u5316\u5c31\u662f\u64cd\u4f5c\u6570\u636e\u5e93\u4e0d\u987a\u5e8f\u6267\u884c\u4e86\uff0c\u76ee\u7684\u5c31\u662f\u51cf\u5c11\u6570\u636e\u5e93\u7684\u538b\u529b\u3002\u6267\u884clua\u811a\u672c\u6263\u51cf\u7f13\u5b58\u4e2d\u7684\u5e93\u5b58\u4e4b\u540e\uff0c\u5982\u679c\u6263\u51cf\u6210\u529f\u90a3\u5c31\u53d1\u9001\u4e00\u4e2a\u6d88\u606f\u5230mq\uff0c\u7136\u540e\u7531\u6d88\u8d39\u8005\u5f02\u6b65\u6267\u884c\u63d2\u5165\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u7684\u8bb0\u5f55\u5230\u6570\u636e\u5e93\u4e2d\uff0c\u5982\u679c\u63d2\u5165\u6210\u529f\uff0c\u540e\u9762\u6267\u884c\u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u5230redis\u4e2d\u4ee5\u53ca\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\u5230mq\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664\u7684\u64cd\u4f5c\u4e5f\u90fd\u662f\u5728\u6d88\u8d39\u8005\u4e2d\u6267\u884c\u7684\u3002<br>\u6ce8\u610fv2\u6ca1\u6709\u533a\u5206direct\u548cbinlog\uff0c\u800c\u662f\u76f4\u63a5\u8ba9\u63d2\u5165\u6570\u636e\u5e93\u7684\u64cd\u4f5c\u548c\u6267\u884c\u6dfb\u52a0\u7528\u6237\u9886\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u7f13\u5b58\u5230redis\u4e2d\u4ee5\u53ca\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\u5230mq\u7b49\u5f85\u4f18\u60e0\u5238\u5230\u671f\u540e\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u4ece\u7f13\u5b58\u4e2d\u5220\u9664\u7684\u64cd\u4f5c\u90fd\u5728\u6d88\u8d39\u8005\u4e2d\u6267\u884c\uff0c\u5e76\u6ca1\u6709\u4f7f\u7528canal\u76d1\u542c<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c25\u5c0f\u8282\uff1a\u5f00\u53d1\u4f18\u60e0\u5238\u9884\u7ea6\u901a\u77e5\u529f\u80fd\uff08\u4e00\uff09<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5927\u5bb6\u53ef\u4ee5\u7c7b\u6bd4 12306 \u8d2d\u7968\u9884\u7ea6\u529f\u80fd\u3002\u5f53\u8d2d\u4e70\u7d27\u5f20\u5217\u8f66\u7684\u8f66\u7968\u65f6\uff0c\u6211\u4eec\u901a\u5e38\u4f1a\u63d0\u524d\u8bbe\u7f6e\u9884\u7ea6\u63d0\u9192\uff0c\u4ee5\u4fbf\u5728\u5f00\u7968\u65f6\u53ca\u65f6\u8d2d\u4e70\u3002\u7c7b\u4f3c\u5730\uff0c\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u4e5f\u5177\u6709\u5f88\u5f3a\u7684\u65f6\u6548\u6027\uff0c\u540c\u65f6\u9700\u8981\u652f\u6301\u6d77\u91cf\u7528\u6237\u7684\u63d0\u9192\u9700\u6c42\u3002\u4e3a\u4e86\u5b9e\u73b0\u8fd9\u4e00\u70b9\uff0c\u6211\u4eec\u9009\u62e9\u4e86 RocketMQ 5.x \u7684\u4efb\u610f\u5ef6\u65f6\u6d88\u606f\u529f\u80fd\uff0c\u5e76\u901a\u8fc7\u7ebf\u7a0b\u6c60\u6765\u5e76\u884c\u63d0\u9192\u7528\u6237\u3002<\/p>\n\n\n\n<p>\u5728\u5b9e\u73b0\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u91c7\u7528\u4e86\u4f4d\u56fe\uff08bitmap\uff09\u601d\u60f3\uff0c\u5de7\u5999\u5730\u5229\u7528\u5355\u4e00\u5b57\u6bb5\u5b9e\u73b0\u4e86\u591a\u4e2a\u65f6\u95f4\u6bb5\u7684\u9884\u7ea6\u63d0\u9192\u529f\u80fd\u3002\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\uff0c\u6211\u4eec\u4e0d\u4ec5\u6ee1\u8db3\u4e86\u6d77\u91cf\u63d0\u9192\u7684\u9700\u6c42\uff0c\u8fd8\u786e\u4fdd\u4e86\u7cfb\u7edf\u7684\u9ad8\u6548\u548c\u65f6\u6548\u6027\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u6574\u4f53\u5b9e\u73b0\u8f83\u4e3a\u590d\u6742\uff0c\u6d89\u53ca\u5230\u4e8c\u8fdb\u5236\u64cd\u4f5c\u8f83\u591a\uff0c\u5982\u679c\u5927\u5bb6\u4e0d\u719f\u6089\u4e8c\u8fdb\u5236 &amp;\u3001^\u3001\u4f4d\u79fb\u7b49\u64cd\u4f5c\uff0c\u9700\u8981\u7f51\u4e0a\u63d0\u524d\u5b66\u4e60\u4e0b\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240918_dev_coupon-remind-v2_rocketmq-bitmap_youya<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u672c\u7ae0\u8282\u9884\u7ea6\u63d0\u9192\u4f18\u60e0\u5238\u6838\u5fc3\u4ee3\u7801\u7531\u4f18\u96c5\u540c\u5b66\u8d21\u732e\uff0c\u611f\u8c22\u4f18\u96c5\u63d0\u4f9b\u7684\u4f18\u79c0\u4ee3\u7801\u8bbe\u8ba1\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">\u6570\u636e\u5e93\u8868\u8bbe\u8ba1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-sql\">1. \u7528\u6237\u9884\u7ea6\u8868 SQL<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATETABLE`t_coupon_template_remind`(`user_id`bigint(20)NOTNULLCOMMENT'\u7528\u6237ID',`coupon_template_id`bigint(20)NOTNULLCOMMENT'\u5238ID',`information`bigint(20)DEFAULTNULLCOMMENT'\u5b58\u50a8\u4fe1\u606f',`shop_number`bigint(20)DEFAULTNULLCOMMENT'\u5e97\u94fa\u7f16\u53f7',`start_time`datetimeDEFAULTNULLCOMMENT'\u4f18\u60e0\u5238\u5f00\u62a2\u65f6\u95f4',PRIMARYKEY(`user_id`,`coupon_template_id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u7528\u6237\u9884\u7ea6\u63d0\u9192\u4fe1\u606f\u5b58\u50a8\u8868';<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u662f\u5426\u5206\u5e93\u5206\u8868\uff1f<\/h3>\n\n\n\n<p>\u8003\u8651\u5230\u4e3b\u952e\u7531 <code>coupon_template_id<\/code> \u548c <code>user_id<\/code> \u7ec4\u6210\uff0c\u5747\u4e3a <code>bigint<\/code> \u7c7b\u578b\uff0c\u5404\u5360 8 \u5b57\u8282\uff0c\u603b\u8ba1 16 \u5b57\u8282\u3002MySQL \u7684\u9875\u5927\u5c0f\u4e3a 16KB\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u7d22\u5f15\u9875<\/strong>\uff1a\u6bcf\u6761\u8bb0\u5f55\u7531\u4e3b\u952e\uff088 \u5b57\u8282 + 8 \u5b57\u8282\uff09\u52a0\u4e0a\u6307\u9488\uff086 \u5b57\u8282\uff09\u7ec4\u6210\uff0c\u5171\u8ba1 22 \u5b57\u8282\u3002\u56e0\u6b64\uff0c\u7d22\u5f15\u9875\u6700\u591a\u53ef\u5b58\u50a8\uff1a16,384 \u5b57\u8282 \u00f7 22 \u5b57\u8282 \u2248 744 \u6761\u8bb0\u5f55\u3002<\/li>\n\n\n\n<li><strong>\u6570\u636e\u9875<\/strong>\uff1a\u6bcf\u6761\u8bb0\u5f55\u5305\u542b\u4e3b\u952e\uff0816 \u5b57\u8282\uff09\u3001<code>information<\/code>\uff088 \u5b57\u8282\uff09\u3001<code>shop_number<\/code>\uff088 \u5b57\u8282\uff09\u548c <code>start_time<\/code>\uff088 \u5b57\u8282\uff09\uff0c\u5408\u8ba1 40 \u5b57\u8282\u3002\u56e0\u6b64\uff0c\u6570\u636e\u9875\u6700\u591a\u53ef\u5b58\u50a8\uff1a16,384 \u5b57\u8282 \u00f7 40 \u5b57\u8282 \u2248 410 \u6761\u8bb0\u5f55\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u5728\u4e09\u5c42 B+ \u6811\u7ed3\u6784\u4e0b\uff0c\u6700\u5927\u53ef\u5b58\u50a8\u7684\u8bb0\u5f55\u6570\u4e3a\uff1a744\uff08\u7b2c\u4e00\u5c42\uff09\u00d7 744\uff08\u7b2c\u4e8c\u5c42\uff09\u00d7 410\uff08\u53f6\u5b50\u8282\u70b9\uff09\u2248 226,492,160 \u6761\u8bb0\u5f55\u3002<\/p>\n\n\n\n<p>\u5373\u5927\u7ea6 <strong>2.26 \u4ebf\u6761\u8bb0\u5f55<\/strong>\u3002\u8003\u8651\u5230\u5b9e\u9645\u60c5\u51b5\u4e2d\u9875\u5185\u53ef\u80fd\u5b58\u5728\u7684\u5176\u4ed6\u5f00\u9500\uff0c\u8fd9\u4e2a\u6570\u503c\u53ef\u80fd\u4f1a\u7565\u5c11\uff0c\u4f46\u81f3\u5c11\u53ef\u4ee5\u652f\u6301 <strong>2 \u4ebf\u6761\u8bb0\u5f55<\/strong>\u3002<\/p>\n\n\n\n<p>\u5047\u8bbe\u7528\u6237\u91cf\u4e3a <strong>5000 \u4e07<\/strong>\uff0c\u90a3\u4e48\u5e73\u5747\u6bcf\u4e2a\u7528\u6237\u53ef\u4ee5\u9884\u7ea6 <strong>4 \u5f20\u5238<\/strong>\uff0c\u5b8c\u5168\u6ee1\u8db3\u9700\u6c42\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u8bbe\u7f6e\u5b9a\u65f6\u4efb\u52a1\uff0c\u5b9a\u671f\u5220\u9664\u5df2\u8fc7\u671f\u7684\u8bb0\u5f55\uff0c\u53ef\u4ee5\u6709\u6548\u63a7\u5236\u6570\u636e\u91cf\u3002\u56e0\u6b64\uff0c<strong>\u5355\u8868\u7ed3\u6784\u5df2\u7ecf\u8db3\u591f\u627f\u8f7d\u5f53\u524d\u4e1a\u52a1\u9700\u6c42\uff0c\u65e0\u9700\u8fdb\u884c\u5206\u5e93\u5206\u8868<\/strong>\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3-id\">3. \u4e3a\u4ec0\u4e48\u4e0d\u8bbe\u7f6e\u4e3b\u952e ID\uff1f<\/h3>\n\n\n\n<p>\u5982\u679c\u6211\u4eec\u989d\u5916\u521b\u5efa\u4e00\u4e2a\u81ea\u589e\u7684 <code>id<\/code> \u4f5c\u4e3a\u4e3b\u952e\uff0c\u90a3\u4e48\u9664\u4e86\u4e3b\u952e\u7d22\u5f15\u5916\uff0c\u6211\u4eec\u4ecd\u7136\u9700\u8981\u901a\u8fc7 <code>(user_id, coupon_template_id)<\/code> \u552f\u4e00\u5b9a\u4f4d\u4e00\u6761\u8bb0\u5f55\u3002\u8fd9\u610f\u5473\u7740\u6211\u4eec\u8fd8\u9700\u8981\u5efa\u7acb\u4e00\u4e2a\u8054\u5408\u7d22\u5f15 <code>(user_id, coupon_template_id)<\/code> \u6765\u63d0\u9ad8\u67e5\u8be2\u6027\u80fd\u3002\u56e0\u6b64\uff0c\u989d\u5916\u6dfb\u52a0\u4e00\u4e2a <code>id<\/code> \u4f5c\u4e3a\u4e3b\u952e\u5e76\u6ca1\u6709\u5b9e\u9645\u610f\u4e49\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u6ca1\u6709\u663e\u793a\u7ed9\u51fa\u4e3b\u952e\u7684\u8bdd\uff0cMySQL \u4f1a\u627e\u4e2a\u552f\u4e00\u7d22\u5f15\u505a\u4e3b\u952e\uff0c\u5982\u679c\u6ca1\u6709\u552f\u4e00\u7d22\u5f15\uff0c\u5c31\u7ed9\u4e2a\u9690\u85cf\u4e3b\u952e\u3002\u6211\u4eec\u901a\u8fc7\u552f\u4e00\u7d22\u5f15\u5b57\u6bb5\u4f5c\u4e3a\u4e3b\u952e\uff0c\u53ef\u4ee5\u8282\u7701\u989d\u5916\u7684\u4e3b\u952e\u5b57\u6bb5\u5927\u5c0f\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u7531\u4e8e <code>(user_id, coupon_template_id)<\/code> \u672c\u8eab\u5c31\u662f\u552f\u4e00\u7684\uff0c\u6240\u4ee5\u76f4\u63a5\u5c06\u5176\u4f5c\u4e3a\u4e3b\u952e\u65e2\u80fd\u4fdd\u8bc1\u552f\u4e00\u6027\uff0c\u53c8\u80fd\u63d0\u5347\u67e5\u8be2\u6548\u7387\u3002<\/p>\n\n\n\n<p><strong>\u4e3a\u4ec0\u4e48\u9009\u62e9 <code>(user_id, coupon_template_id)<\/code> \u800c\u4e0d\u662f <code>(coupon_template_id, user_id)<\/code> \u4f5c\u4e3a\u4e3b\u952e\uff1f<\/strong><\/p>\n\n\n\n<p>\u56e0\u4e3a\u7528\u6237\u53ef\u80fd\u4f1a\u67e5\u8be2\u81ea\u5df1\u9884\u7ea6\u4e86\u54ea\u4e9b\u63d0\u9192\u5238\uff0c\u6211\u4eec\u9700\u8981\u6839\u636e <code>user_id<\/code> \u6765\u68c0\u7d22\u4ed6\u9884\u7ea6\u7684\u6240\u6709\u5238\u3002\u5c06 <code>user_id<\/code> \u653e\u5728\u524d\u9762\uff0c\u53ef\u4ee5\u7b26\u5408\u7d22\u5f15\u7684\u6700\u5de6\u524d\u7f00\u5339\u914d\u539f\u5219\uff0c\u663e\u8457\u63d0\u9ad8\u67e5\u8be2\u6027\u80fd\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4\">4. \u5b58\u50a8\u4fe1\u606f\u6307\u7684\u662f\u4ec0\u4e48\uff1f<\/h3>\n\n\n\n<p>\u4e00\u4e2a\u7528\u6237\u53ef\u4ee5\u6709\u591a\u4e2a\u5238\uff0c\u6bcf\u4e2a\u5238\u7684\u4fe1\u606f\u90fd\u662f\u7528\u4f4d\u56fe\uff08\u5b58\u50a8\u4fe1\u606f\u5b57\u6bb5\uff09\u5b58\u50a8\u7684\uff0c\u53ef\u4ee5\u5b58\u7528\u6237\u5bf9\u8be5\u4f18\u60e0\u5238\u6a21\u677f\u7684\u6240\u6709\u9884\u7ea6\u6d88\u606f\uff0c\u4e00\u4e2a Long \u7c7b\u578b\u7684\u5b57\u6bb5\u5c31\u641e\u5b9a\u4e86\u3002<\/p>\n\n\n\n<p>\u5b58\u50a8\u4fe1\u606f\u5b57\u6bb5\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528 5 \u5206\u949f\u4f5c\u4e3a\u4e00\u4e2a\u95f4\u9694\uff0c\u652f\u6301\u63d0\u524d\u4e00\u5c0f\u65f6\u63d0\u9192\uff0c\u4e5f\u5c31\u662f\u6700\u591a\u652f\u6301\u4e00\u5171\u6709 12 \u4e2a\u503c\u3002\u5e76\u4e14\uff0c\u6211\u4eec\u80fd\u652f\u6301 5 \u79cd\u901a\u77e5\u65b9\u5f0f\uff0c\u901a\u8fc7\u4f4d\u56fe\u7684\u8bbe\u8ba1\u601d\u8def\u653e\u5230\u4e00\u4e2a\u5b57\u6bb5\u91cc\uff0c\u8be6\u60c5\u770b\u4e0b\u6587\u63cf\u8ff0\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u521b\u5efa\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u4f18\u60e0\u5238\u9884\u7ea6\u62a2\u8d2d\u63d0\u9192\u8bf7\u6c42\u53c2\u6570<\/h3>\n\n\n\n<p>\u9996\u5148\u54b1\u4eec\u5148\u8bf4\u4e0b\u8bf7\u6c42\u53c2\u6570\u7684\u5b57\u6bb5\u90fd\u6709\u54ea\u4e9b\uff0c\u65b9\u4fbf\u540e\u7eed\u7684\u4e1a\u52a1\u4ee3\u7801\u8ddf\u8fdb\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Data@Schema(description =\"\u4f18\u60e0\u5238\u9884\u7ea6\u62a2\u5238\u63d0\u9192\u8bf7\u6c42\u53c2\u6570\u5b9e\u4f53\")publicclassCouponTemplateRemindCreateReqDTO{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u4f18\u60e0\u5238\u6a21\u677fid\n &nbsp; &nbsp; *\/@Schema(description =\"\u4f18\u60e0\u5238\u6a21\u677fid\", example =\"xxxxxx\", required =true)privateString couponTemplateId;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u5e97\u94fa\u7f16\u53f7\n &nbsp; &nbsp; *\/@Schema(description =\"\u5e97\u94fa\u7f16\u53f7\", example =\"1810714735922956666\", required =true)privateString shopNumber;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u63d0\u9192\u65b9\u5f0f\n &nbsp; &nbsp; *\/@Schema(description =\"\u63d0\u9192\u65b9\u5f0f\", example =\"0\", required =true)privateInteger type;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u63d0\u9192\u65f6\u95f4\uff0c\u6bd4\u5982\u4e94\u5206\u949f\uff0c\u5341\u5206\u949f\uff0c\u5341\u4e94\u5206\u949f\n &nbsp; &nbsp; *\/@Schema(description =\"\u63d0\u9192\u65f6\u95f4\", example =\"5\", required =true)privateInteger remindTime;}<\/code><\/pre>\n\n\n\n<p>\u5b57\u6bb5\u89e3\u91ca\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4f18\u60e0\u5238\u6a21\u677f ID\uff1a\u5efa\u8bae\u54b1\u4eec\u521b\u5efa\u65b0\u7684\u4f18\u60e0\u5238\u6a21\u677f\uff0c\u521b\u5efa\u7684\u65f6\u5019 <code>validStartTime<\/code> \u9700\u8981\u4e2a\u6027\u5316\u8bbe\u7f6e\uff0c\u6bd4\u5982\u4f60\u60f3\u8bbe\u7f6e\u63d0\u524d 5\u300110 \u5206\u949f\u63d0\u9192\uff0c\u5047\u8bbe\u5f53\u524d\u65f6\u95f4 10:00\uff0c\u90a3\u53ef\u4ee5\u8bbe\u7f6e 10:20\uff0c\u8fd9\u6837\u90fd\u80fd\u6db5\u76d6\u4f4f 5\u300110 \u5206\u949f\u7684\u9884\u7ea6\u63d0\u9192\u6d4b\u8bd5\u3002<\/li>\n\n\n\n<li>\u5e97\u94fa\u7f16\u53f7\uff1a\u4f7f\u7528\u793a\u4f8b\u5e97\u94fa\u7f16\u53f7\u5373\u53ef\u3002<\/li>\n\n\n\n<li>\u63d0\u9192\u65b9\u5f0f\uff1a\u6bd4\u5982\u624b\u673a APP \u5f39\u6846\u63d0\u9192\u3001\u90ae\u4ef6\u63d0\u9192\u7b49\uff0c\u76ee\u524d\u4e3b\u6d41\u662f\u524d\u8005\uff0c\u6211\u4eec\u8fd9\u91cc 0 \u9ed8\u8ba4\u5c31\u662f\u8fd9\u4e2a\u3002<\/li>\n\n\n\n<li>\u63d0\u9192\u65f6\u95f4\uff1a\u63d0\u524d\u591a\u5c11\u5206\u949f\u63d0\u9192\uff0c\u4ee5 5 \u5206\u949f\u4e3a\u5355\u4f4d\uff0c\u6700\u591a\u652f\u6301\u63d0\u524d\u4e00\u5c0f\u65f6\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u9a8c\u8bc1\u4f18\u60e0\u5238\u662f\u5426\u5b58\u5728<\/h3>\n\n\n\n<p>\u9996\u5148\u901a\u8fc7\u6211\u4eec\u4f18\u60e0\u5238\u6a21\u677f Service \u4e2d\u7684\u67e5\u8be2\u6a21\u677f\u4fe1\u606f\u63a5\u53e3\u8fdb\u884c\u5224\u65ad\uff0c\u770b\u6a21\u677f\u662f\u5426\u5b58\u5728\uff0c\u901a\u8fc7\u8fd9\u4e2a\u53ef\u4ee5\u5224\u65ad\u7f13\u5b58\u51fb\u7a7f\u548c\u7a7f\u900f\u95ee\u9898\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Override@TransactionalpublicvoidcreateCouponRemind(CouponTemplateRemindCreateReqDTO requestParam){\/\/ \u9a8c\u8bc1\u4f18\u60e0\u5238\u662f\u5426\u5b58\u5728\uff0c\u907f\u514d\u7f13\u5b58\u7a7f\u900f\u95ee\u9898\u5e76\u83b7\u53d6\u4f18\u60e0\u5238\u5f00\u62a2\u65f6\u95f4CouponTemplateQueryRespDTO couponTemplate = couponTemplateService\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  .findCouponTemplate(newCouponTemplateQueryReqDTO(requestParam.getShopNumber(), requestParam.getCouponTemplateId()));\/\/ ......}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u521b\u5efa\u6216\u8005\u66f4\u65b0\u4f18\u60e0\u5238\u63d0\u9192<\/h3>\n\n\n\n<p>\u903b\u8f91\u7b80\u5355\u68b3\u7406\u5c31\u662f\uff0c\u67e5\u8be2\u6570\u636e\u5e93\u662f\u5426\u5b58\u5728\uff0c\u4e0d\u5b58\u5728\u521b\u5efa\u4f18\u60e0\u5238\u63d0\u9192\uff0c\u5b58\u5728\u5219\u5c06\u63d0\u9192\u65f6\u95f4\u66f4\u65b0\u5230\u5df2\u6709\u7684\u8bb0\u5f55\u4e2d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Override@TransactionalpublicvoidcreateCouponRemind(CouponTemplateRemindCreateReqDTO requestParam){\/\/ ......\/\/ \u67e5\u8be2\u7528\u6237\u662f\u5426\u5df2\u7ecf\u9884\u7ea6\u8fc7\u4f18\u60e0\u5238\u7684\u63d0\u9192\u4fe1\u606fLambdaQueryWrapper&lt;CouponTemplateRemindDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateRemindDO.class).eq(CouponTemplateRemindDO::getUserId,UserContext.getUserId()).eq(CouponTemplateRemindDO::getCouponTemplateId, requestParam.getCouponTemplateId());CouponTemplateRemindDO couponTemplateRemindDO = couponTemplateRemindMapper.selectOne(queryWrapper);\n\u200b\n &nbsp; &nbsp;\/\/ \u5982\u679c\u6ca1\u521b\u5efa\u8fc7\u63d0\u9192if(couponTemplateRemindDO ==null){\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO =BeanUtil.toBean(requestParam,CouponTemplateRemindDO.class);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u8bbe\u7f6e\u4f18\u60e0\u5238\u5f00\u62a2\u65f6\u95f4\u4fe1\u606f\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO.setStartTime(couponTemplate.getValidStartTime());\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO.setInformation(CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType()));\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO.setUserId(Long.parseLong(UserContext.getUserId()));\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindMapper.insert(couponTemplateRemindDO);}else{Long information = couponTemplateRemindDO.getInformation();Long bitMap =CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType());if((information &amp; bitMap)!=0L){thrownewClientException(\"\u5df2\u7ecf\u521b\u5efa\u8fc7\u8be5\u63d0\u9192\u4e86\");}\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO.setInformation(information ^ bitMap);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindMapper.update(couponTemplateRemindDO, queryWrapper);}\/\/ ......}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-1\">3.1 \u521b\u5efa\u4f18\u60e0\u5238\u62a2\u8d2d\u63d0\u9192<\/h4>\n\n\n\n<p>\u8fd9\u91cc\u6709\u4e2a\u5f88\u590d\u6742\u7684\u70b9\uff0c\u90a3\u5c31\u662f\u5982\u4f55\u901a\u8fc7\u521b\u5efa\u65f6\u95f4\u548c\u63d0\u9192\u7c7b\u578b\u8fdb\u884c\u4f4d\u56fe\u8fd0\u7b97\u4e3a\u4e00\u4e2a\u5b57\u6bb5\uff0c\u8fd9\u91cc\u62bd\u53d6\u4e86\u4e2a\u5de5\u5177\u7c7b\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u4e0b\u4e00\u4e2a\u7c7b\u578b\u7684\u4f4d\u79fb\u91cf\uff0c\u6bcf\u4e2a\u7c7b\u578b\u5360\u752812\u4e2abit\u4f4d\uff0c\u5171\u8ba160\u5206\u949f\n *\/privatestaticfinalintNEXT_TYPE_BITS=12;\n\u200b\n\/**\n * 5\u5206\u949f\u4e3a\u4e00\u4e2a\u95f4\u9694\n *\/privatestaticfinalintTIME_INTERVAL=5;\n\u200b\n\/**\n * \u6839\u636e\u9884\u7ea6\u65f6\u95f4\u548c\u9884\u7ea6\u7c7b\u578b\u8ba1\u7b97bitmap\n *\/publicstaticLongcalculateBitMap(Integer remindTime,Integer type){if(remindTime &gt;TIME_INTERVAL*NEXT_TYPE_BITS){thrownewClientException(\"\u9884\u7ea6\u63d0\u9192\u7684\u65f6\u95f4\u4e0d\u80fd\u65e9\u4e8e\u5f00\u7968\u524d\"+TIME_INTERVAL*NEXT_TYPE_BITS+\"\u5206\u949f\");}return1L&lt;&lt;(type *NEXT_TYPE_BITS+Math.max(0, remindTime \/TIME_INTERVAL-1));}<\/code><\/pre>\n\n\n\n<p>\u56db\u4e2a\u5b57\u6bb5\uff08\u4e24\u4e2a\u5c40\u90e8\u53d8\u91cf\u548c\u4e24\u4e2a\u5165\u53c2\uff09\u542b\u4e49\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NEXT_TYPE_BITS\uff1a\u8868\u793a\u6bcf\u79cd\u63d0\u9192\u7c7b\u578b\u5360\u7528\u7684\u4f4d\u6570\u3002\u6bcf\u4e2a\u7c7b\u578b\u652f\u6301 <strong>12 \u4e2a\u63d0\u9192\u65f6\u95f4\u70b9<\/strong>\uff08\u5982\u6bcf 5 \u5206\u949f\u4e00\u4e2a\u63d0\u9192\uff0c\u6700\u591a\u652f\u6301\u63d0\u524d 60 \u5206\u949f\uff09\uff0c\u610f\u5473\u7740\u6bcf\u4e2a\u63d0\u9192\u7c7b\u578b\u5360\u636e 12 \u4e2a bit \u4f4d\u3002<\/li>\n\n\n\n<li>TIME_INTERVAL\uff1a\u8868\u793a\u63d0\u9192\u65f6\u95f4\u7684\u95f4\u9694\uff0c\u4ee5\u5206\u949f\u4e3a\u5355\u4f4d\u3002\u8fd9\u91cc\u5b9a\u4e49\u4e3a\u6bcf <strong>5 \u5206\u949f<\/strong>\u4f5c\u4e3a\u4e00\u4e2a\u95f4\u9694\u3002\u5373\u6bcf 5 \u5206\u949f\u8ba1\u7b97\u4e00\u6b21\u63d0\u9192\u70b9\u3002<\/li>\n\n\n\n<li>remindTime\uff1a\u4f20\u5165\u7684\u9884\u7ea6\u63d0\u9192\u65f6\u95f4\uff0c\u5355\u4f4d\u662f\u5206\u949f\u3002\u4ee3\u8868\u7528\u6237\u5e0c\u671b\u5728\u4f55\u65f6\u63a5\u6536\u5230\u63d0\u9192\u3002<\/li>\n\n\n\n<li>type\uff1a\u4f20\u5165\u7684\u63d0\u9192\u7c7b\u578b\u3002\u4ee3\u8868\u4e0d\u540c\u7684\u63d0\u9192\u65b9\u5f0f\uff0c\u5982 App \u901a\u77e5\u3001\u90ae\u7bb1\u63d0\u9192\u7b49\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u5728\u725b\u5238\u7cfb\u7edf\u4e2d\uff0c<code>calculateBitMap<\/code> \u65b9\u6cd5\u7528\u4e8e\u6839\u636e\u9884\u7ea6\u65f6\u95f4\u548c\u9884\u7ea6\u7c7b\u578b\u8ba1\u7b97\u76f8\u5e94\u7684 bitmap\u3002\u4f20\u5165\u7684\u53c2\u6570\u5305\u62ec <code>remindTime<\/code>\uff08\u4f8b\u598210\u5206\u949f\uff09\u548c <code>type=0<\/code>\uff08\u90ae\u4ef6\u63d0\u9192\uff0c\u679a\u4e3e\u7c7b <code>CouponRemindTypeEnum<\/code> \u4e2d\u5b9a\u4e49\uff09\u3002\u9996\u5148\uff0c\u5bf9\u63d0\u9192\u65f6\u95f4\u8fdb\u884c\u6821\u9a8c\uff0c\u5f53\u524d\u8bbe\u5b9a\u4e3a\u63d0\u9192\u65f6\u95f4\u4e0d\u80fd\u8d85\u8fc7\u5f00\u7968\u524d60\u5206\u949f\u3002\u5982\u679c\u8d85\u8fc7\u8be5\u65f6\u95f4\uff0c\u7cfb\u7edf\u5c06\u629b\u51fa\u5f02\u5e38\u3002<\/p>\n\n\n\n<p>\u63a5\u7740\uff0c\u6839\u636e\u63d0\u9192\u65f6\u95f4\u548c\u7c7b\u578b\u8ba1\u7b97\u76f8\u5e94\u7684\u6bd4\u7279\u4f4d\u3002\u6211\u4eec\u4f7f\u7528 <code>long<\/code> \u7c7b\u578b\u7684\u5b57\u6bb5\u6765\u5b58\u50a8\u63d0\u9192\u4fe1\u606f\uff0c\u603b\u8ba164\u4e2a\u6bd4\u7279\u4f4d\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000<\/code><\/pre>\n\n\n\n<p>\u6bcf\u79cd\u63d0\u9192\u7c7b\u578b\u5360\u752812\u4e2a\u6bd4\u7279\u4f4d\uff0c\u4ece\u5de6\u5411\u53f3\u4f9d\u6b21\u5b58\u50a8\u4e0d\u540c\u63d0\u9192\u7c7b\u578b\u7684\u65f6\u95f4\u8282\u70b9\u3002\u4ee5\u7c7b\u578b\u4e3a <code>0<\/code> \u4e3a\u4f8b\uff0c\u8be5\u7c7b\u578b\u7684\u63d0\u9192\u65f6\u95f4\u5b58\u50a8\u5728\u7b2c1\u5230\u7b2c12\u4e2a\u6bd4\u7279\u4f4d\uff0c\u6bcf\u4e2a\u6bd4\u7279\u4f4d\u5bf9\u5e94\u4e00\u4e2a5\u5206\u949f\u7684\u65f6\u95f4\u95f4\u9694\u3002<\/p>\n\n\n\n<p>\u5047\u8bbe\u7528\u6237\u9884\u7ea6\u4e86\u7c7b\u578b\u4e3a <code>0<\/code> \u7684\u63d0\u9192\uff0c\u5728\u7b2c10\u5206\u949f\u548c\u7b2c45\u5206\u949f\u7684\u8282\u70b9\uff0c\u5219\u4f1a\u8bbe\u7f6e\u5bf9\u5e94\u7684\u6bd4\u7279\u4f4d\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0010<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u7b2c2\u4f4d\u548c\u7b2c9\u4f4d\u7684\u6bd4\u7279\u88ab\u7f6e\u4e3a <code>1<\/code>\uff0c\u8868\u793a\u9884\u7ea6\u4e8610\u5206\u949f\u548c45\u5206\u949f\u7684\u63d0\u9192\u3002<\/p>\n\n\n\n<p>\u5bf9\u4e8e\u7c7b\u578b\u4e3a <code>1<\/code> \u7684\u63d0\u9192\uff08\u5982\u77ed\u4fe1\u63d0\u9192\uff09\uff0c\u5176\u4fe1\u606f\u5b58\u50a8\u5728\u7b2c13\u5230\u7b2c24\u4e2a\u6bd4\u7279\u4f4d\u3002\u5982\u679c\u7528\u6237\u9884\u7ea6\u4e8615\u5206\u949f\u548c50\u5206\u949f\u7684\u8282\u70b9\uff0c\u7ed3\u679c\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0100 0000 0000 0000<\/code><\/pre>\n\n\n\n<p>\u6bcf\u79cd\u63d0\u9192\u7c7b\u578b\u5747\u5360\u752812\u4e2a\u6bd4\u7279\u4f4d\uff0c\u53ef\u5b58\u50a8\u6700\u591a60\u5206\u949f\u5185\u7684\u63d0\u9192\u4fe1\u606f\u3002\u7531\u4e8e <code>long<\/code> \u7c7b\u578b\u670964\u4e2a\u6bd4\u7279\u4f4d\uff0c\u76ee\u524d\u53ef\u4ee5\u652f\u6301\u6700\u591a5\u79cd\u63d0\u9192\u7c7b\u578b\u3002\u5c3d\u7ba1\u5f53\u524d\u7684\u679a\u4e3e\u4e2d\u4ec5\u5305\u542b\u4e24\u79cd\u63d0\u9192\u65b9\u5f0f\uff0c\u4f46\u4e3a\u4e86\u540e\u7eed\u6269\u5c55\uff0c\u6211\u4eec\u4f9d\u7136\u9009\u62e9\u4f7f\u7528 <code>long<\/code> \u6765\u5b58\u50a8\u8fd9\u4e9b\u4fe1\u606f\u3002<\/p>\n\n\n\n<p>\u5728 <code>calculateBitMap<\/code> \u7684\u8ba1\u7b97\u65b9\u6cd5\u4e2d\uff0c\u8fd4\u56de\u8bed\u53e5\u4e3a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>return 1L &lt;&lt; (type * NEXT_TYPE_BITS + Math.max(0, remindTime \/ TIME_INTERVAL - 1));<\/code><\/pre>\n\n\n\n<p>\u8fd9\u6bb5\u4ee3\u7801\u9996\u5148\u901a\u8fc7 <code>type * NEXT_TYPE_BITS<\/code> \u8ba1\u7b97\u63d0\u9192\u7c7b\u578b\u7684\u504f\u79fb\u91cf\u3002\u4f8b\u5982\uff0c<code>type = 0<\/code> \u65f6\uff0c\u504f\u79fb\u91cf\u4e3a <code>0<\/code>\uff0c\u8868\u793a\u4ece\u7b2c0\u4f4d\u5f00\u59cb\uff1b<code>type = 1<\/code> \u65f6\uff0c\u504f\u79fb\u91cf\u4e3a <code>12<\/code>\uff0c\u8868\u793a\u4ece\u7b2c12\u4f4d\u5f00\u59cb\u5b58\u50a8\u4fe1\u606f\u3002<\/p>\n\n\n\n<p>\u63a5\u4e0b\u6765\uff0c<code>Math.max(0, remindTime \/ TIME_INTERVAL - 1)<\/code> \u662f\u4e3a\u4e86\u786e\u4fdd\u63d0\u9192\u65f6\u95f4\u5728\u6709\u6548\u8303\u56f4\u5185\u3002\u4f7f\u7528 <code>Math.max<\/code> \u7684\u76ee\u7684\u662f\u9632\u6b62 <code>remindTime \/ TIME_INTERVAL - 1<\/code> \u5c0f\u4e8e <code>0<\/code>\uff0c\u8fd9\u901a\u5e38\u4f1a\u53d1\u751f\u5728 <code>remindTime<\/code> \u5c0f\u4e8e5\u5206\u949f\u7684\u60c5\u51b5\u4e0b\u3002\u7406\u8bba\u4e0a\uff0c\u8fd9\u79cd\u60c5\u51b5\u5e94\u8be5\u7531\u524d\u7aef\u786e\u4fdd\uff0c<code>remindTime<\/code> \u7684\u503c\u662f5\u5206\u949f\u7684\u500d\u6570\u3002\u56e0\u6b64\uff0c\u68c0\u9a8c\u903b\u8f91\u53ef\u4ee5\u63d0\u524d\u653e\u5728\u8fd4\u56de\u8bed\u53e5\u4e4b\u524d\uff0c\u5982\u679c <code>remindTime<\/code> \u5c0f\u4e8e5\u5206\u949f\uff0c\u7cfb\u7edf\u76f4\u63a5\u629b\u51fa\u53c2\u6570\u9519\u8bef\u5f02\u5e38\u3002<\/p>\n\n\n\n<p><code>remindTime \/ TIME_INTERVAL - 1<\/code> \u7528\u4e8e\u8ba1\u7b97\u63d0\u9192\u65f6\u95f4\u5e94\u8be5\u8bbe\u7f6e\u7684\u5177\u4f53 bit \u4f4d\u3002\u4f8b\u5982\uff0c\u5982\u679c <code>remindTime = 20<\/code> \u5206\u949f\uff0c\u90a3\u4e48 <code>remindTime \/ TIME_INTERVAL - 1 = 3<\/code>\u3002\u5047\u8bbe <code>type = 0<\/code>\uff0c\u6700\u7ec8\u7ed3\u679c\u5c31\u662f\u5c06 <code>1L<\/code> \u5411\u5de6\u79fb\u52a83\u4f4d\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 <\/code><\/pre>\n\n\n\n<p>\u5411\u5de6\u504f\u79fb3\u4f4d\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000<\/code><\/pre>\n\n\n\n<p>\u8fd9\u8868\u793a <code>type = 0<\/code> \u7684\u63d0\u9192\u572820\u5206\u949f\u7684\u8282\u70b9\u3002<\/p>\n\n\n\n<p>\u5982\u679c <code>type = 1<\/code>\uff0c\u63d0\u9192\u65f6\u95f4\u4e3a15\u5206\u949f\uff0c\u5e26\u5165\u516c\u5f0f\u8ba1\u7b97\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1 * NEXT_TYPE_BITS + Math.max(0, 15 \/ 5 - 1) = 14<\/code><\/pre>\n\n\n\n<p>\u7ed3\u679c\u4e3a14\u4f4d\uff0c\u56e0\u6b64 <code>1L<\/code> \u5411\u5de6\u504f\u79fb14\u4f4d\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000<\/code><\/pre>\n\n\n\n<p>\u8fd9\u8868\u793a <code>type = 1<\/code> \u7684\u63d0\u9192\u572815\u5206\u949f\u7684\u8282\u70b9\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-2\">3.2 \u4fee\u6539\u4f18\u60e0\u5238\u62a2\u8d2d\u63d0\u9192<\/h4>\n\n\n\n<p>\u5982\u679c\u4f18\u60e0\u5238\u63d0\u9192\u5df2\u5b58\u5728\uff0c\u6211\u4eec\u9700\u8981\u5224\u65ad\u63d0\u9192\u662f\u5426\u91cd\u590d\uff0c\u5982\u679c\u91cd\u590d\u5b58\u5728\uff0c\u76f4\u63a5\u629b\u51fa\u5f02\u5e38\uff0c\u5982\u679c\u8bf4\u4e24\u4e2a\u63d0\u9192\u4e0d\u5b58\u5728\u91cd\u53e0\uff0c\u5219\u4f7f\u7528 <code>information ^ bitMap<\/code> \u8fd0\u7b97\u8fdb\u884c\u5408\u5e76\u7ed3\u679c\uff0c\u4fee\u6539\u653e\u5165\u6570\u636e\u5e93\u4e2d\u3002<\/p>\n\n\n\n<p><code>information &amp; bitMap<\/code> \u7528\u4e8e\u68c0\u67e5\u5f53\u524d\u7684\u63d0\u9192\u4fe1\u606f\u662f\u5426\u5df2\u7ecf\u5305\u542b\u4e86\u7528\u6237\u8bbe\u7f6e\u7684\u63d0\u9192\uff0c\u5982\u679c\u76f8\u540c\u4f4d\u7f6e\u4e0a\u7684\u4f4d\u90fd\u662f <code>1<\/code>\uff0c\u5219 <code>if ((information &amp; bitMap) != 0L)<\/code> \u4f1a\u4e3a <code>true<\/code>\uff0c\u7cfb\u7edf\u629b\u51fa\u5f02\u5e38\uff0c\u63d0\u793a\u7528\u6237\u5df2\u7ecf\u521b\u5efa\u8fc7\u8be5\u63d0\u9192\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Long information = couponTemplateRemindDO.getInformation();Long bitMap =CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType());if((information &amp; bitMap)!=0L){thrownewClientException(\"\u5df2\u7ecf\u521b\u5efa\u8fc7\u8be5\u63d0\u9192\u4e86\");}\ncouponTemplateRemindDO.setInformation(information ^ bitMap);<\/code><\/pre>\n\n\n\n<p><code>information ^ bitMap<\/code> \u662f\u5f02\u6216\u8fd0\u7b97\uff0c\u7ed9\u5927\u5bb6\u4e3e\u4e2a\u4f8b\u5b50\u3002\u6211\u4eec\u5047\u8bbe\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.<code>information<\/code> \u5f53\u524d\u8868\u793a\u7528\u6237\u5df2\u7ecf\u8bbe\u7f6e\u4e86\u63d0\u9192\u5728 <strong>10\u5206\u949f\u548c45\u5206\u949f<\/strong> \u8282\u70b9\uff08\u7c7b\u578b\u4e3a <code>0<\/code>\uff0c\u5373 App \u63d0\u9192\uff09\u3002<\/li>\n\n\n\n<li>2.\u7528\u6237\u8fd9\u6b21\u5e0c\u671b\u8bbe\u7f6e\u65b0\u7684\u63d0\u9192\u5728 <strong>15\u5206\u949f\u548c50\u5206\u949f<\/strong> \u8282\u70b9\uff08\u7c7b\u578b\u4e3a <code>0<\/code>\uff0c\u5373\u540c\u6837\u662f App \u63d0\u9192\uff09\u3002<\/li>\n<\/ol>\n\n\n\n<p><code>information<\/code> \u7684\u4e8c\u8fdb\u5236\u8868\u793a\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>10\u5206\u949f\u8282\u70b9\u5bf9\u5e94\u7684\u7b2c2\u4f4d\u8bbe\u4e3a <code>1<\/code>\uff0c45\u5206\u949f\u8282\u70b9\u5bf9\u5e94\u7684\u7b2c9\u4f4d\u8bbe\u4e3a <code>1<\/code>\u3002<\/li>\n\n\n\n<li>\u6240\u4ee5 <code>information<\/code> \u7684\u4e8c\u8fdb\u5236\u8868\u793a\u5982\u4e0b\u6240\u793a\uff0c\u5176\u4e2d\u7b2c2\u4f4d\u548c\u7b2c9\u4f4d\u4e3a <code>1<\/code>\uff0c\u5176\u4ed6\u4f4d\u4e3a <code>0<\/code>\u3002<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0010<\/code><\/pre>\n\n\n\n<p><code>bitMap<\/code> \u662f\u7528\u6237\u5e0c\u671b\u65b0\u589e\u7684\u63d0\u9192\u4fe1\u606f\uff0c\u8868\u793a <strong>15\u5206\u949f\u548c50\u5206\u949f<\/strong> \u8282\u70b9\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>15\u5206\u949f\u5bf9\u5e94\u7684\u7b2c3\u4f4d\uff0c50\u5206\u949f\u5bf9\u5e94\u7684\u7b2c10\u4f4d\u3002<\/li>\n\n\n\n<li><code>bitMap<\/code> \u7684\u4e8c\u8fdb\u5236\u8868\u793a\u5982\u4e0b\u6240\u793a\uff0c\u5176\u4e2d\u7b2c3\u4f4d\u548c\u7b2c10\u4f4d\u4e3a <code>1<\/code>\uff0c\u5176\u4ed6\u4f4d\u4e3a <code>0<\/code>\u3002<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0100<\/code><\/pre>\n\n\n\n<p>\u73b0\u5728\u4f7f\u7528 <code>^<\/code>\uff08\u5f02\u6216\uff09\u64cd\u4f5c\u6765\u5408\u5e76\u4e24\u4e2a\u63d0\u9192\u4fe1\u606f\u3002\u5bf9 <code>information<\/code> \u548c <code>bitMap<\/code> \u9010\u4f4d\u8fdb\u884c\u5f02\u6216\u8fd0\u7b97\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u76f8\u540c\u7684\u4f4d\uff1a\u7ed3\u679c\u4e3a <code>0<\/code>\u3002<\/li>\n\n\n\n<li>\u4e0d\u540c\u7684\u4f4d\uff1a\u7ed3\u679c\u4e3a <code>1<\/code>\u3002<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>information: &nbsp; 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0010\nbitMap: &nbsp; &nbsp; &nbsp; &nbsp;0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0100\n------------------------------------------------------------------------------------------------\nresult: &nbsp; &nbsp; &nbsp; &nbsp;0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000 0110<\/code><\/pre>\n\n\n\n<p>\u7ed3\u679c\u89e3\u91ca\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u7b2c2\u4f4d<\/strong> \u548c <strong>\u7b2c9\u4f4d<\/strong> \u662f <code>information<\/code> \u4e2d\u539f\u672c\u5df2\u7ecf\u8bbe\u7f6e\u7684\u63d0\u9192\u8282\u70b9\uff0c<code>bitMap<\/code> \u5bf9\u5e94\u4f4d\u7f6e\u662f <code>0<\/code>\uff0c\u6240\u4ee5\u8fd9\u4e9b\u4f4d\u4fdd\u6301\u4e3a <code>1<\/code>\u3002<\/li>\n\n\n\n<li><strong>\u7b2c3\u4f4d<\/strong> \u548c <strong>\u7b2c10\u4f4d<\/strong> \u662f <code>bitMap<\/code> \u65b0\u589e\u7684\u63d0\u9192\u8282\u70b9\uff0c<code>information<\/code> \u5bf9\u5e94\u4f4d\u7f6e\u662f <code>0<\/code>\uff0c\u5f02\u6216\u8fd0\u7b97\u540e\u8fd9\u4e9b\u4f4d\u53d8\u4e3a <code>1<\/code>\uff0c\u8868\u793a\u65b0\u589e\u4e86\u63d0\u9192\u3002<\/li>\n\n\n\n<li>\u5176\u4ed6\u4f4d\u4fdd\u6301\u4e0d\u53d8\uff0c\u4ecd\u7136\u4e3a <code>0<\/code>\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u6700\u7ec8\u7684\u5408\u5e76\u7ed3\u679c\uff08<code>information ^ bitMap<\/code>\uff09\u662f\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000 0110<\/code><\/pre>\n\n\n\n<p>\u8fd9\u8868\u793a\u7528\u6237\u5df2\u7ecf\u8bbe\u7f6e\u4e86\u5728 <strong>10\u5206\u949f\u300115\u5206\u949f\u300145\u5206\u949f<\/strong> \u548c <strong>50\u5206\u949f<\/strong> \u7684\u63d0\u9192\u8282\u70b9\u3002<\/p>\n\n\n\n<p><code>^<\/code> \u8fd0\u7b97\u7684\u4f5c\u7528\u662f\u5408\u5e76\u7528\u6237\u5df2\u8bbe\u7f6e\u7684\u63d0\u9192\u548c\u65b0\u8bbe\u7f6e\u7684\u63d0\u9192\uff0c\u4e0d\u4f1a\u8986\u76d6\u539f\u6709\u63d0\u9192\u8282\u70b9\uff0c\u800c\u662f\u9010\u4f4d\u6bd4\u8f83\u540e\uff0c\u5c06\u4e0d\u540c\u7684\u4f4d\u7f6e\u7f6e\u4e3a <code>1<\/code>\uff0c\u76f8\u540c\u7684\u4f4d\u7f6e\u4fdd\u6301\u4e0d\u53d8\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4\">4. \u53d1\u9001\u9884\u7ea6\u62a2\u8d2d\u4f18\u60e0\u5238\u5ef6\u65f6\u6d88\u606f<\/h3>\n\n\n\n<p>\u5f53\u6211\u4eec\u628a\u9884\u7ea6\u62a2\u8d2d\u4fe1\u606f\u4fdd\u5b58\u5230\u6570\u636e\u5e93\u4e4b\u540e\uff0c\u5c31\u8981\u8003\u8651\u600e\u4e48\u8ba9\u7528\u6237\u5728\u5f00\u62a2\u4e4b\u524d\u63a5\u6536\u901a\u77e5\uff0c\u6211\u4eec\u4f7f\u7528\u6d88\u606f\u961f\u5217 RocketMQ \u5ef6\u65f6\u6d88\u606f\u5b8c\u6210\u8be5\u9700\u6c42\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"4-1-mq\">4.1 \u4e3a\u4ec0\u4e48\u91c7\u7528 MQ \u5ef6\u65f6\u6d88\u606f<\/h4>\n\n\n\n<p>\u4f18\u96c5\u6700\u7ec8\u8bbe\u8ba1\u8fd9\u4e2a\u65b9\u6848\u4e4b\u524d\uff0c\u6a2a\u5411\u5bf9\u6bd4\u4e86\u5176\u4ed6\u6280\u672f\u65b9\u6848\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Redis \u5ef6\u65f6\u961f\u5217 \/ Redis \u5b58\u50a8\u4fe1\u606f<\/strong>\uff1aRedis \u4ee5\u5185\u5b58\u4e3a\u4e3b\u8fdb\u884c\u6570\u636e\u5b58\u50a8\uff0c\u5f53\u9762\u5bf9\u767e\u4e07\u7ea7\u6d88\u606f\u65f6\uff0c\u5373\u4f7f\u4f7f\u7528 BitMap \u8fdb\u884c\u538b\u7f29\uff0c\u4e5f\u5f88\u96be\u6709\u6548\u5b58\u50a8\uff0c\u5c24\u5176\u662f\u8fd9\u4e9b\u6d88\u606f\u53ef\u80fd\u9700\u8981\u51e0\u5929\u540e\u624d\u88ab\u6d88\u8d39\u3002\u8fd9\u4f1a\u5bfc\u81f4\u5185\u5b58\u5360\u7528\u5de8\u5927\u3002\u800c RocketMQ \u5219\u901a\u8fc7\u786c\u76d8\u5b58\u50a8\u6570\u636e\uff0c\u80fd\u591f\u8f7b\u677e\u5904\u7406\u548c\u5b58\u50a8\u5927\u91cf\u6d88\u606f\u3002<\/li>\n\n\n\n<li><strong>MySQL \u5b58\u50a8\u6d88\u606f<\/strong>\uff1a\u5c06\u6d88\u606f\u5b58\u50a8\u5728 MySQL \u4e2d\uff0c\u5e76\u901a\u8fc7\u5b9a\u65f6\u4efb\u52a1\u5728\u6307\u5b9a\u65f6\u95f4\u63d0\u53d6\u6d88\u606f\u8fdb\u884c\u6d88\u8d39\u3002MySQL \u7684 QPS \u5927\u7ea6\u4e3a 5000 \u591a\uff0c\u6d88\u8d39\u767e\u4e07\u6761\u6d88\u606f\u5927\u91cf\u8bfb\u53d6\u7684 IO \u5bb9\u6613\u6210\u4e3a\u7cfb\u7edf\u74f6\u9888\u3002\u6b64\u5916\uff0c\u968f\u7740\u6570\u636e\u91cf\u7684\u589e\u52a0\uff0cMySQL \u7684\u8fed\u4ee3\u901f\u5ea6\u975e\u5e38\u5feb\uff0c\u5f15\u5165\u5b9a\u65f6\u4efb\u52a1\u5220\u9664\u4e5f\u589e\u52a0\u4e86\u7cfb\u7edf\u7684\u590d\u6742\u6027\u3002<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>MySQL QPS \u67e5\u8be2\u666e\u904d\u6307\u7684\u662f\u4e91 MySQL\uff0c8C16G\uff0c\u81ea\u5efa\u548c\u914d\u7f6e\u8f83\u4f4e\u7684\u53ef\u80fd\u65e0\u6cd5\u8fbe\u5230\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u7efc\u4e0a\u6240\u8ff0\uff0c\u4f7f\u7528 RocketMQ \u662f\u66f4\u4f18\u7684\u9009\u62e9\uff0c\u7279\u522b\u662f\u5728\u5904\u7406\u5927\u91cf\u6d88\u606f\u7684\u573a\u666f\u4e0b\u3002\u5b83\u5177\u5907\u9ad8\u6548\u7684\u786c\u76d8\u5b58\u50a8\u548c\u8f83\u9ad8\u7684\u6d88\u606f\u541e\u5410\u91cf\u3002\u7136\u800c\uff0cRocketMQ \u4e5f\u5b58\u5728\u4e00\u5b9a\u7684\u7f3a\u70b9\uff0c\u4f8b\u5982\uff0cRocketMQ 5.x \u7248\u672c\u5c1a\u672a\u5e7f\u6cdb\u666e\u53ca\uff0c\u7a33\u5b9a\u6027\u548c\u517c\u5bb9\u6027\u96be\u4ee5\u5b8c\u5168\u4fdd\u969c\uff0c\u4e14\u9700\u8981\u6211\u4eec\u5bf9\u6d88\u606f\u6d88\u8d39\u8fc7\u7a0b\u8fdb\u884c\u989d\u5916\u5904\u7406\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"4-2\">4.2 \u53d1\u9001\u9884\u7ea6\u62a2\u8d2d\u4f18\u60e0\u5238\u6d88\u606f<\/h4>\n\n\n\n<p>\u6211\u4eec\u5728\u4e1a\u52a1\u4ee3\u7801\u91cc\u53d1\u9001 RocketMQ \u5ef6\u65f6\u6d88\u606f\uff0c\u5ef6\u8fdf\u65f6\u95f4\u901a\u8fc7\u6211\u4eec\u7684\u4f18\u60e0\u5238\u5f00\u59cb\u65f6\u95f4\u51cf\u53bb\u8bbe\u7f6e\u7684\u63d0\u9192\u65f6\u95f4\u5373\u53ef\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Override@TransactionalpublicvoidcreateCouponRemind(CouponTemplateRemindCreateReqDTO requestParam){\/\/ ......\/\/ \u53d1\u9001\u9884\u7ea6\u63d0\u9192\u62a2\u8d2d\u4f18\u60e0\u5238\u5ef6\u65f6\u6d88\u606fCouponRemindDelayEvent couponRemindDelayEvent =CouponRemindDelayEvent.builder().couponTemplateId(couponTemplate.getId()).userId(UserContext.getUserId()).contact(UserContext.getUserId()).shopNumber(couponTemplate.getShopNumber()).type(requestParam.getType()).remindTime(requestParam.getRemindTime()).startTime(couponTemplate.getValidStartTime()).delayTime(DateUtil.offsetMinute(couponTemplate.getValidStartTime(),-requestParam.getRemindTime()).getTime()).build();\n &nbsp; &nbsp;couponRemindDelayProducer.sendMessage(couponRemindDelayEvent);}<\/code><\/pre>\n\n\n\n<p>\u540e\u7eed\u7684\u67e5\u770b\u7528\u6237\u9884\u7ea6\u62a2\u8d2d\u63d0\u9192\u5217\u8868\u3001\u53d6\u6d88\u7528\u6237\u62a2\u8d2d\u63d0\u9192\u4ee5\u53ca\u53d1\u9001\u63d0\u9192\u901a\u77e5\u5c06\u5728\u540e\u7eed\u7ae0\u8282\u7ed9\u5927\u5bb6\u63ed\u6653\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u5728\u6bd4\u5bf9\u4e86\u591a\u79cd\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u7684\u6280\u672f\u67b6\u6784\u65b9\u6848\u540e\uff0c\u6700\u7ec8\u9009\u62e9\u4e86 RocketMQ 5.x \u7684\u4efb\u610f\u5ef6\u65f6\u6d88\u606f\u673a\u5236\u6765\u5b9e\u73b0\u9884\u7ea6\u63d0\u9192\u3002\u901a\u8fc7\u7ebf\u7a0b\u6c60\u5e76\u884c\u901a\u77e5\u7528\u6237\u7684\u65b9\u5f0f\uff0c\u63d0\u5347\u4e86\u63d0\u9192\u7684\u6548\u7387\u3002\u5728\u6b64\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528\u4e86\u4f4d\u56fe\u6280\u672f\uff0c\u5c06\u591a\u4e2a\u65f6\u95f4\u6bb5\u7684\u63d0\u9192\u4fe1\u606f\u9ad8\u6548\u5730\u5b58\u50a8\u5728\u4e00\u4e2a\u5b57\u6bb5\u4e2d\uff0c\u4ece\u800c\u5b9e\u73b0\u4e86\u5bf9\u6d77\u91cf\u63d0\u9192\u7684\u7cbe\u51c6\u7ba1\u7406\u548c\u9ad8\u6548\u5904\u7406\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u901a\u8fc7RocketMQ\u9884\u7ea6\u62a2\u8d2d\u4f18\u60e0\u5238\u6d88\u606f\uff0c\u63d0\u9192\u65f6\u95f4\u53ea\u80fd\u662f\u4e00\u4e2a\uff0c\u6bd4\u5982\u63d0\u524d5\u5206\u949f\u63d0\u9192\uff0c\u5047\u5982\u6211\u9700\u8981\u57285\u5206\u949f\u300110\u5206\u949f\u90fd\u63d0\u9192\u5462\uff1f\u5982\u679c\u8fd9\u4e2a\u4e0d\u80fd\u7531RocketMQ\u5b9e\u73b0\u7684\u8bdd\uff0c\u90a3\u4e48\u524d\u9762\u901a\u8fc7\u5f02\u6216\u5408\u5e76\u4e24\u4e2a\u63d0\u9192\u65f6\u95f4\u8282\u70b9\u662f\u4e0d\u662f\u6ca1\u7528\u4e86\uff1f<\/p>\n\n\n\n<p>\u6bcf\u6b21\u7684requestParam\u4e2d\u53ea\u6709\u4e00\u4e2a\u63d0\u9192\u65f6\u95f4\uff0ccreateCouponRemind\u65b9\u6cd5\u5bf9\u4e8e\u76f8\u540c\u7684\uff08<code>user_id<\/code>,<code>coupon_template_id<\/code>\uff09\u6dfb\u52a0\u591a\u4e2a\u63d0\u9192\u65f6\u95f4\u5e94\u8be5\u8981\u6267\u884c\u591a\u6b21\uff0c\u6bcf\u6b21\u90fd\u4f1a\u5411\u6d88\u606f\u961f\u5217\u53d1\u9001\u6d88\u606f\uff1b\u5f02\u6216\u5408\u5e76\u662f\u4e3a\u4e86\u5c06mysql\u4e2d\u591a\u4e2a\u63d0\u9192\u65f6\u95f4\u5408\u5e76\u6210\u4e00\u6761\u3002<\/p>\n\n\n\n<p>\u6bcf\u6b21\u8bf7\u6c42\u90fd\u662f\u8bbe\u7f6e\u4e00\u4e2a\u63d0\u9192\u7684\u65f6\u95f4\uff0c\u7136\u540e\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\uff0c\u4e0b\u6b21\u8bf7\u6c42\u518d\u6765\u8bbe\u7f6e\u7684\u8bdd\u5c31\u8981\u5224\u65ad\u4e4b\u524d\u662f\u5426\u8bbe\u7f6e\u8fc7\u8fd9\u4e2a\u65f6\u95f4\uff0c\u5982\u679c\u6ca1\u6709\u8bbe\u7f6e\u8fc7\u90a3\u5c31\u518d\u53d1\u9001\u5ef6\u8fdf\u6d88\u606f\uff0c\u6bcf\u4e2a\u63d0\u9192\u65f6\u95f4\u5bf9\u5e94\u4e00\u6761\u6d88\u606f\uff0c\u5f02\u6216\u7684\u64cd\u4f5c\u867d\u7136\u662f\u4e3a\u4e86\u8bbe\u7f6e\u6700\u7ec8\u7684\u63d0\u9192\u65f6\u95f4\uff0c\u4f46\u4e4b\u540e\u4e5f\u65b9\u4fbf\u901a\u8fc7\u5f02\u6216\u540e\u7684\u7ed3\u679c\u5224\u65ad\u65b0\u7684\u8bf7\u6c42\u8bbe\u7f6e\u7684\u63d0\u9192\u65f6\u95f4\u662f\u5426\u4e4b\u524d\u8bbe\u7f6e\u8fc7\u3002<\/p>\n\n\n\n<p>Long bitMap = CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType()); \u5c06\u7ed3\u679c\u5f02\u6216\uff1f\u4f4d\u56fe\u4e2d\u51fa\u73b0\u7684\u6bcf\u4e2a1\u8868\u793a\u4e00\u6b21\u63d0\u9192\uff0c\u53ef\u4ee5\u901a\u8fc7\u5faa\u73af\u64cd\u4f5c\u53d1\u9001\u6d88\u606f<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\u5341\u516b\u662f\u4e2a\u6728\uff1a\u5173\u4e8e\u8fd9\u4e2a\u5c06\u63d0\u9192\u65f6\u95f4\u548c\u63d0\u9192\u7c7b\u578b\u7ed1\u5b9a\u5230\u4e00\u8d77\u7684\u65b9\u6848\uff0c\u88ab\u95ee\u5230\u8fd9\u4e2a\u65b9\u6848\u6269\u5c55\u6027\u4e0d\u597d\uff0c\u5982\u679c\u540e\u671f\u60f3\u589e\u52a0\u63d0\u9192\u65b9\u5f0f\uff0c\u4ee512bit\u4e3a\u4e00\u4e2a\u7c7b\u578b\u7684\u8bdd\uff0c\u4f4d\u6570\u662f\u6709\u9650\u7684\uff0c\u65e0\u6cd5\u6269\u5c55\uff0c\u540c\u65f6\u8fd8\u8bf4\u5230\u8fd9\u6837\u505a\u589e\u52a0\u590d\u6742\u6027\uff0c\u53ef\u8bfb\u6027\u964d\u4f4e\uff0c\u6211\u8bf4\u8fd9\u6837\u505a\u4e0d\u4ec5\u4ece\u6027\u80fd\u4e0a\u6709\u63d0\u5347\uff0c\u800c\u4e14\u8fd9\u79cd\u65b9\u6848\u53ef\u4ee5\u5c06\u4e0d\u540c\u63d0\u9192\u65f6\u95f4\u6240\u5bf9\u5e94\u4e0d\u540c\u63d0\u9192\u65b9\u5f0f\u90fd\u5b58\u5230\u4e00\u6761\u8bb0\u5f55\u91cc\uff0c\u6bd4\u5982\u53ef\u80fd\u524d5\u5206\u652f\u77ed\u4fe1\u63d0\u9192\uff0c\u524d10\u5206\u949f\u5f39\u7a97\u63d0\u9192\uff0c\u53ef\u4ee5\u53ea\u7528\u4e00\u6761\u8bb0\u5f55\u5b58\u50a8\uff0c\u7136\u540e\u53c8\u88ab\u95ee\uff0c\u90a3\u4f60\u8fd9\u6837\u53c8\u9650\u5236\u4e86\u63d0\u9192\u65f6\u95f4\u8981\u4ee55\u5206\u949f\u4e3a\u4e00\u4e2a\u5355\u4f4d\uff0c\u8bf4\u5047\u5982\u73b0\u57283\u70b938\u5206\uff0c\u7528\u6237\u5c31\u60f3\u51d1\u4e2a\u6574\uff0c4\u70b9\u63d0\u9192\u600e\u4e48\u529e\uff0c\u800c\u4e14\u8fd9\u79cd\u8bb0\u5f55\u5728\u65f6\u95f4\u8fc7\u5b8c\u4e4b\u540e\u5c31\u6ca1\u6709\u4ec0\u4e48\u4f5c\u7528\u4e86\uff0c\u53ef\u4ee5\u5b9a\u671f\u5220\u9664\uff0c\u6240\u4ee5\u5bf9\u6570\u636e\u5e93\u5185\u5b58\u7684\u5360\u7528\u4e5f\u4e0d\u4f1a\u5f88\u591a\u3002\u603b\u4e4b\uff0c\u9762\u8bd5\u5b98\u66f4\u503e\u5411\u4e8e\u52a0\u4e00\u4e2a\u63d0\u9192\u65b9\u5f0f\u7684\u5b57\u6bb5\uff0c\u7136\u540e\u5b9a\u671f\u5220\u9664\u8fc7\u671f\u6570\u636e\u7684\u65b9\u6848\u3002\u8be5\u5982\u4f55\u53d6\u820d\u5462\uff1f\u8fd8\u60f3\u8bf7\u6559\u5927\u4f6c\u4eec\u4e00\u4e0b\u5728\u5b9e\u9645\u5f00\u53d1\u4e2d\uff0c\u8fd9\u4e2a\u9700\u6c42\uff0c\u7528\u4f4d\u8fd0\u7b97\u5c06\u8fd9\u4e24\u4e2a\u5b57\u6bb5\u62fc\u5230\u4e00\u8d77\u7528\u7684\u591a\uff0c\u4e00\u822c\u7528\u7684\u662f\u4ec0\u4e48\u65b9\u6848<\/p>\n\n\n\n<p>\u753b\u4e2d\u753b\u7740\u753b\u4e0d\u51fa\u7684\u753b&nbsp;\u56de\u590d&nbsp;\u5341\u516b\u662f\u4e2a\u6728\uff1a\u5176\u5b9e\u6211\u4e5f\u89c9\u5f97\u6709\u4e9b\u534e\u800c\u4e0d\u5b9e\uff0c\u5305\u62ec\u524d\u9762Excel\u89e3\u6790\u884c\u6570\u7528\u7ebf\u7a0b\u6c60+redission\u505a\u5f02\u6b65\uff0c\u6b63\u5e38MQ\u4e5f\u884c\uff0c\u53ef\u80fd\u9a6c\u54e5\u60f3\u6559\u6211\u4eec\u591a\u79cd\u601d\u8def\u5427\u3002\u9762\u8bd5\u5b98\u8981\u95ee\u5230\uff0c\u5c31\u8bf4\u4e24\u79cd\u65b9\u6848\u81ea\u5df1\u90fd\u77e5\u9053\uff0c\u60f3\u8bd5\u4e0b\u8fd9\u79cd\u65b0\u7684\u5427<\/p>\n\n\n\n<p>\u5341\u516b\u662f\u4e2a\u6728&nbsp;\u56de\u590d&nbsp;\u753b\u4e2d\u753b\u7740\u753b\u4e0d\u51fa\u7684\u753b\uff1a\u5bf9\u7684\uff0c\u5176\u5b9e\u8bf4\u5230\u540e\u9762\u6211\u81ea\u5df1\u4e5f\u503e\u5411\u4e0e\u540e\u9762\u8fd9\u79cd\u65b9\u6848\u4e86\uff0c\u800c\u4e14\u5b8c\u5168\u53ef\u4ee5\u6709\u4e3b\u952eID\uff0c\u7528\u6237\u9884\u7ea6\u65f6\u76f4\u63a5\u63d2\u5165\u63d0\u9192\u65f6\u95f4\uff0c\u63d0\u9192\u65b9\u5f0f\uff0c\u800c\u4e14\u5728\u540e\u9762\u7684\u53d6\u6d88\u9884\u7ea6\u4e2d\uff0c\u5728\u5b9e\u9645\u573a\u666f\u4e2d\uff0c\u53d6\u6d88\u4e00\u822c\u90fd\u4f1a\u5148\u67e5\u8be2\uff0c\u5931\u6548\u7684\u9884\u7ea6\u524d\u7aef\u76f4\u63a5\u9650\u5236\u4e86\u4e0d\u53ef\u53d6\u6d88\uff0c\u67e5\u8be2\u5b8c\u6210\u540e\u5b8c\u5168\u53ef\u4ee5\u6839\u636eid\u53bb\u4fee\u6539\u9884\u7ea6\u6570\u636e\uff0c\u5c31\u4e0d\u7528\u8fdb\u884c\u540e\u9762\u4e00\u5806\u4f4d\u8fd0\u7b97\u4e86<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c26\u5c0f\u8282\uff1a\u5f00\u53d1\u4f18\u60e0\u5238\u9884\u7ea6\u901a\u77e5\u529f\u80fd\uff08\u4e8c\uff09<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5728\u4e0a\u4e00\u4e2a\u7ae0\u8282\u4e2d\uff0c\u6211\u4eec\u8ba8\u8bba\u4e86\u4f18\u60e0\u5238\u9884\u7ea6\u7684\u8bbe\u8ba1\uff0c\u91cd\u70b9\u4ecb\u7ecd\u4e86\u5982\u4f55\u5c06\u9884\u7ea6\u63d0\u9192\u53d1\u9001\u5230 RocketMQ \u5ef6\u65f6\u961f\u5217\u4e2d\u3002\u5728\u672c\u7ae0\u8282\uff0c\u6211\u4eec\u5c06\u8be6\u7ec6\u8bf4\u660e\u5982\u4f55\u5c06\u6d88\u606f\u63a8\u9001\u7ed9\u7528\u6237\uff0c\u786e\u4fdd\u4ed6\u4eec\u80fd\u591f\u53ca\u65f6\u63a5\u6536\u5230\u9884\u7ea6\u63d0\u9192\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u5728 v1 \u5206\u652f\u7684\u57fa\u7840\u4e0a\uff0c\u5bf9\u4f18\u60e0\u5238\u6a21\u677f\u63d0\u9192\u76f8\u5173\u7684\u7c7b\u8fdb\u884c\u4e86\u540d\u79f0\u91cd\u6784\uff0c\u5927\u5bb6\u67e5\u770b\u5f53\u524d\u5206\u652f\u63d0\u4ea4\u8bb0\u5f55\u5373\u53ef\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240919_dev_coupon-remind-v2_rocketmq-bitmap_youya<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u672c\u7ae0\u8282\u9884\u7ea6\u63d0\u9192\u4f18\u60e0\u5238\u6838\u5fc3\u4ee3\u7801\u7531\u4f18\u96c5\u540c\u5b66\u8d21\u732e\uff0c\u611f\u8c22\u4f18\u96c5\u63d0\u4f9b\u7684\u4f18\u79c0\u4ee3\u7801\u8bbe\u8ba1\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">\u63a8\u9001\u7528\u6237\u9884\u7ea6\u63d0\u9192<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u9884\u7ea6\u6d88\u606f\u6d88\u8d39\u8005<\/h3>\n\n\n\n<p>\u5f00\u53d1 RocketMQ \u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\uff0c\u76f8\u5173\u7684\u7528\u6237\u63d0\u9192\u4ee3\u7801\u8fdb\u884c\u4e86\u62bd\u8c61\uff0c\u653e\u5728\u4e86\u4e00\u4e2a\u6267\u884c\u5668\u4e2d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u63d0\u9192\u62a2\u5238\u6d88\u8d39\u8005\n * &lt;p&gt;\n * \u4f5c\u8005\uff1a\u4f18\u96c5\n * \u52a0\u9879\u76ee\u7fa4\uff1a\u65e9\u52a0\u5165\u5c31\u662f\u4f18\u52bf\uff01500\u4eba\u5185\u90e8\u9879\u76ee\u7fa4\uff0c\u5206\u4eab\u7684\u77e5\u8bc6\u603b\u6709\u4f60\u9700\u8981\u7684 &lt;a href=\"https:\/\/t.zsxq.com\/cw7b9\" \/&gt;\n * \u5f00\u53d1\u65f6\u95f4\uff1a2024-07-21\n *\/@Component@RequiredArgsConstructor@RocketMQMessageListener(\n &nbsp; &nbsp; &nbsp; &nbsp;topic =\"one-coupon_engine-service_coupon-remind_topic${unique-name:}\",\n &nbsp; &nbsp; &nbsp; &nbsp;consumerGroup =\"one-coupon_engine-service_coupon-remind_cg${unique-name:}\")@Slf4j(topic =\"CouponTemplateRemindDelayConsumer\")publicclassCouponTemplateRemindDelayConsumerimplementsRocketMQListener&lt;MessageWrapper&lt;CouponTemplateRemindDelayEvent&gt;&gt;{\n\u200b\n &nbsp; &nbsp;privatefinalCouponTemplateRemindExecutor couponTemplateRemindExecutor;\n\u200b\n &nbsp; &nbsp;@OverridepublicvoidonMessage(MessageWrapper&lt;CouponTemplateRemindDelayEvent&gt; messageWrapper){\/\/ \u5f00\u5934\u6253\u5370\u65e5\u5fd7\uff0c\u5e73\u5e38\u53ef Debug \u770b\u4efb\u52a1\u53c2\u6570\uff0c\u7ebf\u4e0a\u53ef\u62a5\u5e73\u5b89\uff08\u6bd4\u5982\u6d88\u606f\u662f\u5426\u6d88\u8d39\uff0c\u91cd\u65b0\u6295\u9012\u65f6\u83b7\u53d6\u53c2\u6570\u7b49\uff09\n &nbsp; &nbsp; &nbsp; &nbsp;log.info(\"&#91;\u6d88\u8d39\u8005] \u63d0\u9192\u7528\u6237\u62a2\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u6d88\u606f\u4f53\uff1a{}\",JSON.toJSONString(messageWrapper));\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;CouponTemplateRemindDelayEvent event = messageWrapper.getMessage();CouponTemplateRemindDTO couponTemplateRemindDTO =BeanUtil.toBean(event,CouponTemplateRemindDTO.class);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6839\u636e\u4e0d\u540c\u7b56\u7565\u5411\u7528\u6237\u53d1\u9001\u6d88\u606f\u63d0\u9192\n &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindExecutor.executeRemindCouponTemplate(couponTemplateRemindDTO);}}<\/code><\/pre>\n\n\n\n<p>\u5411\u7528\u6237\u53d1\u9001\u6d88\u606f\u63d0\u9192\u7684\u903b\u8f91\u5728 <code>CouponTemplateRemindExecutor<\/code> \u6267\u884c\u5668\uff0c\u5206\u4e3a\u51e0\u4e2a\u7248\u672c\u6f14\u8fdb\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u6267\u884c\u63d0\u9192\n *\n * @param couponTemplateRemindDTO \u7528\u6237\u9884\u7ea6\u63d0\u9192\u8bf7\u6c42\u4fe1\u606f\n *\/publicvoidexecuteRemindCouponTemplate(CouponTemplateRemindDTO couponTemplateRemindDTO){\/\/ \u5411\u7528\u6237\u53d1\u8d77\u6d88\u606f\u63d0\u9192switch(Objects.requireNonNull(CouponRemindTypeEnum.getByType(couponTemplateRemindDTO.getType()))){caseAPP-&gt; sendAppMessageRemindCouponTemplate.remind(couponTemplateRemindDTO);caseEMAIL-&gt; sendEmailRemindCouponTemplate.remind(couponTemplateRemindDTO);default-&gt;{}}}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u7ebf\u7a0b\u6c60\u5e76\u884c\u53d1\u9001\u63d0\u9192<\/h3>\n\n\n\n<p>\u901a\u8fc7\u7b2c\u4e00\u7248\u4ee3\u7801\uff0c\u6211\u4eec\u53ef\u4ee5\u660e\u663e\u53d1\u73b0\u4e00\u4e2a\u95ee\u9898\uff1a\u6d88\u606f\u961f\u5217\u7684\u6d88\u8d39\u901f\u5ea6\u8f83\u6162\uff0c\u56e0\u4e3a\u662f\u9010\u6761\u5904\u7406\u6bcf\u6761\u6d88\u606f\u540e\u624d\u6d88\u8d39\u4e0b\u4e00\u6761\u3002\u800c\u6211\u4eec\u5e0c\u671b\u5c3d\u5feb\u5c06\u8fd9\u4e9b\u9884\u7ea6\u4fe1\u606f\u53d1\u9001\u7ed9\u7528\u6237\u3002\u57fa\u4e8e\u8fd9\u4e00\u524d\u63d0\uff0c\u6211\u4eec\u53ef\u4ee5\u91c7\u7528\u7ebf\u7a0b\u6c60\u8fdb\u884c\u5e76\u884c\u53d1\u9001\uff0c\u4ee5\u63d0\u9ad8\u6d88\u606f\u5904\u7406\u548c\u53d1\u9001\u7684\u6548\u7387\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u63d0\u9192\u7528\u6237\u5c5e\u4e8e IO \u5bc6\u96c6\u578b\u4efb\u52a1privatefinalExecutorService executorService =newThreadPoolExecutor(Runtime.getRuntime().availableProcessors()&lt;&lt;1,Runtime.getRuntime().availableProcessors()&lt;&lt;2,60,TimeUnit.SECONDS,newSynchronousQueue&lt;&gt;(),newThreadPoolExecutor.CallerRunsPolicy());\/**\n * \u6267\u884c\u63d0\u9192\n *\n * @param couponTemplateRemindDTO \u7528\u6237\u9884\u7ea6\u63d0\u9192\u8bf7\u6c42\u4fe1\u606f\n *\/publicvoidexecuteRemindCouponTemplate(CouponTemplateRemindDTO couponTemplateRemindDTO){\n    executorService.execute(()-&gt;{\/\/ \u5411\u7528\u6237\u53d1\u8d77\u6d88\u606f\u63d0\u9192switch(Objects.requireNonNull(CouponRemindTypeEnum.getByType(couponTemplateRemindDTO.getType()))){caseAPP-&gt; sendAppMessageRemindCouponTemplate.remind(couponTemplateRemindDTO);caseEMAIL-&gt; sendEmailRemindCouponTemplate.remind(couponTemplateRemindDTO);default-&gt;{}}});}<\/code><\/pre>\n\n\n\n<p>\u7ebf\u7a0b\u6c60\u53c2\u6570\u89e3\u6790\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6838\u5fc3\u7ebf\u7a0b\u6570\uff1a<code>Runtime.getRuntime().availableProcessors() &lt;&lt; 1<\/code> CPU \u6838\u6570 * 2\uff0c\u56e0\u4e3a\u662f IO \u5bc6\u96c6\u578b\u7ebf\u7a0b\u6570\u53ef\u4ee5\u591a\u4e9b\u3002<\/li>\n\n\n\n<li>\u6700\u5927\u7ebf\u7a0b\u6570\uff1a<code>Runtime.getRuntime().availableProcessors() &lt;&lt; 2<\/code> CPU \u6838\u6570 * 4\uff0c\u56e0\u4e3a\u662f IO \u5bc6\u96c6\u578b\u7ebf\u7a0b\u6570\u53ef\u4ee5\u591a\u4e9b\u3002<\/li>\n\n\n\n<li>\u963b\u585e\u961f\u5217\uff1aSynchronousQueue\uff0c\u4e0d\u7f13\u51b2\u4efb\u52a1\u3002<\/li>\n\n\n\n<li>\u62d2\u7edd\u7b56\u7565\uff1aCallerRunsPolicy\uff0c\u901a\u8fc7\u63d0\u4ea4\u4efb\u52a1\u7ebf\u7a0b\u8fd0\u884c\u88ab\u62d2\u7edd\u7684\u4efb\u52a1\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u6211\u4eec\u901a\u8fc7\u7ebf\u7a0b\u6c60\u6765\u52a0\u5feb\u9884\u7ea6\u4efb\u52a1\u7684\u901a\u77e5\u63d0\u9192\u5904\u7406\u3002\u5f53\u7ebf\u7a0b\u6c60\u8fbe\u5230\u5176\u5904\u7406\u80fd\u529b\u7684\u74f6\u9888\u65f6\uff0c\u91c7\u7528\u4efb\u52a1\u62d2\u7edd\u7b56\u7565\uff0c\u5c06\u88ab\u62d2\u7edd\u7684\u4efb\u52a1\u4ea4\u7531\u63d0\u4ea4\u4efb\u52a1\u7684\u7ebf\u7a0b\u81ea\u884c\u6267\u884c\uff0c\u4ee5\u786e\u4fdd\u901a\u77e5\u4efb\u52a1\u4e0d\u4f1a\u88ab\u4e22\u5f03\u5e76\u5c3d\u53ef\u80fd\u63d0\u9ad8\u7cfb\u7edf\u7684\u5904\u7406\u6548\u7387\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3-redis\">3. \u901a\u8fc7 Redis \u5ef6\u8fdf\u961f\u5217\u515c\u5e95\u4efb\u52a1<\/h3>\n\n\n\n<p>\u4e3a\u4e86\u63d0\u5347\u6d88\u606f\u6d88\u8d39\u7684\u901f\u5ea6\uff0c\u6211\u4eec\u5c06\u4efb\u52a1\u6295\u9012\u5230\u7ebf\u7a0b\u6c60\u540e\u7acb\u5373\u8fd4\u56de\u6d88\u606f\u6295\u9012\u6210\u529f\u7ed9 MQ\u3002\u7136\u800c\uff0c\u5982\u679c\u6b64\u65f6\u53d1\u751f\u4e86\u65ad\u7535\uff0c\u7ebf\u7a0b\u6c60\u4e2d\u7684\u4efb\u52a1\u5c06\u4f1a\u4e22\u5931\u3002\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u6211\u4eec\u9700\u8981\u5f15\u5165\u6807\u8bb0\u6216\u6301\u4e45\u5316\u64cd\u4f5c\uff0c\u5e76\u5728\u540e\u7eed\u901a\u8fc7\u626b\u63cf\u68c0\u6d4b\u4efb\u52a1\u72b6\u6001\uff0c\u786e\u4fdd\u4efb\u52a1\u672a\u4e22\u5931\u3002<\/p>\n\n\n\n<p>\u5f53\u6536\u5230\u6d88\u606f\u65f6\uff0c\u4f7f\u7528 Redisson \u7684\u5ef6\u65f6\u961f\u5217\uff0c\u53d1\u9001\u4e00\u6761\u5ef6\u65f6 10 \u79d2\u7684\u6d88\u606f\u300210 \u79d2\u540e\uff0c\u7cfb\u7edf\u68c0\u67e5\u4efb\u52a1\u72b6\u6001\u3002\u5982\u679c\u6d88\u8d39\u6210\u529f\uff0c\u6d41\u7a0b\u7ed3\u675f\uff1b\u5982\u679c\u6d88\u8d39\u5931\u8d25\uff0c\u5219\u91cd\u65b0\u6295\u9012\u6d88\u606f\uff0c\u4ece\u800c\u4fdd\u8bc1\u6d88\u606f\u4e0d\u4f1a\u4e22\u5931\u3002<\/p>\n\n\n\n<p>\u9700\u8981\u8003\u8651\u7684\u51e0\u4e2a\u95ee\u9898\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.<strong>\u4e3a\u4ec0\u4e48\u4f7f\u7528 Redis \u7684\u5ef6\u65f6\u961f\u5217\uff0c\u800c\u4e0d\u662f\u7ee7\u7eed\u4f7f\u7528 RocketMQ \u7684\u5ef6\u65f6\u6d88\u606f\uff1f<\/strong> Redis \u7684\u5ef6\u65f6\u961f\u5217\u9002\u7528\u4e8e 10 \u79d2\u7684\u77ed\u65f6\u4efb\u52a1\uff0c\u6570\u636e\u5728 10 \u79d2\u540e\u6295\u9012\u5b8c\u6210\u5373\u5220\u9664\u3002<\/li>\n\n\n\n<li>2.<strong>\u662f\u5426\u6709\u6a2a\u5411\u5bf9\u6bd4\u5176\u5b83\u65b9\u6848\uff1f<\/strong> \u6211\u4eec\u4e5f\u8003\u8651\u4e86 Redis \u7684\u8fc7\u671f\u76d1\u542c\u673a\u5236\u3002\u867d\u7136\u5b9e\u73b0\u7b80\u5355\uff0c\u4f46\u7531\u4e8e\u8fc7\u671f\u76d1\u542c\u7684\u65f6\u95f4\u4e0d\u591f\u7cbe\u51c6\uff0c\u4e14\u8fc7\u671f\u6d88\u606f\u53ea\u53d1\u9001\u4e00\u6b21\uff0c\u53ef\u9760\u6027\u8f83\u5dee\u3002\u5982\u679c\u6d88\u606f\u672a\u6210\u529f\u63a5\u6536\u6216\u8005\u53d1\u751f\u5f02\u5e38\uff0c\u65e0\u6cd5\u518d\u6b21\u6536\u5230\uff0c\u56e0\u6b64\u4e0d\u591f\u7a33\u59a5\u3002<\/li>\n\n\n\n<li>3.<strong>\u5982\u679c\u201c\u68c0\u6d4b\u72b6\u6001\u201d\u7684\u673a\u5668\u4e5f\u6302\u4e86\u600e\u4e48\u529e\uff1f<\/strong> \u7531\u4e8e\u6211\u4eec\u4f7f\u7528\u7684\u662f Redis \u7684\u5ef6\u65f6\u961f\u5217\uff0c\u53ea\u8981\u6709\u4e00\u53f0\u673a\u5668\u5b58\u6d3b\uff0c\u5c31\u80fd\u7ee7\u7eed\u6536\u5230\u6d88\u606f\u3002\u9664\u975e\u6240\u6709\u673a\u5668\u540c\u65f6\u5b95\u673a\uff0c\u5426\u5219\u6d88\u606f\u4ecd\u53ef\u88ab\u6d88\u8d39\u3002\u5bf9\u4e8e\u6211\u4eec\u8fd9\u4e2a\u573a\u666f\uff0c\u5076\u5c14\u4e22\u5931\u5c11\u91cf\u6d88\u606f\u4ec5\u610f\u5473\u7740\u5c11\u901a\u77e5\u51e0\u4e2a\u7528\u6237\uff0c\u53ef\u4ee5\u63a5\u53d7\uff0c\u5e76\u4e0d\u6784\u6210\u91cd\u5927\u5f71\u54cd\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u8fd9\u79cd\u65b9\u6848\u786e\u4fdd\u4e86\u5728\u4fdd\u8bc1\u6d88\u606f\u6d88\u8d39\u901f\u5ea6\u7684\u540c\u65f6\uff0c\u964d\u4f4e\u4e86\u6d88\u606f\u4e22\u5931\u7684\u98ce\u9669\u3002\u6240\u4ee5\uff0c\u6211\u4eec\u8981\u53c2\u8003\u4e4b\u524d\u4f18\u60e0\u5238\u5206\u53d1\u4efb\u52a1\u7684 Redis Stream \u5ef6\u8fdf\u4efb\u52a1\u8fdb\u884c\u515c\u5e95\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u6267\u884c\u63d0\u9192\n *\n * @param couponTemplateRemindDTO \u7528\u6237\u9884\u7ea6\u63d0\u9192\u8bf7\u6c42\u4fe1\u606f\n *\/publicvoidexecuteRemindCouponTemplate(CouponTemplateRemindDTO couponTemplateRemindDTO){\/\/ \u5047\u8bbe\u521a\u628a\u6d88\u606f\u63d0\u4ea4\u5230\u7ebf\u7a0b\u6c60\uff0c\u7a81\u7136\u5e94\u7528\u5b95\u673a\u4e86\uff0c\u6211\u4eec\u901a\u8fc7\u5ef6\u8fdf\u961f\u5217\u8fdb\u884c\u515c\u5e95 RefreshRBlockingDeque&lt;String&gt; blockingDeque = redissonClient.getBlockingDeque(REDIS_BLOCKING_DEQUE);RDelayedQueue&lt;String&gt; delayedQueue = redissonClient.getDelayedQueue(blockingDeque);String key =String.format(COUPON_REMIND_CHECK_KEY, couponTemplateRemindDTO.getUserId(), couponTemplateRemindDTO.getCouponTemplateId(), couponTemplateRemindDTO.getRemindTime(), couponTemplateRemindDTO.getType());\n &nbsp; &nbsp;stringRedisTemplate.opsForValue().set(key,JSON.toJSONString(couponTemplateRemindDTO));\n &nbsp; &nbsp;delayedQueue.offer(key,10,TimeUnit.SECONDS);\n\u200b\n &nbsp; &nbsp;executorService.execute(()-&gt;{\/\/ \u5411\u7528\u6237\u53d1\u8d77\u6d88\u606f\u63d0\u9192switch(Objects.requireNonNull(CouponRemindTypeEnum.getByType(couponTemplateRemindDTO.getType()))){caseAPP-&gt; sendAppMessageRemindCouponTemplate.remind(couponTemplateRemindDTO);caseEMAIL-&gt; sendEmailRemindCouponTemplate.remind(couponTemplateRemindDTO);default-&gt;{}}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u63d0\u9192\u7528\u6237\u540e\u5220\u9664 Key\n &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.delete(key);});}<\/code><\/pre>\n\n\n\n<p>\u6211\u4eec\u5c06\u4efb\u52a1\u6682\u5b58\u5230 Redis String\uff0c\u5e76\u901a\u8fc7\u5ef6\u8fdf\u961f\u5217\u8fdb\u884c\u515c\u5e95\u5904\u7406\u3002\u9996\u5148\u68c0\u67e5 Redis String \u662f\u5426\u5b58\u5728\uff0c\u5982\u679c\u4e0d\u5b58\u5728\uff0c\u8868\u793a\u4efb\u52a1\u5df2\u6210\u529f\u6d88\u8d39\uff1b\u5982\u679c\u5b58\u5728\uff0c\u5219\u9700\u8981\u91cd\u65b0\u6295\u9012\u6d88\u606f\uff0c\u786e\u4fdd\u4efb\u52a1\u88ab\u6b63\u786e\u5904\u7406\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u4e3a\u4e86\u7b80\u5316\u4ee3\u7801\u7ed3\u6784\uff0c\u907f\u514d\u521b\u5efa\u8fc7\u591a\u7684\u7c7b\uff0c\u6211\u4eec\u91c7\u7528\u5185\u90e8\u7c7b\u7684\u65b9\u5f0f\u6765\u5b8c\u6210\u8fd9\u90e8\u5206\u903b\u8f91\u7684\u5b9e\u73b0\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Slf4j@Component@RequiredArgsConstructorstaticclassRefreshCouponRemindDelayQueueRunnerimplementsCommandLineRunner{privatefinalCouponTemplateRemindDelayProducer couponRemindProducer;privatefinalRedissonClient redissonClient;privatefinalStringRedisTemplate stringRedisTemplate;@Overridepublicvoidrun(String... args){Executors.newSingleThreadExecutor(\n                        runnable -&gt;{Thread thread =newThread(runnable);\n                            thread.setName(\"delay_coupon-remind_consumer\");\n                            thread.setDaemon(Boolean.TRUE);return thread;}).execute(()-&gt;{RBlockingDeque&lt;String&gt; blockingDeque = redissonClient.getBlockingDeque(REDIS_BLOCKING_DEQUE);for(;;){try{\/\/ \u83b7\u53d6\u5ef6\u8fdf\u961f\u5217\u5f85\u6d88\u8d39 KeyString key = blockingDeque.take();if(stringRedisTemplate.hasKey(key)){\n                                log.info(\"\u68c0\u67e5\u7528\u6237\u53d1\u9001\u7684\u901a\u77e5\u6d88\u606fKey\uff1a{} \u672a\u6d88\u8d39\u5b8c\u6210\uff0c\u5f00\u542f\u91cd\u65b0\u6295\u9012\", key);\/\/ Redis \u4e2d\u8fd8\u5b58\u5728\u8be5 Key\uff0c\u8bf4\u660e\u4efb\u52a1\u6ca1\u88ab\u6d88\u8d39\u5b8c\uff0c\u5219\u53ef\u80fd\u662f\u6d88\u8d39\u673a\u5668\u5b95\u673a\u4e86\uff0c\u91cd\u65b0\u6295\u9012\u6d88\u606fCouponTemplateRemindDelayEvent couponTemplateRemindDelayEvent =JSONUtil.toBean(stringRedisTemplate.opsForValue().get(key),CouponTemplateRemindDelayEvent.class);\n                                couponRemindProducer.sendMessage(couponTemplateRemindDelayEvent);\/\/ \u63d0\u9192\u7528\u6237\u540e\u5220\u9664 Key\n                                stringRedisTemplate.delete(key);}}catch(Throwable ignored){}}});}}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5e38\u89c1\u95ee\u9898\u7b54\u7591<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u6d88\u606f\u6d88\u8d39\u662f\u5426\u9700\u8981\u505a\u5e42\u7b49\uff1f<\/h3>\n\n\n\n<p>\u5728\u6211\u4eec\u8fd9\u4e2a\u573a\u666f\u4e2d\uff0c\u6ca1\u5fc5\u8981\u5f15\u5165\u6d88\u606f\u6d88\u8d39\u5e42\u7b49\u673a\u5236\uff0c\u539f\u56e0\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.<strong>\u6d88\u606f\u6d88\u8d39\u901f\u5ea6\u975e\u5e38\u5feb<\/strong>\uff1a\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u662f\u6536\u5230\u6d88\u606f\u540e\uff0c\u901a\u8fc7 Redis \u53d1\u9001\u5ef6\u65f6\u961f\u5217\uff0c\u4efb\u52a1\u7acb\u5373\u4e22\u8fdb\u7ebf\u7a0b\u6c60\u6267\u884c\uff0c\u968f\u540e\u8fd4\u56de\u7ed3\u679c\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u51fa\u95ee\u9898\u7684\u6982\u7387\u6781\u4f4e\uff0c\u7edd\u5927\u591a\u6570\u6d88\u606f\u80fd\u591f\u6b63\u5e38\u6d88\u8d39\u3002<\/li>\n\n\n\n<li>2.<strong>\u5373\u4f7f\u53d1\u751f\u6d88\u606f\u91cd\u590d\u6295\u9012\uff0c\u5f71\u54cd\u4e5f\u5f88\u5c0f<\/strong>\uff1a\u5bf9\u4e8e\u5c11\u6570\u672a\u80fd\u6b63\u5e38\u6d88\u8d39\u7684\u6d88\u606f\uff0c\u53ef\u80fd\u4f1a\u4ea7\u751f\u91cd\u590d\u6d88\u8d39\u7684\u60c5\u51b5\u3002\u4f46\u5728\u6211\u4eec\u8fd9\u4e2a\u573a\u666f\u4e2d\uff0c\u91cd\u590d\u6d88\u8d39\u7684\u5f71\u54cd\u4ec5\u9650\u4e8e\u91cd\u590d\u901a\u77e5\u7528\u6237\uff0c\u5b8c\u5168\u53ef\u4ee5\u63a5\u53d7\uff0c\u4e0d\u4f1a\u4ea7\u751f\u91cd\u5927\u95ee\u9898\u3002<\/li>\n\n\n\n<li>3.<strong>\u5f15\u5165\u5e42\u7b49\u7684\u4ee3\u4ef7\u8fc7\u5927<\/strong>\uff1a\u5982\u679c\u6211\u4eec\u4e3a\u6d88\u606f\u6d88\u8d39\u5f15\u5165\u5e42\u7b49\u673a\u5236\uff0c\u9700\u8981\u627f\u53d7\u4ee5\u4e0b\u5f00\u9500\uff1a\n<ul class=\"wp-block-list\">\n<li>\u9700\u8981\u4e24\u6b21 Redis \u7f51\u7edc\u8bf7\u6c42\u6765\u68c0\u67e5\u548c\u8bbe\u7f6e\u5e42\u7b49\u6807\u8bc6\u3002<\/li>\n\n\n\n<li>\u4ee3\u7801\u4e2d\u9700\u8981\u589e\u52a0\u989d\u5916\u7684\u903b\u8f91\u5224\u65ad\u3002<\/li>\n\n\n\n<li>Redis \u9700\u8981\u5b58\u50a8\u6570\u767e\u4e07\u6761\u5e42\u7b49\u6807\u8bc6\uff0c\u5e76\u4e14\u901a\u5e38\u8fd9\u4e9b\u6807\u8bc6\u9700\u8981\u8bbe\u7f6e\u7a0d\u957f\uff08\u6bd4\u59822 \u6216\u8005 10 \u5206\u949f\uff09\u7684\u6709\u6548\u671f\uff0c\u5bfc\u81f4\u5de8\u5927\u7684\u5b58\u50a8\u6210\u672c\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>\u7efc\u4e0a\u6240\u8ff0\uff0c\u505a\u6d88\u606f\u6d88\u8d39\u5e42\u7b49\u7684\u6536\u76ca\u975e\u5e38\u6709\u9650\uff0c\u4f46\u4ee3\u4ef7\u5de8\u5927\uff0c\u56e0\u6b64\u6211\u4eec\u65e0\u9700\u4e3a\u6b64\u573a\u666f\u5f15\u5165\u6d88\u8d39\u5e42\u7b49\u673a\u5236\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u4e3a\u4ec0\u4e48\u901a\u77e5\u7c7b\u7a7a\u5b9e\u73b0\uff1f<\/h3>\n\n\n\n<p>\u53d1\u9001\u6d88\u606f\u63d0\u9192\u5c5e\u4e8e\u975e\u6838\u5fc3\u529f\u80fd\uff0c\u901a\u5e38\u53ea\u9700\u590d\u5236 API \u5b9e\u73b0\u5373\u53ef\u3002\u5728\u5b9e\u9645\u5f00\u53d1\u548c\u9762\u8bd5\u4e2d\uff0c\u8fd9\u7c7b\u529f\u80fd\u901a\u5e38\u4e0d\u4f1a\u53d7\u5230\u9762\u8bd5\u5b98\u7684\u7279\u522b\u5173\u6ce8\u3002\u56e0\u6b64\uff0c\u4e3a\u4e86\u7b80\u5316\u5b9e\u73b0\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u76f4\u63a5\u91c7\u7528\u7a7a\u5b9e\u73b0\u7684\u65b9\u5f0f\uff0c\u7701\u53bb\u4e0d\u5fc5\u8981\u7684\u590d\u6742\u5ea6\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u5982\u4f55\u5e94\u5bf9\u767e\u4e07\u7528\u6237\u7684\u5238\u9884\u7ea6\u901a\u77e5\uff1f<\/h3>\n\n\n\n<p>\u5bf9\u4e8e\u8fd9\u4e2a\u95ee\u9898\uff0c\u5b9e\u9645\u4e0a\u5e76\u6ca1\u6709\u6240\u8c13\u7684\u201c\u94f6\u5f39\u201d\u3002\u5728\u4e92\u8054\u7f51\u4f01\u4e1a\u4e2d\uff0c\u9762\u5bf9\u5982\u6b64\u5927\u89c4\u6a21\u7684\u901a\u77e5\u9700\u6c42\uff0c\u5e38\u89c1\u7684\u89e3\u51b3\u65b9\u6848\u662f\u589e\u52a0\u5e94\u7528\u8282\u70b9\u6216\u6269\u5bb9\u7ebf\u7a0b\u6c60\u4e2d\u7684\u7ebf\u7a0b\u6570\u3002\u4ee5\u6700\u8fd1\u5f88\u706b\u7684\u534e\u4e3a XT \u975e\u51e1\u5927\u5e08\u4e3a\u4f8b\uff0c\u5e73\u65f6\u7684\u9884\u7ea6\u91cf\u53ef\u80fd\u53ea\u6709\u51e0\u4e07\uff0c\u7ecf\u8fc7\u8bc4\u4f30\u8282\u70b9\u540e\u53ef\u4ee5\u6b63\u5e38\u53d1\u9001\u3002\u4f46\u662f\uff0c\u9762\u5bf9\u767e\u500d\u589e\u957f\u7684\u60c5\u51b5\uff0c\u4e34\u65f6\u589e\u52a0\u8282\u70b9\u5e76\u6269\u5bb9\u7ebf\u7a0b\u6c60\u53c2\u6570\uff0c\u662f\u6211\u4eec\u5e94\u5bf9\u5927\u89c4\u6a21\u901a\u77e5\u7684\u4e3b\u8981\u624b\u6bb5\u3002<\/p>\n\n\n\n<p>\u9664\u6b64\u4e4b\u5916\uff0c\u6211\u4eec\u8fd8\u53ef\u4ee5\u63d0\u524d\u51e0\u5206\u949f\u901a\u77e5\u7528\u6237\uff0c\u8fd9\u6837\u53ef\u4ee5\u907f\u514d\u7528\u6237\u56e0\u901a\u77e5\u5ef6\u8fdf\u800c\u9519\u8fc7\u63d0\u9192\uff0c\u786e\u4fdd\u7528\u6237\u53ca\u65f6\u6536\u5230\u901a\u77e5\u5e76\u505a\u51fa\u53cd\u5e94\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6d4b\u8bd5\u9884\u7ea6\u529f\u80fd<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u521b\u5efa\u65b0\u7684\u4f18\u60e0\u5238\u6a21\u677f<\/h3>\n\n\n\n<p>\u5927\u5bb6\u8bb0\u5f97\u901a\u8fc7\u540e\u7ba1\u670d\u52a1\u521b\u5efa\u65b0\u7684\u4f18\u60e0\u5238\u6a21\u677f\uff0c\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5982\u679c\u4f60\u8981\u6d4b\u8bd5\u63d0\u524d 5 \u5206\u949f\u901a\u77e5\uff0c\u90a3\u4e48\u6700\u597d <code>validStartTime<\/code> \u65f6\u95f4\u662f\u5f53\u524d\u65f6\u95f4\u7684 7 \u5206\u949f\u540e\u3002\u8fd9\u6837\uff0c\u6211\u4eec\u80fd\u7a7a\u51fa\u6765 2 \u5206\u949f\u65f6\u95f4\u53bb\u521b\u5efa\u9884\u7ea6\u63d0\u9192\u3002<\/p>\n\n\n\n<p>\u6bd4\u5982\u73b0\u5728\u662f 18:23\uff0c\u5f00\u59cb\u65f6\u95f4\u6211\u5c31\u8bbe\u7f6e\u4e3a 18:30\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"name\":\"\u7528\u6237\u4e0b\u5355\u6ee110\u51cf3\u7279\u5927\u4f18\u60e0\",\"source\":0,\"target\":1,\"goods\":\"\",\"type\":0,\"validStartTime\":\"2024-09-20 18:30:00\",\"validEndTime\":\"2024-09-24 18:40:00\",\"stock\":4998,\"receiveRule\":\"{\\\"limitPerPerson\\\":10,\\\"usageInstructions\\\":\\\"3\\\"}\",\"consumeRule\":\"{\\\"termsOfUse\\\":10,\\\"maximumDiscountAmount\\\":3,\\\"explanationOfUnmetConditions\\\":\\\"3\\\",\\\"validityPeriod\\\":\\\"48\\\"}\"}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u521b\u5efa\u9884\u7ea6\u63d0\u9192\u529f\u80fd<\/h3>\n\n\n\n<p>\u901a\u8fc7\u5f15\u64ce\u670d\u52a1\u8c03\u7528\u521b\u5efa\u9884\u7ea6\u63d0\u9192\u63a5\u53e3\uff0c\u590d\u5236\u4e0a\u9762\u521b\u5efa\u7684\u4f18\u60e0\u5238\u6a21\u677f ID\uff0c\u6211\u4eec\u9009\u62e9\u5f00\u62a2\u524d 5 \u5206\u949f\u53d1\u8d77\u63d0\u9192\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"couponTemplateId\":\"1837074807976407041\",\"shopNumber\":\"1810714735922956666\",\"type\":0,\"remindTime\":5}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u67e5\u770b\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\u65e5\u5fd7<\/h3>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u65f6\u95f4\u6765\u5230 18:25 \u7684\u65f6\u5019\uff0c\u6211\u4eec\u7684\u6d88\u606f\u961f\u5217\u6d88\u8d39\u65e5\u5fd7\u89e6\u53d1\u6253\u5370\uff0c\u903b\u8f91\u6b63\u5e38\u6267\u884c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2024-09-20T18:25:00.007+08:00INFO78960---&#91;ading11045568_3]CouponTemplateRemindDelayConsumer:&#91;\u6d88\u8d39\u8005] \u63d0\u9192\u7528\u6237\u62a2\u5238 - \u6267\u884c\u6d88\u8d39\u903b\u8f91\uff0c\u6d88\u606f\u4f53\uff1a{\"keys\":\"1810518709471555585:1837075848033775618\",\"message\":{\"contact\":\"1810518709471555585\",\"couponTemplateId\":\"1837074807976407041\",\"delayTime\":1726828080000,\"remindTime\":5,\"shopNumber\":\"1810714735922956666\",\"startTime\":\"2024-09-20 18:30:00\",\"type\":0,\"userId\":\"1810518709471555585\"},\"timestamp\":1726827998881,\"uuid\":\"31d6d070-cbf0-4096-b3f4-f6feb739b972\"}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u5f00\u53d1\u4e86\u4f18\u60e0\u5238\u9884\u7ea6\u901a\u77e5\u7684\u6d88\u606f\u961f\u5217\u6d88\u8d39\u8005\uff0c\u91c7\u7528\u7ebf\u7a0b\u6c60\u5e76\u884c\u53d1\u9001\u7528\u6237\u9884\u7ea6\u63d0\u9192\uff0c\u786e\u4fdd\u7528\u6237\u80fd\u591f\u53ca\u65f6\u6536\u5230\u901a\u77e5\u3002\u540c\u65f6\uff0c\u4e3a\u4e86\u4fdd\u969c\u7ebf\u7a0b\u6c60\u4e2d\u7684\u4efb\u52a1\u4e0d\u4e22\u5931\uff0c\u6211\u4eec\u901a\u8fc7 Redis Stream \u5ef6\u8fdf\u961f\u5217\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u4efb\u52a1\u7684\u53ef\u9760\u5904\u7406\u3002\u8fd9\u79cd\u65b9\u5f0f\u65e2\u4fdd\u8bc1\u4e86\u63d0\u9192\u7684\u5b9e\u65f6\u6027\uff0c\u4e5f\u786e\u4fdd\u4e86\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b\u4efb\u52a1\u7684\u7a33\u5b9a\u6027\u548c\u53ef\u9760\u6027\u3002<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u5173\u4e8e\u7528\u6237\u53d6\u6d88\u9884\u7ea6\u8bf7\u6c42\u4ee5\u53ca\u67e5\u770b\u7528\u6237\u9884\u7ea6\u5217\u8868\uff0c\u8bf7\u770b\u4e0b\u56de\u5206\u89e3\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c27\u5c0f\u8282\uff1a\u7528\u6237\u67e5\u8be2\/\u53d6\u6d88\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u529f\u80fd<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5f53\u7528\u6237\u9884\u7ea6\u4e86\u4e00\u4e2a\u6216\u591a\u4e2a\u4f18\u60e0\u5238\u62a2\u8d2d\u63d0\u9192\u540e\uff0c\u5982\u679c\u4e0d\u518d\u9700\u8981\u63d0\u9192\uff0c\u53ef\u4ee5\u53d6\u6d88\u9884\u7ea6\u901a\u77e5\u3002\u4e0d\u8fc7\uff0c\u867d\u7136\u7528\u6237\u53ef\u4ee5\u53d6\u6d88\u63d0\u9192\uff0c\u4f46\u5df2\u7ecf\u53d1\u9001\u5230 MQ \u7684\u6d88\u606f\u4e0d\u4f1a\u88ab\u64a4\u56de\uff0c\u6d88\u8d39\u8005\u5728\u65f6\u95f4\u70b9\u5230\u8fbe\u65f6\u4f9d\u7136\u4f1a\u6536\u5230\u6d88\u606f\u3002\u6b64\u65f6\uff0c\u6211\u4eec\u4e0d\u5e94\u8be5\u518d\u5411\u7528\u6237\u53d1\u51fa\u63d0\u9192\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u9700\u8981\u5f00\u53d1\u4e00\u4e2a\u65b9\u6cd5\u6765\u5224\u65ad\u7528\u6237\u662f\u5426\u53d6\u6d88\u4e86\u9884\u7ea6\u3002\u540c\u65f6\uff0c\u8fd8\u9700\u652f\u6301\u7528\u6237\u67e5\u8be2\u5176\u5df2\u9884\u7ea6\u7684\u4f18\u60e0\u5238\u5217\u8868\u4fe1\u606f\uff0c\u4ee5\u4fbf\u7528\u6237\u7ba1\u7406\u5176\u9884\u7ea6\u72b6\u6001\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>20240920_dev_coupon-remind-v3_rocketmq-bitmap_youya<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u672c\u7ae0\u8282\u9884\u7ea6\u63d0\u9192\u4f18\u60e0\u5238\u6838\u5fc3\u4ee3\u7801\u7531\u4f18\u96c5\u540c\u5b66\u8d21\u732e\uff0c\u611f\u8c22\u4f18\u96c5\u63d0\u4f9b\u7684\u4f18\u79c0\u4ee3\u7801\u8bbe\u8ba1\u3002<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">\u53d6\u6d88\u9884\u7ea6\u63d0\u9192<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u53d6\u6d88\u7528\u6237\u9884\u7ea6\u4f18\u60e0\u5238\u63d0\u9192<\/h3>\n\n\n\n<p>\u6709\u8fd9\u6837\u4e00\u79cd\u60c5\u51b5\uff0c\u7528\u6237\u9884\u7ea6\u4e86\u4f18\u60e0\u5238\u63d0\u9192\u540e\u4e0d\u60f3\u518d\u9884\u7ea6\u573a\u666f\uff0c\u90a3\u6211\u4eec\u5c31\u9700\u8981\u628a\u8fd9\u4e2a\u63d0\u9192\u5220\u9664\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\/\/ ......\n\u200b\n &nbsp; &nbsp;@OverridepublicvoidcancelCouponRemind(CouponTemplateRemindCancelReqDTO requestParam){\/\/ \u9a8c\u8bc1\u4f18\u60e0\u5238\u662f\u5426\u5b58\u5728\uff0c\u907f\u514d\u7f13\u5b58\u7a7f\u900f\u95ee\u9898\u5e76\u83b7\u53d6\u4f18\u60e0\u5238\u5f00\u62a2\u65f6\u95f4CouponTemplateQueryRespDTO couponTemplate = couponTemplateService\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  .findCouponTemplate(newCouponTemplateQueryReqDTO(requestParam.getShopNumber(), requestParam.getCouponTemplateId()));if(couponTemplate.getValidStartTime().before(newDate())){thrownewClientException(\"\u65e0\u6cd5\u53d6\u6d88\u5df2\u5f00\u59cb\u9886\u53d6\u7684\u4f18\u60e0\u5238\u9884\u7ea6\");}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;LambdaQueryWrapper&lt;CouponTemplateRemindDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateRemindDO.class).eq(CouponTemplateRemindDO::getUserId,UserContext.getUserId()).eq(CouponTemplateRemindDO::getCouponTemplateId, requestParam.getCouponTemplateId());CouponTemplateRemindDO couponTemplateRemindDO = couponTemplateRemindMapper.selectOne(queryWrapper);if(couponTemplateRemindDO ==null){thrownewClientException(\"\u4f18\u60e0\u5238\u6a21\u677f\u9884\u7ea6\u4fe1\u606f\u4e0d\u5b58\u5728\");}\/\/ \u8ba1\u7b97 BitMap \u4fe1\u606fLong bitMap =CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType());if((bitMap &amp; couponTemplateRemindDO.getInformation())==0L){thrownewClientException(\"\u60a8\u6ca1\u6709\u9884\u7ea6\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\");}\n &nbsp; &nbsp; &nbsp; &nbsp;bitMap ^= couponTemplateRemindDO.getInformation();\n &nbsp; &nbsp; &nbsp; &nbsp;queryWrapper.eq(CouponTemplateRemindDO::getInformation, couponTemplateRemindDO.getInformation());if(bitMap.equals(0L)){\/\/ \u5982\u679c\u65b0 BitMap \u4fe1\u606f\u662f 0\uff0c\u8bf4\u660e\u5df2\u7ecf\u6ca1\u6709\u9884\u7ea6\u63d0\u9192\u4e86\uff0c\u53ef\u4ee5\u76f4\u63a5\u5220\u9664if(couponTemplateRemindMapper.delete(queryWrapper)==0){\/\/ MySQL \u4e50\u89c2\u9501\u8fdb\u884c\u5220\u9664\uff0c\u5982\u679c\u5220\u9664\u5931\u8d25\uff0c\u8bf4\u660e\u7528\u6237\u53ef\u80fd\u540c\u65f6\u6b63\u5728\u8fdb\u884c\u5220\u9664\u3001\u65b0\u589e\u63d0\u9192\u64cd\u4f5cthrownewClientException(\"\u53d6\u6d88\u63d0\u9192\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u9875\u9762\u540e\u91cd\u8bd5\");}}else{\/\/ \u867d\u7136\u5220\u9664\u4e86\u8fd9\u4e2a\u9884\u7ea6\u63d0\u9192\uff0c\u4f46\u8fd8\u6709\u5176\u5b83\u63d0\u9192\uff0c\u90a3\u5c31\u66f4\u65b0\u6570\u636e\u5e93\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDO.setInformation(bitMap);if(couponTemplateRemindMapper.update(couponTemplateRemindDO, queryWrapper)==0){\/\/ MySQL \u4e50\u89c2\u9501\u8fdb\u884c\u66f4\u65b0\uff0c\u5982\u679c\u66f4\u65b0\u5931\u8d25\uff0c\u8bf4\u660e\u7528\u6237\u53ef\u80fd\u540c\u65f6\u6b63\u5728\u8fdb\u884c\u5220\u9664\u3001\u65b0\u589e\u63d0\u9192\u64cd\u4f5cthrownewClientException(\"\u53d6\u6d88\u63d0\u9192\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u9875\u9762\u540e\u91cd\u8bd5\");}}}}<\/code><\/pre>\n\n\n\n<p>\u4e1a\u52a1\u6d41\u7a0b\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u9a8c\u8bc1\u4f18\u60e0\u5238\uff1a\u6839\u636e\u67e5\u8be2\u4f18\u60e0\u5238\u6a21\u677f\u65b9\u6cd5\u907f\u514d\u7f13\u5b58\u51fb\u7a7f\u548c\u7a7f\u900f\uff0c\u5e76\u4e14\u83b7\u53d6\u5230\u4f18\u60e0\u5238\u6a21\u677f\u8be6\u60c5\u540e\u5224\u65ad\u4f18\u60e0\u5238\u662f\u5426\u5df2\u5f00\u59cb\u9886\u53d6\uff0c\u5982\u679c\u662f\u7684\u8bdd\u629b\u51fa\u5f02\u5e38\u3002<\/li>\n\n\n\n<li>2.\u67e5\u8be2\u9884\u7ea6\u63d0\u9192\u8bb0\u5f55\uff1a\u7cfb\u7edf\u4f7f\u7528 <code>userId<\/code> \u548c <code>couponTemplateId<\/code> \u5728\u6570\u636e\u5e93\u4e2d\u67e5\u627e\u5bf9\u5e94\u7684\u63d0\u9192\u8bb0\u5f55\u3002\u5982\u679c\u627e\u4e0d\u5230\u8be5\u8bb0\u5f55\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u63d0\u793a\u201c\u4f18\u60e0\u5238\u6a21\u677f\u9884\u7ea6\u4fe1\u606f\u4e0d\u5b58\u5728\u201d\u3002\u5982\u679c\u627e\u5230\u8bb0\u5f55\uff0c\u7ee7\u7eed\u6267\u884c\u540e\u7eed\u64cd\u4f5c\u3002<\/li>\n\n\n\n<li>3.\u8ba1\u7b97\u7528\u6237\u60f3\u8981\u53d6\u6d88\u7684\u63d0\u9192\u5bf9\u5e94\u7684 BitMap\uff1a\u4f7f\u7528 <code>CouponTemplateRemindUtil.calculateBitMap()<\/code> \u65b9\u6cd5\uff0c\u6839\u636e\u7528\u6237\u7684 <code>remindTime<\/code> \u548c <code>type<\/code> \u8ba1\u7b97\u51fa\u8be5\u63d0\u9192\u5bf9\u5e94\u7684 <code>bitMap<\/code>\uff08\u4f4d\u56fe\uff09\u3002<\/li>\n\n\n\n<li>4.\u68c0\u67e5\u7528\u6237\u662f\u5426\u5df2\u7ecf\u9884\u7ea6\u8be5\u63d0\u9192\uff1a\u901a\u8fc7 <code>bitMap &amp; couponTemplateRemindDO.getInformation()<\/code> \u68c0\u67e5\u6570\u636e\u5e93\u4e2d\u7684\u9884\u7ea6\u63d0\u9192\u4fe1\u606f\u662f\u5426\u5305\u542b\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\u3002\u5982\u679c\u7ed3\u679c\u4e3a <code>0<\/code>\uff0c\u8bf4\u660e\u7528\u6237\u6ca1\u6709\u9884\u7ea6\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\uff0c\u629b\u51fa\u5f02\u5e38\u63d0\u793a\u201c\u60a8\u6ca1\u6709\u9884\u7ea6\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\u201d\u3002<\/li>\n\n\n\n<li>5.\u66f4\u65b0 BitMap \u4fe1\u606f\uff1a\u4f7f\u7528\u5f02\u6216\u64cd\u4f5c <code>bitMap ^= couponTemplateRemindDO.getInformation()<\/code> \u53d6\u6d88\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\u4f4d\u3002\u6b64\u65f6\uff0c<code>bitMap<\/code> \u4f1a\u53bb\u9664\u7528\u6237\u60f3\u8981\u53d6\u6d88\u7684\u63d0\u9192\u5bf9\u5e94\u7684\u4f4d\u3002<\/li>\n\n\n\n<li>6.\u5224\u65ad\u66f4\u65b0\u540e\u7684 BitMap\uff1a\u5982\u679c <code>bitMap<\/code> \u4e3a <code>0<\/code>\uff0c\u8bf4\u660e\u7528\u6237\u53d6\u6d88\u4e86\u6240\u6709\u63d0\u9192\uff0c\u5220\u9664\u8be5\u9884\u7ea6\u63d0\u9192\u8bb0\u5f55\u3002\u5982\u679c <code>bitMap<\/code> \u4e0d\u4e3a <code>0<\/code>\uff1a\u8bf4\u660e\u7528\u6237\u53d6\u6d88\u4e86\u90e8\u5206\u63d0\u9192\uff0c\u4ecd\u6709\u5176\u4ed6\u63d0\u9192\u5b58\u5728\u3002\u7cfb\u7edf\u66f4\u65b0\u6570\u636e\u5e93\u4e2d\u7684 <code>information<\/code> \u5b57\u6bb5\uff0c\u4fdd\u5b58\u5269\u4f59\u7684\u63d0\u9192\u4fe1\u606f\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u6211\u4eec\u901a\u8fc7\u521b\u5efa\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u529f\u80fd\uff0c\u6dfb\u52a0\u4e00\u4e2a 0 \u7c7b\u578b\uff0c\u63d0\u524d 15 \u5206\u949f\u7684\u9884\u7ea6\u63d0\u9192\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"couponTemplateId\":\"1836986189085790209\",\"shopNumber\":\"1810714735922956666\",\"type\":0,\"remindTime\":15}<\/code><\/pre>\n\n\n\n<p>\u9700\u8981\u6ce8\u610f\uff0c\u5728\u540e\u53f0\u670d\u52a1\u521b\u5efa\u4f18\u60e0\u5238\u6a21\u677f\u65f6\uff0c<code>validStartTime<\/code> \u4e0d\u80fd\u5c0f\u4e8e\u5f53\u524d\u65f6\u95f4\u3002\u521b\u5efa\u5b8c\u6210\u540e\uff0c\u6a21\u677f\u4fe1\u606f\u4f1a\u88ab\u590d\u5236\u5230\u521b\u5efa\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u7684\u5165\u53c2\u4e2d\uff0c\u5e76\u5728 <code>t_coupon_template_remind<\/code> \u8868\u4e2d\u751f\u6210\u4e00\u6761\u9884\u7ea6\u63d0\u9192\u8bb0\u5f55\u3002<\/p>\n\n\n\n<p>\u5f53\u7528\u6237\u901a\u8fc7\u53d6\u6d88\u9884\u7ea6\u63d0\u9192\u63a5\u53e3\u8fdb\u884c\u64cd\u4f5c\u65f6\uff0c\u4f20\u5165\u7684\u53c2\u6570\u4f9d\u7136\u662f\u4e0a\u8ff0\u7684\u6a21\u677f\u4fe1\u606f\u3002\u6267\u884c\u53d6\u6d88\u64cd\u4f5c\u540e\uff0c\u67e5\u770b\u6570\u636e\u5e93\u65f6\uff0c\u53ef\u4ee5\u53d1\u73b0\u5bf9\u5e94\u7684\u9884\u7ea6\u63d0\u9192\u8bb0\u5f55\u4f1a\u88ab\u9010\u6b65\u4fee\u6539\u3002\u5982\u679c\u7528\u6237\u521b\u5efa\u4e86\u591a\u4e2a\u65f6\u95f4\u6bb5\u7684\u63d0\u9192\uff0c\u6bcf\u6b21\u53d6\u6d88\u4f1a\u4fee\u6539\u8bb0\u5f55\u4e2d\u7684\u63d0\u9192\u4fe1\u606f\uff0c\u76f4\u5230\u6700\u540e\u4e00\u4e2a\u9884\u7ea6\u65f6\u95f4\u88ab\u53d6\u6d88\uff0c\u624d\u6700\u7ec8\u5220\u9664\u8be5\u8bb0\u5f55\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u6d88\u606f\u961f\u5217\u5224\u65ad\u662f\u5426\u5df2\u53d6\u6d88\u9884\u7ea6<\/h3>\n\n\n\n<p>\u867d\u7136\u7528\u6237\u53ef\u4ee5\u53d6\u6d88\u63d0\u9192\uff0c\u4f46\u5df2\u7ecf\u53d1\u9001\u5230 MQ \u7684\u6d88\u606f\u4e0d\u4f1a\u88ab\u64a4\u56de\uff0c\u6d88\u8d39\u8005\u5728\u65f6\u95f4\u70b9\u5230\u8fbe\u65f6\u4f9d\u7136\u4f1a\u6536\u5230\u6d88\u606f\u3002\u8fd9\u65f6\u6211\u4eec\u4e0d\u5e94\u8be5\u518d\u5411\u7528\u6237\u53d1\u51fa\u63d0\u9192\u3002\u6240\u4ee5\uff0c\u6211\u4eec\u9700\u8981\u5f00\u53d1\u4e00\u4e2a\u65b9\u6cd5\uff0c\u90a3\u5c31\u662f\u5224\u65ad\u7528\u6237\u662f\u5426\u53d6\u6d88\u4e86\u9884\u7ea6\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\n\u200b\n &nbsp; &nbsp;\/\/ ......\n\u200b\n &nbsp; &nbsp;@OverridepublicbooleanisCancelRemind(CouponTemplateRemindDTO requestParam){LambdaQueryWrapper&lt;CouponTemplateRemindDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateRemindDO.class).eq(CouponTemplateRemindDO::getUserId, requestParam.getUserId()).eq(CouponTemplateRemindDO::getCouponTemplateId, requestParam.getCouponTemplateId());CouponTemplateRemindDO couponTemplateRemindDO = couponTemplateRemindMapper.selectOne(queryWrapper);if(couponTemplateRemindDO ==null){\/\/ \u6570\u636e\u5e93\u4e2d\u6ca1\u8be5\u6761\u9884\u7ea6\u63d0\u9192\uff0c\u8bf4\u660e\u88ab\u53d6\u6d88returntrue;}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u5373\u4f7f\u5b58\u5728\u6570\u636e\uff0c\u4e5f\u8981\u68c0\u67e5\u8be5\u7c7b\u578b\u7684\u8be5\u65f6\u95f4\u70b9\u662f\u5426\u6709\u63d0\u9192Long information = couponTemplateRemindDO.getInformation();Long bitMap =CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType());\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6309\u4f4d\u4e0e\u7b49\u4e8e 0 \u8bf4\u660e\u7528\u6237\u53d6\u6d88\u4e86\u9884\u7ea6return(bitMap &amp; information)==0L;}}<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u8be5\u65b9\u6cd5\uff0c\u6211\u4eec\u5728\u6d88\u606f\u961f\u5217\u7684\u6d88\u8d39\u8005\u6267\u884c\u524d\u52a0\u5165\u5224\u65ad\uff0c\u5982\u679c\u5df2\u53d6\u6d88\u5219\u6253\u5370\u4e00\u884c\u65e5\u5fd7\u5373\u53ef\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Slf4j@Component@RequiredArgsConstructorpublicclassCouponTemplateRemindExecutor{\n\u200b\n &nbsp; &nbsp;privatefinalCouponTemplateRemindService couponTemplateRemindService;\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u6267\u884c\u63d0\u9192\n &nbsp; &nbsp; *\n &nbsp; &nbsp; * @param couponTemplateRemindDTO \u7528\u6237\u9884\u7ea6\u63d0\u9192\u8bf7\u6c42\u4fe1\u606f\n &nbsp; &nbsp; *\/publicvoidexecuteRemindCouponTemplate(CouponTemplateRemindDTO couponTemplateRemindDTO){\/\/ \u7528\u6237\u6ca1\u53d6\u6d88\u9884\u7ea6\uff0c\u5219\u53d1\u51fa\u63d0\u9192if(couponTemplateRemindService.isCancelRemind(couponTemplateRemindDTO)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.info(\"\u7528\u6237\u5df2\u53d6\u6d88\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\uff0c\u53c2\u6570\uff1a{}\",JSON.toJSONString(couponTemplateRemindDTO));return;}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ ......}}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u5e03\u9686\u8fc7\u6ee4\u5668\u4f18\u5316\u6027\u80fd<\/h3>\n\n\n\n<p>\u662f\u5426\u9700\u8981\u6bcf\u6b21\u6d88\u606f\u6d88\u8d39\u65f6\u90fd\u67e5\u8be2\u6570\u636e\u5e93\u6765\u68c0\u67e5\u7528\u6237\u662f\u5426\u53d6\u6d88\u4e86\u63d0\u9192\u5462\uff1f\u5982\u679c\u5bf9\u6bcf\u6761\u6d88\u606f\u90fd\u8fdb\u884c\u6570\u636e\u5e93\u67e5\u8be2\uff0c\u6d88\u606f\u6d88\u8d39\u7684\u6548\u7387\u5c31\u4f1a\u53d7\u5230\u6570\u636e\u5e93\u7684\u74f6\u9888\u5f71\u54cd\u3002<\/p>\n\n\n\n<p>\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u53ef\u4ee5\u4f7f\u7528\u5e03\u9686\u8fc7\u6ee4\u5668\u8fdb\u884c\u521d\u6b65\u5224\u65ad\u3002\u5f53\u7528\u6237\u53d6\u6d88\u63d0\u9192\u65f6\uff0c\u6211\u4eec\u6839\u636e\uff08\u7528\u6237ID\u3001\u5238ID\u3001\u63d0\u9192\u65f6\u95f4\u70b9\u3001\u63d0\u9192\u7c7b\u578b\uff09\u7684\u56db\u5143\u7ec4\u8ba1\u7b97\u54c8\u5e0c\u503c\uff0c\u5e76\u5c06\u5176\u5b58\u5165\u5e03\u9686\u8fc7\u6ee4\u5668\u3002\u6d88\u606f\u6d88\u8d39\u65f6\uff0c\u5982\u679c\u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\u4e0d\u5b58\u5728\u8be5\u54c8\u5e0c\u503c\uff0c\u5219\u8bf4\u660e\u7528\u6237\u6ca1\u6709\u53d6\u6d88\u63d0\u9192\uff0c\u53ef\u4ee5\u76f4\u63a5\u53d1\u9001\u63d0\u9192\u3002\u5982\u679c\u5b58\u5728\u8be5\u54c8\u5e0c\u503c\uff0c\u5219\u6709\u4e24\u79cd\u53ef\u80fd\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>1.\u7528\u6237\u786e\u5b9e\u53d6\u6d88\u4e86\u63d0\u9192\u3002<\/li>\n\n\n\n<li>2.\u5e03\u9686\u8fc7\u6ee4\u5668\u53d1\u751f\u4e86\u8bef\u5224\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u7531\u4e8e\u5b58\u5728\u8bef\u5224\u7684\u53ef\u80fd\u6027\uff0c\u6211\u4eec\u5fc5\u987b\u8fdb\u4e00\u6b65\u67e5\u8be2\u6570\u636e\u5e93\uff0c\u786e\u8ba4\u7528\u6237\u662f\u5426\u771f\u7684\u53d6\u6d88\u4e86\u63d0\u9192\u3002\u4e0d\u8fc7\u8fd9\u79cd\u60c5\u51b5\u5f88\u5c11\u51fa\u73b0\uff0c\u5927\u90e8\u5206\u8bf7\u6c42\u5df2\u7ecf\u88ab\u5e03\u9686\u8fc7\u6ee4\u5668\u8fc7\u6ee4\uff0c\u5269\u4e0b\u9700\u8981\u67e5\u8be2\u6570\u636e\u5e93\u7684\u8bf7\u6c42\u91cf\u5f88\u5c0f\u3002<\/p>\n\n\n\n<p>\u5173\u4e8e\u4f7f\u7528 Redis \u8fdb\u884c\u5b58\u50a8\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5728\u6570\u636e\u91cf\u4e0d\u5927\u7684\u60c5\u51b5\u4e0b\uff0c\u53ef\u4ee5\u4f7f\u7528 Redis \u7684 <code>set<\/code> \u96c6\u5408\u6765\u5b58\u50a8\u8fd9\u4e9b\u56db\u5143\u7ec4\u3002<\/li>\n\n\n\n<li>\u4e0d\u80fd\u4f7f\u7528\u4f4d\u56fe\uff0c\u56e0\u4e3a\u4f4d\u56fe\u9002\u7528\u4e8e\u6570\u5b57\u5b58\u50a8\uff0c\u800c\u6211\u4eec\u9700\u8981\u4f7f\u7528\u56db\u5143\u7ec4\u7684\u54c8\u5e0c\u503c\u8fdb\u884c\u5224\u65ad\uff0c\u5f3a\u884c\u4f7f\u7528\u4f4d\u56fe\u4f1a\u5e26\u6765\u8bef\u5224\uff0c\u4e0e\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u60c5\u51b5\u7c7b\u4f3c\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-1\">3.1 \u521b\u5efa\u5e03\u9686\u8fc7\u6ee4\u5668<\/h4>\n\n\n\n<p>\u5728\u4f18\u60e0\u5238\u67e5\u8be2\u5e03\u9686\u8fc7\u6ee4\u5668\u7684\u57fa\u7840\u4e0a\uff0c\u6dfb\u52a0\u9632\u6b62\u53d6\u6d88\u63d0\u9192\u7f13\u5b58\u7a7f\u900f\u5e03\u9686\u8fc7\u6ee4\u5668\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@ConfigurationpublicclassRBloomFilterConfiguration{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u4f18\u60e0\u5238\u67e5\u8be2\u7f13\u5b58\u7a7f\u900f\u5e03\u9686\u8fc7\u6ee4\u5668\n &nbsp; &nbsp; *\/@BeanpublicRBloomFilter&lt;String&gt;couponTemplateQueryBloomFilter(RedissonClient redissonClient,@Value(\"${framework.cache.redis.prefix:}\")String cachePrefix){RBloomFilter&lt;String&gt; bloomFilter = redissonClient.getBloomFilter(cachePrefix +\"couponTemplateQueryBloomFilter\");\n &nbsp; &nbsp; &nbsp; &nbsp;bloomFilter.tryInit(640L,0.001);return bloomFilter;}\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u9632\u6b62\u53d6\u6d88\u63d0\u9192\u7f13\u5b58\u7a7f\u900f\u7684\u5e03\u9686\u8fc7\u6ee4\u5668\n &nbsp; &nbsp; *\/@BeanpublicRBloomFilter&lt;String&gt;cancelRemindBloomFilter(RedissonClient redissonClient,@Value(\"${framework.cache.redis.prefix:}\")String cachePrefix){RBloomFilter&lt;String&gt; bloomFilter = redissonClient.getBloomFilter(cachePrefix +\"cancelRemindBloomFilter\");\n &nbsp; &nbsp; &nbsp; &nbsp;bloomFilter.tryInit(640L,0.001);return bloomFilter;}}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-2\">3.2 \u53d6\u6d88\u9884\u7ea6\u63d0\u9192\u52a0\u5165\u5e03\u9686\u8fc7\u6ee4\u5668<\/h4>\n\n\n\n<p>\u5728\u6211\u4eec\u53d6\u6d88\u4f18\u60e0\u5238\u63d0\u9192\u65b9\u6cd5\u7684\u6700\u540e\uff0c\u5c06\u4f18\u60e0\u5238\u6a21\u677f ID\u3001\u7528\u6237 ID\u3001\u9884\u7ea6\u65f6\u95f4\u3001\u9884\u7ea6\u7c7b\u578b\u83b7\u53d6 Hash \u52a0\u5165\u5e03\u9686\u8fc7\u6ee4\u5668\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\/\/ ......\n\u200b\n &nbsp; &nbsp;privatefinalRBloomFilter&lt;String&gt; cancelRemindBloomFilter;@OverridepublicvoidcancelCouponRemind(CouponTemplateRemindCancelReqDTO requestParam){\/\/ ......\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d6\u6d88\u63d0\u9192\u8fd9\u4e2a\u4fe1\u606f\u6dfb\u52a0\u5230\u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\n &nbsp; &nbsp; &nbsp; &nbsp;cancelRemindBloomFilter.add(String.valueOf(Objects.hash(requestParam.getCouponTemplateId(),UserContext.getUserId(), requestParam.getRemindTime(), requestParam.getType())));}}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-3\">3.3 \u5224\u65ad\u53d6\u6d88\u4f18\u60e0\u5238\u63d0\u9192<\/h4>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\/\/ ......\n\u200b\n &nbsp; &nbsp;privatefinalRBloomFilter&lt;String&gt; cancelRemindBloomFilter;\n\u200b\n &nbsp; &nbsp;@OverridepublicbooleanisCancelRemind(CouponTemplateRemindDTO requestParam){if(!cancelRemindBloomFilter.contains(String.valueOf(Objects.hash(requestParam.getCouponTemplateId(), requestParam.getUserId(), requestParam.getRemindTime(), requestParam.getType())))){\/\/ \u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\u4e0d\u5b58\u5728\uff0c\u8bf4\u660e\u6ca1\u53d6\u6d88\u63d0\u9192\uff0c\u6b64\u65f6\u5df2\u7ecf\u80fd\u6321\u4e0b\u5927\u90e8\u5206\u8bf7\u6c42returnfalse;}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u5bf9\u4e8e\u5c11\u90e8\u5206\u7684\u201c\u53d6\u6d88\u4e86\u9884\u7ea6\u201d\uff0c\u53ef\u80fd\u662f\u8bef\u5224\uff0c\u6b64\u65f6\u9700\u8981\u53bb\u6570\u636e\u5e93\u4e2d\u67e5\u627eLambdaQueryWrapper&lt;CouponTemplateRemindDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateRemindDO.class).eq(CouponTemplateRemindDO::getUserId, requestParam.getUserId()).eq(CouponTemplateRemindDO::getCouponTemplateId, requestParam.getCouponTemplateId());CouponTemplateRemindDO couponTemplateRemindDO = couponTemplateRemindMapper.selectOne(queryWrapper);if(couponTemplateRemindDO ==null){\/\/ \u6570\u636e\u5e93\u4e2d\u6ca1\u8be5\u6761\u9884\u7ea6\u63d0\u9192\uff0c\u8bf4\u660e\u88ab\u53d6\u6d88returntrue;}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u5373\u4f7f\u5b58\u5728\u6570\u636e\uff0c\u4e5f\u8981\u68c0\u67e5\u8be5\u7c7b\u578b\u7684\u8be5\u65f6\u95f4\u70b9\u662f\u5426\u6709\u63d0\u9192Long information = couponTemplateRemindDO.getInformation();Long bitMap =CouponTemplateRemindUtil.calculateBitMap(requestParam.getRemindTime(), requestParam.getType());\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6309\u4f4d\u4e0e\u7b49\u4e8e 0 \u8bf4\u660e\u7528\u6237\u53d6\u6d88\u4e86\u9884\u7ea6return(bitMap &amp; information)==0L;}}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u67e5\u8be2\u9884\u7ea6\u63d0\u9192\u5217\u8868<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u67e5\u8be2\u7528\u6237\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u5217\u8868<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\/\/ ......\n\u200b\n &nbsp; &nbsp;@OverridepublicList&lt;CouponTemplateRemindQueryRespDTO&gt;listCouponRemind(CouponTemplateRemindQueryReqDTO requestParam){String value = stringRedisTemplate.opsForValue().get(String.format(USER_COUPON_TEMPLATE_REMIND_INFORMATION, requestParam.getUserId()));if(value !=null){returnJSON.parseArray(value,CouponTemplateRemindQueryRespDTO.class);}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u67e5\u51fa\u7528\u6237\u9884\u7ea6\u7684\u4fe1\u606fLambdaQueryWrapper&lt;CouponTemplateRemindDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateRemindDO.class).eq(CouponTemplateRemindDO::getUserId, requestParam.getUserId());List&lt;CouponTemplateRemindDO&gt; couponTemplateRemindDOlist = couponTemplateRemindMapper.selectList(queryWrapper);if(CollUtil.isEmpty(couponTemplateRemindDOlist))returnnewArrayList&lt;&gt;();\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u6839\u636e\u4f18\u60e0\u5238 ID \u67e5\u8be2\u4f18\u60e0\u5238\u4fe1\u606fList&lt;Long&gt; couponIds = couponTemplateRemindDOlist.stream().map(CouponTemplateRemindDO::getCouponTemplateId).toList();List&lt;Long&gt; shopNumbers = couponTemplateRemindDOlist.stream().map(CouponTemplateRemindDO::getShopNumber).toList();List&lt;CouponTemplateDO&gt; couponTemplateDOList = couponTemplateService.listCouponTemplateByIds(couponIds, shopNumbers);List&lt;CouponTemplateRemindQueryRespDTO&gt; actualResult =BeanUtil.copyToList(couponTemplateDOList,CouponTemplateRemindQueryRespDTO.class);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u586b\u5145\u54cd\u5e94\u7ed3\u679c\u7684\u5176\u5b83\u4fe1\u606f\n &nbsp; &nbsp; &nbsp; &nbsp;actualResult.forEach(each -&gt;{\/\/ \u627e\u5230\u5f53\u524d\u4f18\u60e0\u5238\u5bf9\u5e94\u7684\u9884\u7ea6\u63d0\u9192\u4fe1\u606f\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;couponTemplateRemindDOlist.stream().filter(i -&gt; i.getCouponTemplateId().equals(each.getId())).findFirst().ifPresent(i -&gt;{\/\/ \u89e3\u6790\u5e76\u586b\u5145\u9884\u7ea6\u63d0\u9192\u4fe1\u606fCouponTemplateRemindUtil.fillRemindInformation(each, i.getInformation());});});\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.opsForValue().set(String.format(USER_COUPON_TEMPLATE_REMIND_INFORMATION, requestParam.getUserId()),JSON.toJSONString(actualResult),1,TimeUnit.MINUTES);return actualResult;}}<\/code><\/pre>\n\n\n\n<p>\u903b\u8f91\u6574\u4f53\u6765\u8bf4\u6bd4\u8f83\u7b80\u5355\uff0c\u4f46\u662f\u6709\u4e24\u4e2a\u6211\u8ba4\u4e3a\u7684\u96be\u70b9\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5982\u4f55\u5c06\u4f4d\u56fe\u4e2d\u7684\u4fe1\u606f\u89e3\u6790\u4e3a\u6b63\u5e38\u7684\u9884\u7ea6\u8bb0\u5f55\uff1f<\/li>\n\n\n\n<li>\u56e0\u4e3a\u7528\u6237\u9884\u7ea6\u7684\u4f18\u60e0\u5238\u53ef\u80fd\u662f\u8de8\u591a\u4e2a\u5e93\u7684\uff0c\u5982\u4f55\u5b8c\u6210\u8de8\u5e93\u67e5\u8be2\uff1f<\/li>\n<\/ul>\n\n\n\n<p>\u56e0\u4e3a\u6211\u4eec\u53d6\u6d88\u4e86\u7528\u6237\u7684\u4f18\u60e0\u5238\u6a21\u677f\u9884\u7ea6\u63d0\u9192\uff0c\u5bf9\u5e94\u6dfb\u52a0\u7684\u7f13\u5b58\u4e5f\u9700\u8981\u5220\u9664\uff0c\u6211\u4eec\u8fd9\u91cc\u91c7\u7528\u66f4\u65b0\u6570\u636e\u5e93\u5220\u9664\u7f13\u5b58\u7b56\u7565\u4fdd\u969c\u6570\u636e\u5e93\u548c\u7f13\u5b58\u4e00\u81f4\u6027\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service@RequiredArgsConstructorpublicclassCouponTemplateServiceRemindImplextendsServiceImpl&lt;CouponTemplateRemindMapper, CouponTemplateRemindDO&gt;implementsCouponTemplateRemindService{\/\/ ......\n\u200b\n &nbsp; &nbsp;privatefinalRBloomFilter&lt;String&gt; cancelRemindBloomFilter;@OverridepublicvoidcancelCouponRemind(CouponTemplateRemindCancelReqDTO requestParam){\/\/ ......\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d6\u6d88\u63d0\u9192\u8fd9\u4e2a\u4fe1\u606f\u6dfb\u52a0\u5230\u5e03\u9686\u8fc7\u6ee4\u5668\u4e2d\n &nbsp; &nbsp; &nbsp; &nbsp;cancelRemindBloomFilter.add(String.valueOf(Objects.hash(requestParam.getCouponTemplateId(),UserContext.getUserId(), requestParam.getRemindTime(), requestParam.getType())));\/\/ \u5220\u9664\u7528\u6237\u9884\u7ea6\u63d0\u9192\u7684\u7f13\u5b58\u4fe1\u606f\uff0c\u901a\u8fc7\u66f4\u65b0\u6570\u636e\u5e93\u5220\u9664\u7f13\u5b58\u7b56\u7565\u4fdd\u969c\u6570\u636e\u5e93\u548c\u7f13\u5b58\u4e00\u81f4\u6027\n &nbsp; &nbsp; &nbsp; &nbsp;stringRedisTemplate.delete(String.format(USER_COUPON_TEMPLATE_REMIND_INFORMATION,UserContext.getUserId()));}}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u89e3\u6790\u4f4d\u56fe\u4fe1\u606f<\/h3>\n\n\n\n<p>\u5916\u5c42\u5faa\u73af\u9010\u4e00\u904d\u5386\u6bcf\u4e2a\u65f6\u95f4\u8282\u70b9\uff0c\u4ece 60 \u5206\u949f\uff08i = 11\uff09\u5f00\u59cb\uff0c\u4f9d\u6b21\u904d\u5386\u5230 5 \u5206\u949f\uff08i = 0\uff09\uff0c\u5373\u4ece\u8ddd\u79bb\u62a2\u8d2d\u65f6\u95f4\u6700\u8fdc\u7684\u8282\u70b9\u9010\u6e10\u904d\u5386\u5230\u79bb\u5f53\u524d\u65f6\u95f4\u6700\u8fd1\u7684\u8282\u70b9\u3002\u5bf9\u4e8e\u6bcf\u4e2a\u65f6\u95f4\u8282\u70b9\uff0c\u8fd8\u9700\u8981\u904d\u5386\u6240\u6709\u63d0\u9192\u7c7b\u578b\u3002\u56e0\u6b64\uff0c\u6700\u7ec8\u7684\u904d\u5386\u987a\u5e8f\u662f\uff1a\u9996\u5148\u904d\u5386 60 \u5206\u949f\u8282\u70b9\u7684\u6240\u6709\u7c7b\u578b\uff08\u5982\u90ae\u7bb1\u63d0\u9192\u3001\u77ed\u4fe1\u63d0\u9192\uff09\uff0c\u63a5\u7740\u904d\u5386 55 \u5206\u949f\u8282\u70b9\u7684\u6240\u6709\u7c7b\u578b\uff0c\u4f9d\u6b64\u7c7b\u63a8\uff0c\u76f4\u5230 5 \u5206\u949f\u8282\u70b9\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * \u4e0b\u4e00\u4e2a\u7c7b\u578b\u7684\u4f4d\u79fb\u91cf\uff0c\u6bcf\u4e2a\u7c7b\u578b\u5360\u752812\u4e2abit\u4f4d\uff0c\u5171\u8ba160\u5206\u949f\n *\/privatestaticfinalintNEXT_TYPE_BITS=12;\n\u200b\n\/**\n * 5\u5206\u949f\u4e3a\u4e00\u4e2a\u95f4\u9694\n *\/privatestaticfinalintTIME_INTERVAL=5;\n\u200b\n\/**\n * \u63d0\u9192\u65b9\u5f0f\u7684\u6570\u91cf\n *\/privatestaticfinalintTYPE_COUNT=CouponRemindTypeEnum.values().length;\n\u200b\n\/**\n * \u586b\u5145\u9884\u7ea6\u4fe1\u606f\n *\/publicstaticvoidfillRemindInformation(CouponTemplateRemindQueryRespDTO resp,Long information){List&lt;Date&gt; dateList =newArrayList&lt;&gt;();List&lt;String&gt; remindType =newArrayList&lt;&gt;();Date validStartTime = resp.getValidStartTime();for(int i =NEXT_TYPE_BITS-1; i &gt;=0; i--){\/\/ \u6309\u65f6\u95f4\u8282\u70b9\u5012\u53d9\u904d\u5386\uff0c\u5373\u79bb\u5f00\u62a2\u65f6\u95f4\u6700\u4e45\uff0c\u79bb\u73b0\u5728\u6700\u8fd1for(int j =0; j &lt;TYPE_COUNT; j++){\/\/ \u5bf9\u4e8e\u6bcf\u4e2a\u65f6\u95f4\u8282\u70b9\uff0c\u904d\u5386\u6240\u6709\u7c7b\u578bif(((information &gt;&gt;(j *NEXT_TYPE_BITS+ i))&amp;1)==1){\/\/ \u8be5\u65f6\u95f4\u8282\u70b9\u7684\u8be5\u63d0\u9192\u7c7b\u578b\u7528\u6237\u6709\u9884\u7ea6Date date =DateUtil.offsetMinute(validStartTime,-((i +1)*TIME_INTERVAL));\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dateList.add(date);\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;remindType.add(CouponRemindTypeEnum.getDescribeByType(j));}}}\n &nbsp; &nbsp;resp.setRemindTime(dateList);\n &nbsp; &nbsp;resp.setRemindType(remindType);}<\/code><\/pre>\n\n\n\n<p>\u6838\u5fc3\u5224\u65ad\u903b\u8f91\u4e3a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>((information &gt;&gt;(j *NEXT_TYPE_BITS+ i))&amp;1)==1<\/code><\/pre>\n\n\n\n<p>\u5728\u904d\u5386\u8fc7\u7a0b\u4e2d\uff0c<code>j<\/code> \u4ee3\u8868\u63d0\u9192\u7c7b\u578b\uff0c<code>i<\/code> \u4ee3\u8868\u65f6\u95f4\u8282\u70b9\uff08\u4f8b\u598260\u5206\u949f\u5bf9\u5e94 i = 11\uff09\u3002\u56e0\u6b64\uff0c<code>j * NEXT_TYPE_BITS + i<\/code> \u8ba1\u7b97\u51fa\u4f4d\u79fb\u91cf\uff0c\u4f8b\u5982\u5f53 <code>j = 0<\/code>\uff08\u90ae\u4ef6\u63d0\u9192\uff09\u4e14 <code>i = 10<\/code>\uff0855\u5206\u949f\uff09\uff0c\u8ba1\u7b97\u7ed3\u679c\u4e3a <code>0 * 12 + 10 = 10<\/code>\u3002\u5982\u679c <code>information<\/code> \u5728\u8be5\u7c7b\u578b\u548c\u65f6\u95f4\u8282\u70b9\u4e0b\u6709\u9884\u7ea6\u8bb0\u5f55\uff0c\u90a3\u4e48 <code>information<\/code> \u7684\u4f4d\u56fe\u7c7b\u4f3c\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7 <code>information &gt;&gt; 10<\/code> \u53ef\u4ee5\u5f97\u5230\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001<\/code><\/pre>\n\n\n\n<p>\u6b64\u65f6\u518d\u4e0e <code>1<\/code> \u8fdb\u884c\u6309\u4f4d\u4e0e\u64cd\u4f5c\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001\n&amp;\n0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001\n= 1<\/code><\/pre>\n\n\n\n<p>\u8bf4\u660e\u8be5\u8282\u70b9\u5df2\u7ecf\u9884\u7ea6\u3002\u5982\u679c\u7ed3\u679c\u4e3a <code>0<\/code>\uff0c\u5219\u8bf4\u660e\u6ca1\u6709\u9884\u7ea6\u3002\u4f8b\u5982\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\n&amp;\n0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001\n= 0<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u8fd9\u4e2a\u504f\u79fb\u8ba1\u7b97\uff0c\u53ef\u4ee5\u51c6\u786e\u5224\u65ad <code>j<\/code> \u7c7b\u578b\u4e0b <code>i<\/code> \u65f6\u95f4\u8282\u70b9\u7684 <code>information<\/code> \u4f4d\u56fe\u662f\u5426\u4e3a1\uff0c\u4ece\u800c\u786e\u5b9a\u7528\u6237\u662f\u5426\u9884\u7ea6\u4e86\u8be5\u65f6\u95f4\u70b9\u7684\u63d0\u9192\u3002<\/p>\n\n\n\n<p>\u6211\u4eec\u521b\u5efa\u51e0\u4e2a\u9884\u7ea6\u63d0\u9192\u540e\uff0c\u901a\u8fc7\u63a5\u53e3\u67e5\u8be2\u7ed3\u679c\u5f97\u77e5\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"code\":\"0\",\"message\":null,\"data\":&#91;{\"id\":1836986189085790209,\"shopNumber\":1810714735922956666,\"name\":\"\u7528\u6237\u4e0b\u5355\u6ee110\u51cf3\u7279\u5927\u4f18\u60e0\",\"source\":0,\"target\":1,\"goods\":\"\",\"type\":0,\"validStartTime\":\"2024-09-20 18:50:00\",\"validEndTime\":\"2024-09-24 18:40:00\",\"receiveRule\":\"{\\\"limitPerPerson\\\": 10, \\\"usageInstructions\\\": \\\"3\\\"}\",\"consumeRule\":\"{\\\"termsOfUse\\\": 10, \\\"validityPeriod\\\": \\\"48\\\", \\\"maximumDiscountAmount\\\": 3, \\\"explanationOfUnmetConditions\\\": \\\"3\\\"}\",\"remindTime\":&#91;\"2024-09-20 18:20:00\",\"2024-09-20 18:20:00\",\"2024-09-20 18:25:00\",\"2024-09-20 18:30:00\",\"2024-09-20 18:35:00\"],\"remindType\":&#91;\"App\u901a\u77e5\",\"\u90ae\u4ef6\u63d0\u9192\",\"App\u901a\u77e5\",\"App\u901a\u77e5\",\"App\u901a\u77e5\"]},{\"id\":1837033594250448898,\"shopNumber\":1810714735922956666,\"name\":\"\u7528\u6237\u4e0b\u5355\u6ee110\u51cf3\u7279\u5927\u4f18\u60e0\",\"source\":0,\"target\":1,\"goods\":\"\",\"type\":0,\"validStartTime\":\"2024-09-20 18:50:00\",\"validEndTime\":\"2024-09-24 18:40:00\",\"receiveRule\":\"{\\\"limitPerPerson\\\": 10, \\\"usageInstructions\\\": \\\"3\\\"}\",\"consumeRule\":\"{\\\"termsOfUse\\\": 10, \\\"validityPeriod\\\": \\\"48\\\", \\\"maximumDiscountAmount\\\": 3, \\\"explanationOfUnmetConditions\\\": \\\"3\\\"}\",\"remindTime\":&#91;\"2024-09-20 18:00:00\",\"2024-09-20 18:05:00\",\"2024-09-20 18:20:00\"],\"remindType\":&#91;\"\u90ae\u4ef6\u63d0\u9192\",\"\u90ae\u4ef6\u63d0\u9192\",\"\u90ae\u4ef6\u63d0\u9192\"]}],\"requestId\":null,\"fail\":false,\"success\":true}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u6279\u91cf\u67e5\u8be2\u4f18\u60e0\u5238\u6a21\u677f<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@OverridepublicList&lt;CouponTemplateDO&gt;listCouponTemplateByIds(List&lt;Long&gt; couponTemplateIds,List&lt;Long&gt; shopNumbers){\/\/ 1. \u5c06 shopNumbers\u96c6\u5408 \u5bf9\u5e94\u7684index\u62c6\u5206\u5230\u6570\u636e\u5e93\u4e2dMap&lt;Integer, List&lt;Long&gt;&gt; databaseIndexMap =splitIndexByDatabase(shopNumbers);List&lt;CouponTemplateDO&gt; result =newArrayList&lt;&gt;();\/\/ 2. \u5bf9\u6bcf\u4e2a\u6570\u636e\u5e93\u6267\u884c\u67e5\u8be2for(Map.Entry&lt;Integer, List&lt;Long&gt;&gt; entry : databaseIndexMap.entrySet()){List&lt;Long&gt; shopNumbersSubset = entry.getValue();\/\/ \u6267\u884c\u67e5\u8be2List&lt;CouponTemplateDO&gt; couponTemplateDOList =queryDatabase(couponTemplateIds, shopNumbersSubset);\n        result.addAll(couponTemplateDOList);}return result;}privateList&lt;CouponTemplateDO&gt;queryDatabase(List&lt;Long&gt; couponTemplateIds,List&lt;Long&gt; shopNumbers){LambdaQueryWrapper&lt;CouponTemplateDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponTemplateDO.class).in(CouponTemplateDO::getShopNumber, shopNumbers).in(CouponTemplateDO::getId, couponTemplateIds);return couponTemplateMapper.selectList(queryWrapper);}privateMap&lt;Integer, List&lt;Long&gt;&gt;splitIndexByDatabase(List&lt;Long&gt; shopNumbers){Map&lt;Integer, List&lt;Long&gt;&gt; databaseShopNumberMap =newHashMap&lt;&gt;();for(Long shopNumber : shopNumbers){int databaseMod =DBShardingUtil.doCouponSharding(shopNumber);\n        databaseShopNumberMap\n                .computeIfAbsent(databaseMod, k -&gt;newArrayList&lt;&gt;()).add(shopNumber);}return databaseShopNumberMap;}<\/code><\/pre>\n\n\n\n<p>\u6570\u636e\u5e93\u5206\u7247\u5de5\u5177\u7c7b\u903b\u8f91\u5f88\u7b80\u5355\uff0c\u6309\u7167\u6211\u4eec\u7684\u5206\u7247\u7b97\u6cd5\u7c7b\u8fdb\u884c\u5206\u7247\u5373\u53ef\uff0c\u8fd9\u6837\u5c31\u80fd\u77e5\u9053\u6570\u636e\u5728\u54ea\u4e2a\u5e93\u4e2d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>publicfinalclassDBShardingUtil{\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u83b7\u53d6\u6570\u636e\u5e93\u5206\u7247\u7b97\u6cd5\u7c7b\uff0c\u5728\u8be5\u7c7b\u521d\u59cb\u5316\u65f6\u5411 Singleton \u653e\u5165\u5b9e\u4f8b\n &nbsp; &nbsp; *\/privatestaticfinalDBHashModShardingAlgorithm dbShardingAlgorithm =Singleton.get(DBHashModShardingAlgorithm.class);\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u89e3\u51b3\u67e5\u8be2\u5546\u5bb6\u4f18\u60e0\u5238 IN \u573a\u666f\u8de8\u5e93\u8868\u4e0d\u5b58\u5728\u95ee\u9898\n &nbsp; &nbsp; *\n &nbsp; &nbsp; * @param shopNumber \u5206\u7247\u952e shopNumber\n &nbsp; &nbsp; * @return \u8fd4\u56de shopNumber \u6240\u5728\u7684\u6570\u636e\u6e90\n &nbsp; &nbsp; *\/publicstaticintdoCouponSharding(Long shopNumber){return dbShardingAlgorithm.getShardingMod(shopNumber,getAvailableDatabases().size());}\n\u200b\n &nbsp; &nbsp;\/**\n &nbsp; &nbsp; * \u83b7\u53d6\u53ef\u7528\u7684\u6570\u636e\u6e90\u5217\u8868\n &nbsp; &nbsp; *\/privatestaticCollection&lt;String&gt;getAvailableDatabases(){returnList.of(\"ds0\",\"ds1\");}}<\/code><\/pre>\n\n\n\n<p>\u4e3a\u4ec0\u4e48\u4e0d\u76f4\u63a5\u4f7f\u7528 selectList \u67e5\u8be2\u800c\u662f\u9700\u8981\u8fdb\u884c\u62c6\u5206\u518d\u591a\u6b21\u67e5\u8be2\uff1f\u56e0\u4e3a\u4e00\u7ec4\u4f18\u60e0\u5238 ID \u4e2d\u53ef\u80fd\u4f1a\u7275\u626f\u591a\u4e2a\u5e93\uff0c\u8fd9\u6837\u5c31\u4f1a\u51fa\u73b0\u8de8\u5e93\u67e5\u8be2\u95ee\u9898\u3002<\/p>\n\n\n\n<p>\u4e3a\u6b64\u6211\u4eec\u6309\u7167\u4e0d\u540c\u4f18\u60e0\u5238 ID \u7684\u6570\u636e\u5e93\u8fdb\u884c\u5206\u7c7b\uff0c\u6bd4\u5982\u4e00\u5171\u6709 5000 \u6761\u8bb0\u5f55\uff0cds0 \u4e0b\u6709 2600 \u6761\u8bb0\u5f55\uff0cds1 \u4e0b\u6709 2400 \u6761\u8bb0\u5f55\uff0c\u5206\u522b\u67e5\u8be2\u5373\u53ef\u6210\u529f\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u672c\u7ae0\u8282\u5c06\u7ee7\u7eed\u56f4\u7ed5\u7528\u6237\u4f18\u60e0\u5238\u9884\u7ea6\u63d0\u9192\u529f\u80fd\u7684\u5f00\u53d1\u5c55\u5f00\uff0c\u652f\u6301\u7528\u6237\u53d6\u6d88\u9884\u7ea6\u63d0\u9192\u3002\u53d6\u6d88\u540e\uff0cRocketMQ \u6d88\u8d39\u8005\u53ef\u4ee5\u611f\u77e5\u5230\u53d6\u6d88\u64cd\u4f5c\uff0c\u4e0d\u518d\u53d1\u9001\u901a\u77e5\u3002\u540c\u65f6\uff0c\u901a\u8fc7\u5404\u79cd\u4f4d\u8fd0\u7b97\uff0c\u7cfb\u7edf\u80fd\u591f\u89e3\u6790\u51fa\u7528\u6237\u7684\u4f18\u60e0\u5238\u6a21\u677f\u9884\u7ea6\u5217\u8868\uff0c\u8ba9\u7528\u6237\u65b9\u4fbf\u5730\u7ba1\u7406\u5176\u9884\u7ea6\u4fe1\u606f\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7b2c28\u5c0f\u8282\uff1a\u5b8c\u6210\u9501\u5b9a\/\u6838\u9500\/\u9000\u8fd8\u4f18\u60e0\u5238\u529f\u80fd<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e1a\u52a1\u80cc\u666f<\/h2>\n\n\n\n<p>\u5151\u6362\u4f18\u60e0\u5238\u4e4b\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u5728\u8ba2\u5355\u7ed3\u7b97\u65f6\u4f7f\u7528\u4f18\u60e0\u5238\uff0c\u8fd9\u4e2a\u65f6\u5019\u4f18\u60e0\u5238\u72b6\u6001\u5c31\u4f1a\u53d8\u6210\u9501\u5b9a\u4e2d\uff1b\u5982\u679c\u7528\u6237\u652f\u4ed8\u4e86\u8ba2\u5355\uff0c\u4f18\u60e0\u5238\u72b6\u6001\u53d8\u66f4\u4e3a\u5df2\u4f7f\u7528\uff1b\u5982\u679c\u8ba2\u5355\u9000\u6b3e\uff0c\u7528\u6237\u4f18\u60e0\u5238\u56de\u9000\u5230\u7528\u6237\u8d26\u6237\u91cc\uff0c\u4f18\u60e0\u5238\u72b6\u6001\u56de\u9000\u5230\u672a\u4f7f\u7528\u72b6\u6001\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5151\u6362\u4f18\u60e0\u5238\uff08\u672a\u4f7f\u7528\uff09<\/strong>\uff1a\u4f18\u60e0\u5238\u88ab\u9886\u53d6\u5230\u7528\u6237\u8d26\u6237\u4e2d\uff0c\u521d\u59cb\u72b6\u6001\u4e3a <code>\u672a\u4f7f\u7528<\/code>\u3002<\/li>\n\n\n\n<li><strong>\u8ba2\u5355\u7ed3\u7b97\uff08\u9501\u5b9a\u4e2d\uff09<\/strong>\uff1a\u5f53\u7528\u6237\u5728\u8ba2\u5355\u4e2d\u4f7f\u7528\u4f18\u60e0\u5238\u65f6\uff0c\u4f18\u60e0\u5238\u72b6\u6001\u5e94\u53d8\u66f4\u4e3a <code>\u9501\u5b9a\u4e2d<\/code>\u3002\u6b64\u65f6\u4f18\u60e0\u5238\u4e0d\u53ef\u88ab\u5176\u4ed6\u8ba2\u5355\u518d\u6b21\u4f7f\u7528\uff0c\u76f4\u5230\u8ba2\u5355\u5b8c\u6210\u6216\u53d6\u6d88\u3002<\/li>\n\n\n\n<li><strong>\u652f\u4ed8\u6210\u529f\uff08\u5df2\u4f7f\u7528\uff09<\/strong>\uff1a\u7528\u6237\u652f\u4ed8\u8ba2\u5355\u540e\uff0c\u4f18\u60e0\u5238\u72b6\u6001\u53d8\u66f4\u4e3a <code>\u5df2\u4f7f\u7528<\/code>\uff0c\u8868\u793a\u4f18\u60e0\u5238\u4f7f\u7528\u6210\u529f\uff0c\u4e0d\u53ef\u518d\u88ab\u4f7f\u7528\u3002<\/li>\n\n\n\n<li><strong>\u8ba2\u5355\u9000\u6b3e\uff08\u672a\u4f7f\u7528\uff09<\/strong>\uff1a\u5982\u679c\u8ba2\u5355\u53d6\u6d88\u6216\u53d1\u751f\u9000\u6b3e\uff0c\u4f18\u60e0\u5238\u72b6\u6001\u56de\u9000\u81f3 <code>\u672a\u4f7f\u7528<\/code>\uff0c\u91cd\u65b0\u56de\u5230\u7528\u6237\u8d26\u6237\u4e2d\uff0c\u53ef\u88ab\u518d\u6b21\u4f7f\u7528\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"git\">Git \u5206\u652f<\/h2>\n\n\n\n<p>\u5148\u4ece main \u5206\u652f\u4e0a\u67e5\u770b\uff0c\u4ee3\u7801\u5165\u53e3\uff1a<code>UserCouponController<\/code>\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6570\u636e\u5e93\u8bbe\u8ba1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1-sql\">1. \u7ed3\u7b97\u8868 SQL<\/h3>\n\n\n\n<p>\u8fdb\u5165 <code>one_coupon_rebuild_0<\/code> \u6570\u636e\u5e93\u4e2d\u6267\u884c\u4e0b\u8ff0 SQL \u8bed\u53e5\u3002<\/p>\n\n\n\n<p>SQL \u8bed\u53e5\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATETABLE`t_coupon_settlement_0`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_1`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_2`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_3`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_4`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_5`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_6`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_7`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';<\/code><\/pre>\n\n\n\n<p>\u7ee7\u7eed\u8fdb\u5165 <code>one_coupon_rebuild_1<\/code> \u6570\u636e\u5e93\u4e2d\u6267\u884c\u4e0b\u8ff0 SQL \u8bed\u53e5\u3002<\/p>\n\n\n\n<p>SQL \u8bed\u53e5\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATETABLE`t_coupon_settlement_8`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_9`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_10`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_11`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_12`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_13`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_14`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';\n\u200b\nCREATETABLE`t_coupon_settlement_15`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'ID',`order_id`bigint(20)DEFAULTNULLCOMMENT'\u8ba2\u5355ID',`user_id`bigint(20)DEFAULTNULLCOMMENT'\u7528\u6237ID',`coupon_id`bigint(20)DEFAULTNULLCOMMENT'\u4f18\u60e0\u5238ID',`status`int(11)DEFAULTNULLCOMMENT'\u7ed3\u7b97\u5355\u72b6\u6001 0\uff1a\u9501\u5b9a 1\uff1a\u5df2\u53d6\u6d88 2\uff1a\u5df2\u652f\u4ed8 3\uff1a\u5df2\u9000\u6b3e',`create_time`datetimeDEFAULTNULLCOMMENT'\u521b\u5efa\u65f6\u95f4',`update_time`datetimeDEFAULTNULLCOMMENT'\u4fee\u6539\u65f6\u95f4',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8868';<\/code><\/pre>\n\n\n\n<p>\u4e3a\u4ec0\u4e48\u7ed3\u7b97\u5355\u8868\u6bd4\u7528\u6237\u4f18\u60e0\u5238\u8868\u5c0f\uff1f<\/p>\n\n\n\n<p>\u8fd9\u5176\u5b9e\u662f\u4e2a\u6bd4\u8f83\u5e38\u89c4\u95ee\u9898\uff0c\u56e0\u4e3a\u6211\u4eec\u9886\u53d6\u4f18\u60e0\u5238\u5f88\u591a\uff0c\u5b9e\u9645\u4e0a\u7528\u7684\u5f88\u5c11\uff0c\u5341\u5206\u4e4b\u4e00\u90fd\u662f\u8bf4\u7684\u7b97\u591a\u4e86\uff0c\u8fd9\u91cc\u653e\u4e86 16 \u5f20\u8868\u4f5c\u4e3a\u793a\u4f8b\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u5206\u5e93\u5206\u8868\u914d\u7f6e<\/h3>\n\n\n\n<p>Engine \u5f15\u64ce\u670d\u52a1\u7684 <code>shardingsphere-config.yaml<\/code> \u4e5f\u9700\u8981\u6dfb\u52a0\u4e0a\u76f8\u5173\u7684\u5206\u5e93\u5206\u8868\u914d\u7f6e\u3002<\/p>\n\n\n\n<p>ShardingSphere \u5b8c\u6574\u5206\u5e93\u5206\u8868\u914d\u7f6e\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u6570\u636e\u6e90\u96c6\u5408dataSources:# \u81ea\u5b9a\u4e49\u6570\u636e\u6e90\u540d\u79f0\uff0c\u53ef\u4ee5\u662f ds_0 \u4e5f\u53ef\u4ee5\u53eb datasource_0 \u90fd\u53ef\u4ee5ds_0:\n &nbsp;  dataSourceClassName: com.zaxxer.hikari.HikariDataSource\n &nbsp;  driverClassName: com.mysql.cj.jdbc.Driver\n &nbsp;  jdbcUrl: jdbc:mysql:\/\/127.0.0.1:3306\/one_coupon_rebuild_0?useUnicode=true&amp;characterEncoding=UTF-8&amp;rewriteBatchedStatements=true&amp;allowMultiQueries=true&amp;serverTimezone=Asia\/Shanghai\n &nbsp;  username: root\n &nbsp;  password: root\n  ds_1:\n &nbsp;  dataSourceClassName: com.zaxxer.hikari.HikariDataSource\n &nbsp;  driverClassName: com.mysql.cj.jdbc.Driver\n &nbsp;  jdbcUrl: jdbc:mysql:\/\/127.0.0.1:3306\/one_coupon_rebuild_1?useUnicode=true&amp;characterEncoding=UTF-8&amp;rewriteBatchedStatements=true&amp;allowMultiQueries=true&amp;serverTimezone=Asia\/Shanghai\n &nbsp;  username: root\n &nbsp;  password: root\n\u200b\nrules:-!SHARDING\n &nbsp;  tables:# \u9700\u8981\u5206\u7247\u7684\u6570\u636e\u5e93\u8868\u96c6\u5408\n &nbsp; &nbsp;  t_coupon_template:# \u4f18\u60e0\u5238\u6a21\u677f\u8868# \u771f\u5b9e\u5b58\u5728\u6570\u636e\u5e93\u4e2d\u7684\u7269\u7406\u8868\n &nbsp; &nbsp; &nbsp;  actualDataNodes: ds_${0..1}.t_coupon_template_${0..15}\n &nbsp; &nbsp; &nbsp;  databaseStrategy:# \u5206\u5e93\u7b56\u7565\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:# \u5355\u5206\u7247\u952e\u5206\u5e93\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: shop_number # \u5206\u7247\u952e\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: coupon_template_database_mod # \u5e93\u5206\u7247\u7b97\u6cd5\u540d\u79f0\uff0c\u5bf9\u5e94 rules&#91;0].shardingAlgorithms\n &nbsp; &nbsp; &nbsp;  tableStrategy:# \u5206\u8868\u7b56\u7565\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:# \u5355\u5206\u7247\u952e\u5206\u8868\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: shop_number # \u5206\u7247\u952e\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: coupon_template_table_mod # \u8868\u5206\u7247\u7b97\u6cd5\u540d\u79f0\uff0c\u5bf9\u5e94 rules&#91;0].shardingAlgorithms\n &nbsp; &nbsp;  t_user_coupon:\n &nbsp; &nbsp; &nbsp;  actualDataNodes: ds_${0..1}.t_user_coupon_${0..31}\n &nbsp; &nbsp; &nbsp;  databaseStrategy:\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: user_id\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: user_coupon_database_mod\n &nbsp; &nbsp; &nbsp;  tableStrategy:\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: user_id\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: user_coupon_table_mod\n &nbsp; &nbsp;  t_coupon_settlement:# \u65b0\u52a0\u7684\n &nbsp; &nbsp; &nbsp;  actualDataNodes: ds_${0..1}.t_coupon_settlement_${0..15}\n &nbsp; &nbsp; &nbsp;  databaseStrategy:\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: user_id\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: user_coupon_settlement_database_mod\n &nbsp; &nbsp; &nbsp;  tableStrategy:\n &nbsp; &nbsp; &nbsp; &nbsp;  standard:\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingColumn: user_id\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  shardingAlgorithmName: user_coupon_settlement_table_mod\n &nbsp;  shardingAlgorithms:# \u5206\u7247\u7b97\u6cd5\u5b9a\u4e49\u96c6\u5408\n &nbsp; &nbsp;  coupon_template_database_mod:# \u4f18\u60e0\u5238\u5206\u5e93\u7b97\u6cd5\u5b9a\u4e49\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED # \u6839\u636e\u81ea\u5b9a\u4e49\u5e93\u5206\u7247\u7b97\u6cd5\u7c7b\u8fdb\u884c\u5206\u7247\n &nbsp; &nbsp; &nbsp;  props:# \u5206\u7247\u76f8\u5173\u5c5e\u6027# \u81ea\u5b9a\u4e49\u5e93\u5206\u7247\u7b97\u6cd5Class\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.DBHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  sharding-count:16# \u5206\u7247\u603b\u6570\u91cf\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard # \u5206\u7247\u7c7b\u578b\uff0c\u5355\u5b57\u6bb5\u5206\u7247\n &nbsp; &nbsp;  coupon_template_table_mod:# \u4f18\u60e0\u5238\u5206\u8868\u7b97\u6cd5\u5b9a\u4e49\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED # \u6839\u636e\u81ea\u5b9a\u4e49\u5e93\u5206\u7247\u7b97\u6cd5\u7c7b\u8fdb\u884c\u5206\u7247\n &nbsp; &nbsp; &nbsp;  props:# \u5206\u7247\u76f8\u5173\u5c5e\u6027# \u81ea\u5b9a\u4e49\u8868\u5206\u7247\u7b97\u6cd5Class\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.TableHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard # \u5206\u7247\u7c7b\u578b\uff0c\u5355\u5b57\u6bb5\u5206\u7247\n &nbsp; &nbsp;  user_coupon_database_mod:\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED\n &nbsp; &nbsp; &nbsp;  props:\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.DBHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  sharding-count:32\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard\n &nbsp; &nbsp;  user_coupon_table_mod:\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED\n &nbsp; &nbsp; &nbsp;  props:\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.TableHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard\n &nbsp; &nbsp;  user_coupon_settlement_database_mod:\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED\n &nbsp; &nbsp; &nbsp;  props:\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.DBHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  sharding-count:16\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard\n &nbsp; &nbsp;  user_coupon_settlement_table_mod:\n &nbsp; &nbsp; &nbsp;  type: CLASS_BASED\n &nbsp; &nbsp; &nbsp;  props:\n &nbsp; &nbsp; &nbsp; &nbsp;  algorithmClassName: com.nageoffer.onecoupon.engine.dao.sharding.TableHashModShardingAlgorithm\n &nbsp; &nbsp; &nbsp; &nbsp;  strategy: standard\n\u200b\nprops:# \u914d\u7f6e ShardingSphere \u9ed8\u8ba4\u6253\u5370 SQL \u6267\u884c\u8bed\u53e5sql-show:true<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u9501\u5b9a\u4f18\u60e0\u5238<\/h2>\n\n\n\n<p>\u7528\u6237\u5728\u8ba2\u5355\u7ed3\u7b97\u65f6\u4f7f\u7528\u4f18\u60e0\u5238\uff0c<strong>\u521b\u5efa\u4f18\u60e0\u5238\u7ed3\u7b97\u5355<\/strong>\uff0c\u5e76\u5c06\u7528\u6237\u4f18\u60e0\u5238\u7684\u72b6\u6001\u4ece\u201c\u672a\u4f7f\u7528\u201d\u53d8\u66f4\u4e3a\u201c\u9501\u5b9a\u4e2d\u201d\uff0c\u786e\u4fdd\u4f18\u60e0\u5238\u5728\u8ba2\u5355\u652f\u4ed8\u8fc7\u7a0b\u4e2d\u88ab\u9501\u5b9a\uff0c\u907f\u514d\u5e76\u53d1\u60c5\u51b5\u4e0b\u540c\u4e00\u4f18\u60e0\u5238\u88ab\u91cd\u590d\u4f7f\u7528\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u83b7\u53d6\u5206\u5e03\u5f0f\u9501<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u65f6\u6240\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RLock lock = redissonClient.getLock(String.format(EngineRedisConstant.LOCK_COUPON_SETTLEMENT_KEY, requestParam.getCouponId()));boolean tryLock = lock.tryLock();if(!tryLock){thrownewClientException(\"\u6b63\u5728\u521b\u5efa\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u83b7\u53d6\u5206\u5e03\u5f0f\u9501<\/strong>\uff1a\u4f7f\u7528 <code>Redisson<\/code> \u83b7\u53d6\u57fa\u4e8e <code>Redis<\/code> \u7684\u5206\u5e03\u5f0f\u9501\uff0c\u9632\u6b62\u5e76\u53d1\u60c5\u51b5\u4e0b\u540c\u4e00\u4f18\u60e0\u5238\u88ab\u591a\u4e2a\u7ebf\u7a0b\u540c\u65f6\u4f7f\u7528\u3002<\/li>\n\n\n\n<li><strong>\u9501\u7684 Key<\/strong>\uff1a\u9501\u7684 Key \u4e3a <code>LOCK_COUPON_SETTLEMENT_KEY + couponId<\/code>\uff0c\u8868\u793a\u9501\u5b9a\u67d0\u4e2a\u5177\u4f53\u4f18\u60e0\u5238\u7684\u7ed3\u7b97\u64cd\u4f5c\u3002<\/li>\n\n\n\n<li><strong>tryLock \u5224\u65ad<\/strong>\uff1a\u5982\u679c\u83b7\u53d6\u4e0d\u5230\u9501\uff0c\u5219\u8868\u793a\u5f53\u524d\u4f18\u60e0\u5238\u6b63\u5728\u521b\u5efa\u7ed3\u7b97\u5355\uff0c\u629b\u51fa\u5f02\u5e38\uff0c\u63d0\u793a\u7a0d\u540e\u518d\u8bd5\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u68c0\u67e5\u4f18\u60e0\u5238\u72b6\u6001<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LambdaQueryWrapper&lt;CouponSettlementDO&gt; queryWrapper =Wrappers.lambdaQuery(CouponSettlementDO.class).eq(CouponSettlementDO::getCouponId, requestParam.getCouponId()).eq(CouponSettlementDO::getUserId,Long.parseLong(UserContext.getUserId())).in(CouponSettlementDO::getStatus,0,2);\n\u200b\nif(couponSettlementMapper.selectOne(queryWrapper)!=null){thrownewClientException(\"\u8bf7\u68c0\u67e5\u4f18\u60e0\u5238\u662f\u5426\u5df2\u4f7f\u7528\");}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u68c0\u67e5\u4f18\u60e0\u5238\u72b6\u6001<\/strong>\uff1a\u901a\u8fc7 <code>CouponSettlementDO<\/code> \u67e5\u8be2\u5f53\u524d\u7528\u6237\u7684\u4f18\u60e0\u5238\u662f\u5426\u5df2\u7ecf\u6709\u7ed3\u7b97\u8bb0\u5f55\u3002\n<ul class=\"wp-block-list\">\n<li>\u72b6\u6001\u4e3a <code>0<\/code> \u8868\u793a\u201c\u9501\u5b9a\u4e2d\u201d\uff0c\u72b6\u6001\u4e3a <code>2<\/code> \u8868\u793a\u201c\u5df2\u4f7f\u7528\u201d\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u907f\u514d\u91cd\u590d\u4f7f\u7528<\/strong>\uff1a\u5982\u679c\u67e5\u8be2\u7ed3\u679c\u4e0d\u4e3a\u7a7a\uff0c\u8bf4\u660e\u4f18\u60e0\u5238\u6b63\u5728\u4f7f\u7528\u6216\u5df2\u4f7f\u7528\uff0c\u629b\u51fa\u5f02\u5e38\u63d0\u793a\u201c\u4f18\u60e0\u5238\u5df2\u4f7f\u7528\u201d\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3\">3. \u7528\u6237\u4f18\u60e0\u5238\u7684\u6709\u6548\u6027\u548c\u72b6\u6001<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UserCouponDO userCouponDO = userCouponMapper.selectOne(Wrappers.lambdaQuery(UserCouponDO.class).eq(UserCouponDO::getId, requestParam.getCouponId()).eq(UserCouponDO::getUserId,Long.parseLong(UserContext.getUserId())));\n\u200b\nif(Objects.isNull(userCouponDO)){thrownewClientException(\"\u4f18\u60e0\u5238\u4e0d\u5b58\u5728\");}if(userCouponDO.getValidEndTime().before(newDate())){thrownewClientException(\"\u4f18\u60e0\u5238\u5df2\u8fc7\u671f\");}if(userCouponDO.getStatus()!=0){thrownewClientException(\"\u4f18\u60e0\u5238\u4f7f\u7528\u72b6\u6001\u5f02\u5e38\");}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u68c0\u67e5\u4f18\u60e0\u5238\u662f\u5426\u5b58\u5728<\/strong>\uff1a\u6839\u636e\u7528\u6237 ID \u548c\u4f18\u60e0\u5238 ID \u67e5\u8be2\u7528\u6237\u7684\u4f18\u60e0\u5238\u6570\u636e\uff0c\u9a8c\u8bc1\u4f18\u60e0\u5238\u7684\u5b58\u5728\u6027\u3002<\/li>\n\n\n\n<li><strong>\u68c0\u67e5\u4f18\u60e0\u5238\u6709\u6548\u671f<\/strong>\uff1a\u5224\u65ad\u4f18\u60e0\u5238\u662f\u5426\u8fc7\u671f\uff0c\u5982\u679c\u8fc7\u671f\u5219\u629b\u51fa\u5f02\u5e38\u3002<\/li>\n\n\n\n<li><strong>\u68c0\u67e5\u4f18\u60e0\u5238\u72b6\u6001<\/strong>\uff1a\u9a8c\u8bc1\u4f18\u60e0\u5238\u662f\u5426\u5904\u4e8e\u201c\u672a\u4f7f\u7528\u201d\u72b6\u6001\uff08<code>status = 0<\/code>\uff09\uff0c\u5982\u679c\u4e0d\u662f\uff0c\u629b\u51fa\u201c\u4f18\u60e0\u5238\u4f7f\u7528\u72b6\u6001\u5f02\u5e38\u201d\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4\">4. \u83b7\u53d6\u4f18\u60e0\u5238\u6a21\u677f\u548c\u6d88\u8d39\u89c4\u5219\uff0c\u8ba1\u7b97\u6298\u6263\u91d1\u989d<\/h3>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CouponTemplateQueryRespDTO couponTemplate = couponTemplateService.findCouponTemplate(newCouponTemplateQueryReqDTO(requestParam.getShopNumber(),String.valueOf(userCouponDO.getCouponTemplateId())));JSONObject consumeRule =JSONObject.parseObject(couponTemplate.getConsumeRule());<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u67e5\u8be2\u4f18\u60e0\u5238\u6a21\u677f<\/strong>\uff1a\u6839\u636e\u4f18\u60e0\u5238\u6a21\u677f ID \u548c\u5e97\u94fa\u7f16\u53f7\uff08<code>shopNumber<\/code>\uff09\u67e5\u8be2\u4f18\u60e0\u5238\u6a21\u677f\u4fe1\u606f\u3002<\/li>\n\n\n\n<li><strong>\u89e3\u6790\u4f18\u60e0\u5238\u7684\u6d88\u8d39\u89c4\u5219<\/strong>\uff1a\u4f7f\u7528 <code>JSONObject<\/code> \u89e3\u6790\u6d88\u8d39\u89c4\u5219\uff08\u4f8b\u5982\u6ee1\u51cf\u6761\u4ef6\u3001\u6298\u6263\u6bd4\u4f8b\u7b49\uff09\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"5\">5. \u6839\u636e\u4e0d\u540c\u7684\u4f18\u60e0\u5238\u7c7b\u578b\u8ba1\u7b97\u6298\u6263\u91d1\u989d<\/h3>\n\n\n\n<p><strong>\u5546\u54c1\u4e13\u5c5e\u4f18\u60e0\u5238<\/strong>\uff1a\u5982\u679c <code>couponTemplate.getTarget()<\/code> \u4e3a <code>0<\/code>\uff0c\u8868\u793a\u4f18\u60e0\u5238\u662f\u5546\u54c1\u4e13\u5c5e\u5238\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u68c0\u67e5\u5546\u54c1\u7f16\u53f7\u662f\u5426\u5339\u914d\uff0c\u5e76\u8ba1\u7b97\u5546\u54c1\u7684\u6298\u6263\u91d1\u989d\u3002<\/li>\n\n\n\n<li>\u5982\u679c\u5546\u54c1\u91d1\u989d\u548c\u6298\u6263\u91d1\u989d\u4e0d\u4e00\u81f4\uff0c\u5219\u629b\u51fa\u5f02\u5e38\u3002<\/li>\n<\/ul>\n\n\n\n<p><strong>\u5e97\u94fa\u4e13\u5c5e\u4f18\u60e0\u5238<\/strong>\uff1a\u5982\u679c <code>couponTemplate.getTarget()<\/code> \u4e3a <code>1<\/code>\uff0c\u8868\u793a\u4f18\u60e0\u5238\u662f\u5e97\u94fa\u4e13\u5c5e\u5238\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u68c0\u67e5\u5e97\u94fa\u7f16\u53f7\u662f\u5426\u5339\u914d\uff0c\u5e76\u6839\u636e\u4f18\u60e0\u5238\u7684\u7c7b\u578b\uff08\u7acb\u51cf\u3001\u6ee1\u51cf\u3001\u6298\u6263\uff09\u8ba1\u7b97\u6298\u6263\u91d1\u989d\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u8ba1\u7b97\u6298\u6263\u540e\u91d1\u989d\u5e76\u68c0\u67e5\uff0c\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BigDecimal actualPayableAmount = requestParam.getOrderAmount().subtract(discountAmount);if(actualPayableAmount.compareTo(requestParam.getPayableAmount())!=0){thrownewClientException(\"\u6298\u6263\u540e\u91d1\u989d\u4e0d\u4e00\u81f4\");}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u8ba1\u7b97\u5b9e\u9645\u5e94\u4ed8\u91d1\u989d<\/strong>\uff1a\u4f7f\u7528\u8ba2\u5355\u91d1\u989d\u51cf\u53bb\u6298\u6263\u91d1\u989d\u6765\u8ba1\u7b97\u5b9e\u9645\u5e94\u4ed8\u91d1\u989d\uff0c\u5e76\u4e0e\u8bf7\u6c42\u53c2\u6570\u4e2d\u7684 <code>payableAmount<\/code> \u8fdb\u884c\u6bd4\u8f83\u3002<\/li>\n\n\n\n<li><strong>\u9a8c\u8bc1\u4e00\u81f4\u6027<\/strong>\uff1a\u5982\u679c\u8ba1\u7b97\u7684\u91d1\u989d\u548c\u8bf7\u6c42\u91d1\u989d\u4e0d\u4e00\u81f4\uff0c\u629b\u51fa\u5f02\u5e38\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"6\">6. \u521b\u5efa\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u5e76\u66f4\u65b0\u4f18\u60e0\u5238\u72b6\u6001<\/h3>\n\n\n\n<p>\u4f7f\u7528 Spring \u7684 <code>TransactionTemplate<\/code> \u63a7\u5236\u4e8b\u52a1\u8303\u56f4\uff0c\u786e\u4fdd\u5728\u540c\u4e00\u4e2a\u4e8b\u52a1\u4e2d\u521b\u5efa\u7ed3\u7b97\u5355\u548c\u66f4\u65b0\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u3002<\/p>\n\n\n\n<p>\u7ed3\u7b97\u5355\u72b6\u6001\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>0\uff1a\u9501\u5b9a<\/li>\n\n\n\n<li>1\uff1a\u5df2\u53d6\u6d88<\/li>\n\n\n\n<li>2\uff1a\u5df2\u652f\u4ed8<\/li>\n\n\n\n<li>3\uff1a\u5df2\u9000\u6b3e<\/li>\n<\/ul>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>transactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ \u521b\u5efa\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8bb0\u5f55CouponSettlementDO couponSettlementDO =CouponSettlementDO.builder().orderId(requestParam.getOrderId()).couponId(requestParam.getCouponId()).userId(Long.parseLong(UserContext.getUserId())).status(0)\/\/ \u72b6\u6001 0 \u8868\u793a\u201c\u9501\u5b9a\u4e2d\u201d.build();\n &nbsp; &nbsp; &nbsp; &nbsp;couponSettlementMapper.insert(couponSettlementDO);\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d8\u66f4\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001LambdaUpdateWrapper&lt;UserCouponDO&gt; userCouponUpdateWrapper =Wrappers.lambdaUpdate(UserCouponDO.class).eq(UserCouponDO::getId, requestParam.getCouponId()).eq(UserCouponDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(UserCouponDO::getStatus,UserCouponStatusEnum.UNUSED.getCode());UserCouponDO updateUserCouponDO =UserCouponDO.builder().status(UserCouponStatusEnum.LOCKING.getCode())\/\/ \u5c06\u72b6\u6001\u66f4\u65b0\u4e3a\u201c\u9501\u5b9a\u4e2d\u201d.build();\n &nbsp; &nbsp; &nbsp; &nbsp;userCouponMapper.update(updateUserCouponDO, userCouponUpdateWrapper);}catch(Exception ex){\n &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u521b\u5efa\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5931\u8d25\", ex);\n &nbsp; &nbsp; &nbsp; &nbsp;status.setRollbackOnly();\/\/ \u4e8b\u52a1\u56de\u6edathrow ex;}});<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u521b\u5efa\u7ed3\u7b97\u5355\u8bb0\u5f55<\/strong>\uff1a\u5728\u6570\u636e\u5e93\u4e2d\u63d2\u5165\u4e00\u6761\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u8bb0\u5f55\u3002<\/li>\n\n\n\n<li><strong>\u66f4\u65b0\u4f18\u60e0\u5238\u72b6\u6001<\/strong>\uff1a\u5c06\u7528\u6237\u7684\u4f18\u60e0\u5238\u72b6\u6001\u4ece\u201c\u672a\u4f7f\u7528\u201d\u66f4\u65b0\u4e3a\u201c\u9501\u5b9a\u4e2d\u201d\u3002<\/li>\n\n\n\n<li><strong>\u4e8b\u52a1\u63a7\u5236<\/strong>\uff1a\u786e\u4fdd\u4ee5\u4e0a\u64cd\u4f5c\u5728\u540c\u4e00\u4e2a\u4e8b\u52a1\u4e2d\u6267\u884c\uff0c\u5982\u679c\u53d1\u751f\u5f02\u5e38\uff0c\u5219\u8fdb\u884c\u4e8b\u52a1\u56de\u6eda\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"7\">7. \u5220\u9664\u7f13\u5b58\u4e2d\u7684\u7528\u6237\u4f18\u60e0\u5238\u6570\u636e<\/h3>\n\n\n\n<p>\u4ece Redis \u4e2d\u5220\u9664\u8be5\u4f18\u60e0\u5238\uff0c\u9632\u6b62\u7528\u6237\u518d\u6b21\u770b\u5230\u5e76\u4f7f\u7528\u3002\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>String userCouponItemCacheKey =StrUtil.builder().append(userCouponDO.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\nstringRedisTemplate.opsForZSet().remove(String.format(USER_COUPON_TEMPLATE_LIST_KEY,UserContext.getUserId()), userCouponItemCacheKey);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u6838\u9500\u4f18\u60e0\u5238<\/h2>\n\n\n\n<p>\u5728\u4f18\u60e0\u5238\u7ed3\u7b97\u8fc7\u7a0b\u4e2d\uff0c<strong>\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355<\/strong>\uff0c\u5e76\u4e14\u5c06\u5bf9\u5e94\u7684\u4f18\u60e0\u5238\u72b6\u6001\u4ece\u201c\u9501\u5b9a\u4e2d\u201d\u53d8\u66f4\u4e3a\u201c\u5df2\u4f7f\u7528\u201d\uff0c\u4fdd\u8bc1\u7ed3\u7b97\u5355\u548c\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u7684\u4e00\u81f4\u6027\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u83b7\u53d6\u5206\u5e03\u5f0f\u9501\uff08<code>Redisson<\/code>\uff09\u6765\u786e\u4fdd\u540c\u4e00\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5728\u591a\u7ebf\u7a0b\u6216\u5e76\u53d1\u64cd\u4f5c\u65f6\u4e0d\u88ab\u91cd\u590d\u6838\u9500\uff0c\u5e76\u4f7f\u7528\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u63a7\u5236\uff08<code>TransactionTemplate<\/code>\uff09\u6765\u786e\u4fdd\u6570\u636e\u64cd\u4f5c\u7684\u539f\u5b50\u6027\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u529f\u80fd\u6982\u8ff0\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u83b7\u53d6\u5206\u5e03\u5f0f\u9501<\/strong>\uff1a\u9632\u6b62\u5e76\u53d1\u60c5\u51b5\u4e0b\u540c\u4e00\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u88ab\u91cd\u590d\u6838\u9500\u3002<\/li>\n\n\n\n<li><strong>\u4e8b\u52a1\u7ba1\u7406<\/strong>\uff1a\u901a\u8fc7 <code>TransactionTemplate<\/code> \u63a7\u5236\u7ed3\u7b97\u5355\u72b6\u6001\u548c\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u7684\u539f\u5b50\u6027\u53d8\u66f4\u3002<\/li>\n\n\n\n<li><strong>\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355<\/strong>\uff1a\u5c06\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u7684\u72b6\u6001\u66f4\u65b0\u4e3a\u201c\u5df2\u652f\u4ed8\u201d\u3002<\/li>\n\n\n\n<li><strong>\u66f4\u65b0\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001<\/strong>\uff1a\u5c06\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u4ece\u201c\u9501\u5b9a\u4e2d\u201d\u66f4\u65b0\u4e3a\u201c\u5df2\u4f7f\u7528\u201d\u3002<\/li>\n\n\n\n<li><strong>\u5f02\u5e38\u5904\u7406\u548c\u65e5\u5fd7\u8bb0\u5f55<\/strong>\uff1a\u5728\u4efb\u4f55\u64cd\u4f5c\u51fa\u73b0\u5f02\u5e38\u65f6\uff0c\u8fdb\u884c\u4e8b\u52a1\u56de\u6eda\uff0c\u5e76\u8bb0\u5f55\u8be6\u7ec6\u7684\u5f02\u5e38\u4fe1\u606f\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u83b7\u53d6\u5206\u5e03\u5f0f\u9501\u9632\u5e76\u53d1<\/h3>\n\n\n\n<p>\u4f7f\u7528 <code>Redisson<\/code> \u521b\u5efa\u4e00\u4e2a\u57fa\u4e8e <code>Redis<\/code> \u7684\u5206\u5e03\u5f0f\u9501 <code>RLock<\/code>\uff0c\u5982\u679c\u5f53\u524d\u7ed3\u7b97\u5355\u5df2\u7ecf\u5728\u88ab\u5176\u4ed6\u7ebf\u7a0b\u6216\u5176\u4ed6\u64cd\u4f5c\u8fdb\u884c\u6838\u9500\uff0c\u9501\u83b7\u53d6\u5931\u8d25\uff08<code>tryLock<\/code> \u8fd4\u56de <code>false<\/code>\uff09\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u63d0\u793a\u201c\u6b63\u5728\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\u201d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RLock lock = redissonClient.getLock(String.format(EngineRedisConstant.LOCK_COUPON_SETTLEMENT_KEY, requestParam.getCouponId()));boolean tryLock = lock.tryLock();if(!tryLock){thrownewClientException(\"\u6b63\u5728\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u4fee\u6539\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u5e76\u66f4\u65b0\u4f18\u60e0\u5238\u72b6\u6001<\/h3>\n\n\n\n<p>\u4f7f\u7528 Spring \u7684 <code>TransactionTemplate<\/code> \u6765\u624b\u52a8\u63a7\u5236\u4e8b\u52a1\uff0c\u786e\u4fdd\u64cd\u4f5c\u7684\u539f\u5b50\u6027\u548c\u4e00\u81f4\u6027\u3002<\/p>\n\n\n\n<p>\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\uff0c\u66f4\u65b0\u72b6\u6001\u4e3a\u201c\u5df2\u652f\u4ed8\u201d\uff0c\u72b6\u6001 <code>0<\/code> \u8868\u793a\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5904\u4e8e\u201c\u9501\u5b9a\u4e2d\u201d\uff0c\u9632\u6b62\u91cd\u590d\u6838\u9500\u5df2\u652f\u4ed8\u7684\u7ed3\u7b97\u5355\u3002\u5c06 <code>CouponSettlementDO<\/code> \u5bf9\u8c61\u7684\u72b6\u6001\u66f4\u65b0\u4e3a <code>2<\/code>\uff08\u8868\u793a\u201c\u5df2\u652f\u4ed8\u201d\uff09\uff0c\u5e76\u6267\u884c\u66f4\u65b0\u64cd\u4f5c\u3002\u5982\u679c <code>update<\/code> \u64cd\u4f5c\u8fd4\u56de\u7ed3\u679c\u4e3a <code>0<\/code>\uff08\u8868\u793a\u672a\u66f4\u65b0\u4efb\u4f55\u8bb0\u5f55\uff09\uff0c\u5219\u629b\u51fa\u5f02\u5e38\u3002<\/p>\n\n\n\n<p>\u5c06\u7528\u6237\u4f18\u60e0\u5238\u7684\u72b6\u6001\u66f4\u65b0\u4e3a <code>USED<\/code>\uff08\u8868\u793a\u201c\u5df2\u4f7f\u7528\u201d\uff09\uff0c\u66f4\u65b0\u540e\u68c0\u67e5\u662f\u5426\u6210\u529f\uff0c\u5982\u679c\u5931\u8d25\uff0c\u8bb0\u5f55\u65e5\u5fd7\u5e76\u629b\u51fa\u5f02\u5e38\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u51cf\u5c0f\u4e8b\u52a1\u8303\u56f4\ntransactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ \u53d8\u66f4\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u72b6\u6001\u4e3a\u5df2\u652f\u4ed8LambdaUpdateWrapper&lt;CouponSettlementDO&gt; couponSettlementUpdateWrapper =Wrappers.lambdaUpdate(CouponSettlementDO.class).eq(CouponSettlementDO::getCouponId, requestParam.getCouponId()).eq(CouponSettlementDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(CouponSettlementDO::getStatus,0);CouponSettlementDO couponSettlementDO =CouponSettlementDO.builder().status(2).build();int couponSettlementUpdated = couponSettlementMapper.update(couponSettlementDO, couponSettlementUpdateWrapper);if(!SqlHelper.retBool(couponSettlementUpdated)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5f02\u5e38\uff0c\u8bf7\u6c42\u53c2\u6570\uff1a{}\", com.alibaba.fastjson.JSON.toJSONString(requestParam));thrownewServiceException(\"\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5f02\u5e38\");}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d8\u66f4\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001LambdaUpdateWrapper&lt;UserCouponDO&gt; userCouponUpdateWrapper =Wrappers.lambdaUpdate(UserCouponDO.class).eq(UserCouponDO::getId, requestParam.getCouponId()).eq(UserCouponDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(UserCouponDO::getStatus,UserCouponStatusEnum.LOCKING.getCode());UserCouponDO userCouponDO =UserCouponDO.builder().status(UserCouponStatusEnum.USED.getCode()).build();int userCouponUpdated = userCouponMapper.update(userCouponDO, userCouponUpdateWrapper);if(!SqlHelper.retBool(userCouponUpdated)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u4fee\u6539\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u72b6\u6001\u5df2\u4f7f\u7528\u5f02\u5e38\uff0c\u8bf7\u6c42\u53c2\u6570\uff1a{}\", com.alibaba.fastjson.JSON.toJSONString(requestParam));thrownewServiceException(\"\u4fee\u6539\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u72b6\u6001\u5f02\u5e38\");}}catch(Exception ex){\n &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5931\u8d25\", ex);\n &nbsp; &nbsp; &nbsp; &nbsp;status.setRollbackOnly();throw ex;}finally{\n &nbsp; &nbsp; &nbsp; &nbsp;lock.unlock();}});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u9000\u6b3e\u4f18\u60e0\u5238<\/h2>\n\n\n\n<p>\u5c06\u7528\u6237\u5df2\u7ecf\u4f7f\u7528\u7684\u4f18\u60e0\u5238\u6062\u590d\u4e3a\u201c\u672a\u4f7f\u7528\u201d\u72b6\u6001\uff0c\u5e76\u5c06\u5bf9\u5e94\u7684\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u72b6\u6001\u53d8\u66f4\u4e3a\u201c\u5df2\u9000\u6b3e\u201d\u3002\u5728\u4f18\u60e0\u5238\u72b6\u6001\u53d8\u66f4\u5b8c\u6210\u540e\uff0c\u8fd8\u5c06\u4f18\u60e0\u5238\u91cd\u65b0\u653e\u56de Redis \u7f13\u5b58\u4e2d\uff0c\u4fbf\u4e8e\u7528\u6237\u540e\u7eed\u7ee7\u7eed\u4f7f\u7528\u8be5\u4f18\u60e0\u5238\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u903b\u8f91\u6982\u8ff0\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u83b7\u53d6\u5206\u5e03\u5f0f\u9501<\/strong>\uff1a\u901a\u8fc7\u5206\u5e03\u5f0f\u9501\u786e\u4fdd\u540c\u4e00\u65f6\u95f4\u53ea\u6709\u4e00\u4e2a\u7ebf\u7a0b\u80fd\u591f\u5bf9\u76f8\u540c\u7684\u4f18\u60e0\u5238\u8fdb\u884c\u9000\u6b3e\u5904\u7406\uff0c\u9632\u6b62\u5e76\u53d1\u64cd\u4f5c\u5f15\u53d1\u6570\u636e\u4e0d\u4e00\u81f4\u3002<\/li>\n\n\n\n<li><strong>\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u63a7\u5236<\/strong>\uff1a\u4f7f\u7528 <code>TransactionTemplate<\/code> \u63a7\u5236\u4e8b\u52a1\u8303\u56f4\uff0c\u4fdd\u8bc1\u7ed3\u7b97\u5355\u548c\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u7684\u539f\u5b50\u6027\u53d8\u66f4\u3002<\/li>\n\n\n\n<li><strong>\u66f4\u65b0\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u72b6\u6001<\/strong>\uff1a\u5c06\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u72b6\u6001\u4ece\u201c\u5df2\u4f7f\u7528\u201d\u53d8\u66f4\u4e3a\u201c\u5df2\u9000\u6b3e\u201d\u3002<\/li>\n\n\n\n<li><strong>\u6062\u590d\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001<\/strong>\uff1a\u5c06\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001\u4ece\u201c\u5df2\u4f7f\u7528\u201d\u6062\u590d\u4e3a\u201c\u672a\u4f7f\u7528\u201d\u3002<\/li>\n\n\n\n<li><strong>\u5c06\u4f18\u60e0\u5238\u653e\u56de Redis \u7f13\u5b58<\/strong>\uff1a\u67e5\u8be2\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\uff0c\u5c06\u4f18\u60e0\u5238\u91cd\u65b0\u653e\u56de Redis \u4e2d\uff0c\u4fbf\u4e8e\u7528\u6237\u540e\u7eed\u7ee7\u7eed\u4f7f\u7528\u3002<\/li>\n\n\n\n<li><strong>\u5f02\u5e38\u5904\u7406\u548c\u9501\u91ca\u653e<\/strong>\uff1a\u5904\u7406\u8fc7\u7a0b\u4e2d\u51fa\u73b0\u4efb\u4f55\u5f02\u5e38\u65f6\uff0c\u8bb0\u5f55\u65e5\u5fd7\u5e76\u56de\u6eda\u4e8b\u52a1\uff0c\u540c\u65f6\u4fdd\u8bc1\u5206\u5e03\u5f0f\u9501\u80fd\u591f\u88ab\u6b63\u786e\u91ca\u653e\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"1\">1. \u83b7\u53d6\u5206\u5e03\u5f0f\u9501\u9632\u6b62\u5e76\u53d1<\/h3>\n\n\n\n<p>\u5982\u679c\u5f53\u524d\u4f18\u60e0\u5238\u5df2\u7ecf\u5728\u88ab\u5176\u4ed6\u7ebf\u7a0b\u6216\u64cd\u4f5c\u8fdb\u884c\u9000\u6b3e\u5904\u7406\uff0c\u9501\u83b7\u53d6\u5931\u8d25\uff08<code>tryLock<\/code> \u8fd4\u56de <code>false<\/code>\uff09\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u63d0\u793a\u201c\u6b63\u5728\u6267\u884c\u4f18\u60e0\u5238\u9000\u6b3e\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\u201d\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RLock lock = redissonClient.getLock(String.format(EngineRedisConstant.LOCK_COUPON_SETTLEMENT_KEY, requestParam.getCouponId()));boolean tryLock = lock.tryLock();if(!tryLock){thrownewClientException(\"\u6b63\u5728\u6267\u884c\u4f18\u60e0\u5238\u9000\u6b3e\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5\");}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"2\">2. \u66f4\u65b0\u7ed3\u7b97\u5355\u548c\u4f18\u60e0\u5238\u72b6\u6001<\/h3>\n\n\n\n<p>\u4f7f\u7528 Spring \u7684 <code>TransactionTemplate<\/code> \u6765\u624b\u52a8\u63a7\u5236\u4e8b\u52a1\uff0c\u786e\u4fdd\u64cd\u4f5c\u7684\u539f\u5b50\u6027\u548c\u4e00\u81f4\u6027\u3002<\/p>\n\n\n\n<p>\u5c06 <code>CouponSettlementDO<\/code> \u5bf9\u8c61\u7684\u72b6\u6001\u66f4\u65b0\u4e3a <code>3<\/code>\uff08\u201c\u5df2\u9000\u6b3e\u201d\uff09\uff0c\u5e76\u6267\u884c\u66f4\u65b0\u64cd\u4f5c\u3002\u5982\u679c <code>update<\/code> \u64cd\u4f5c\u8fd4\u56de\u7ed3\u679c\u4e3a <code>0<\/code>\uff08\u8868\u793a\u672a\u66f4\u65b0\u4efb\u4f55\u8bb0\u5f55\uff09\uff0c\u5219\u629b\u51fa\u5f02\u5e38\u3002<\/p>\n\n\n\n<p>\u5c06\u7528\u6237\u4f18\u60e0\u5238\u7684\u72b6\u6001\u66f4\u65b0\u4e3a <code>UNUSED<\/code>\uff08\u201c\u672a\u4f7f\u7528\u201d\uff09\uff0c\u68c0\u67e5\u66f4\u65b0\u662f\u5426\u6210\u529f\uff0c\u5982\u679c\u5931\u8d25\uff0c\u8bb0\u5f55\u65e5\u5fd7\u5e76\u629b\u51fa\u5f02\u5e38\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u901a\u8fc7\u7f16\u7a0b\u5f0f\u4e8b\u52a1\u51cf\u5c0f\u4e8b\u52a1\u8303\u56f4\ntransactionTemplate.executeWithoutResult(status -&gt;{try{\/\/ \u53d8\u66f4\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u72b6\u6001\u4e3a\u5df2\u9000\u6b3eLambdaUpdateWrapper&lt;CouponSettlementDO&gt; couponSettlementUpdateWrapper =Wrappers.lambdaUpdate(CouponSettlementDO.class).eq(CouponSettlementDO::getCouponId, requestParam.getCouponId()).eq(CouponSettlementDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(CouponSettlementDO::getStatus,2);CouponSettlementDO couponSettlementDO =CouponSettlementDO.builder().status(3).build();int couponSettlementUpdated = couponSettlementMapper.update(couponSettlementDO, couponSettlementUpdateWrapper);if(!SqlHelper.retBool(couponSettlementUpdated)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u9000\u6b3e\u5f02\u5e38\uff0c\u8bf7\u6c42\u53c2\u6570\uff1a{}\", com.alibaba.fastjson.JSON.toJSONString(requestParam));thrownewServiceException(\"\u6838\u9500\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u5f02\u5e38\");}\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp;\/\/ \u53d8\u66f4\u7528\u6237\u4f18\u60e0\u5238\u72b6\u6001LambdaUpdateWrapper&lt;UserCouponDO&gt; userCouponUpdateWrapper =Wrappers.lambdaUpdate(UserCouponDO.class).eq(UserCouponDO::getId, requestParam.getCouponId()).eq(UserCouponDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(UserCouponDO::getStatus,UserCouponStatusEnum.USED.getCode());UserCouponDO userCouponDO =UserCouponDO.builder().status(UserCouponStatusEnum.UNUSED.getCode()).build();int userCouponUpdated = userCouponMapper.update(userCouponDO, userCouponUpdateWrapper);if(!SqlHelper.retBool(userCouponUpdated)){\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u4fee\u6539\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u72b6\u6001\u672a\u4f7f\u7528\u5f02\u5e38\uff0c\u8bf7\u6c42\u53c2\u6570\uff1a{}\", com.alibaba.fastjson.JSON.toJSONString(requestParam));thrownewServiceException(\"\u4fee\u6539\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\u72b6\u6001\u5f02\u5e38\");}}catch(Exception ex){\n &nbsp; &nbsp; &nbsp; &nbsp;log.error(\"\u6267\u884c\u4f18\u60e0\u5238\u7ed3\u7b97\u5355\u9000\u6b3e\u5931\u8d25\", ex);\n &nbsp; &nbsp; &nbsp; &nbsp;status.setRollbackOnly();throw ex;}});<\/code><\/pre>\n\n\n\n<p>\u67e5\u8be2\u7528\u6237\u4f18\u60e0\u5238\u8bb0\u5f55\uff0c\u6784\u5efa\u7f13\u5b58 Key\uff0c\u4f7f\u7528 <code>ZSet<\/code> \u6570\u636e\u7ed3\u6784\u5c06\u4f18\u60e0\u5238\u4fe1\u606f\u653e\u56de Redis \u4e2d\uff0c\u786e\u4fdd\u7528\u6237\u53ef\u4ee5\u5728\u540e\u7eed\u7ee7\u7eed\u4f7f\u7528\u8be5\u4f18\u60e0\u5238\u3002<\/p>\n\n\n\n<p>\u4ee3\u7801\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u67e5\u8be2\u51fa\u6765\u4f18\u60e0\u5238\u518d\u653e\u56de\u7f13\u5b58UserCouponDO userCouponDO = userCouponMapper.selectOne(Wrappers.lambdaQuery(UserCouponDO.class).eq(UserCouponDO::getUserId,Long.parseLong(UserContext.getUserId())).eq(UserCouponDO::getId, requestParam.getCouponId()));String userCouponItemCacheKey =StrUtil.builder().append(userCouponDO.getCouponTemplateId()).append(\"_\").append(userCouponDO.getId()).toString();\nstringRedisTemplate.opsForZSet().add(String.format(USER_COUPON_TEMPLATE_LIST_KEY,UserContext.getUserId()), userCouponItemCacheKey, userCouponDO.getReceiveTime().getTime());<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u6587\u672b\u603b\u7ed3<\/h2>\n\n\n\n<p>\u672c\u7ae0\u8282\u91cd\u70b9\u5b9e\u73b0\u4e86\u4f18\u60e0\u5238\u5728\u4e0d\u540c\u4e1a\u52a1\u573a\u666f\u4e0b\u7684\u72b6\u6001\u7ba1\u7406\uff0c\u5305\u62ec\u9501\u5b9a\u3001\u6838\u9500\u548c\u9000\u8fd8\u529f\u80fd\u3002\u901a\u8fc7\u5f15\u5165\u5206\u5e03\u5f0f\u9501\uff08\u5982 Redis \u7684 Redisson\uff09\u548c\u4e8b\u52a1\u63a7\u5236\uff0c\u786e\u4fdd\u4e86\u4f18\u60e0\u5238\u72b6\u6001\u53d8\u66f4\u7684\u539f\u5b50\u6027\u548c\u4e00\u81f4\u6027\uff0c\u9632\u6b62\u4e86\u5e76\u53d1\u64cd\u4f5c\u53ef\u80fd\u5bfc\u81f4\u7684\u72b6\u6001\u51b2\u7a81\u3002<\/p>\n\n\n\n<p>\u5b8c\u7ed3\uff0c\u6492\u82b1 \ud83c\udf89<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7b2c21\u5c0f\u8282\uff1a\u4f18\u60e0\u5238\u5206\u53d1\u5931\u8d25\u8bb0\u5f55\u6df1\u5206\u9875\u4f18\u5316 \u4e1a\u52a1\u80cc\u666f \u5728\u6267\u884c\u4f18\u60e0\u5238\u5206\u53d1\u65f6\uff0c\u5bf9\u4e8e\u56e0\u5e93\u5b58\u4e0d\u8db3\u6216\u7528\u6237\u5df2\u9886\u53d6\u8fc7\u4f18\u60e0\u5238\u800c\u5bfc\u81f4\u7684\u5206\u53d1\u5931\u8d25\u60c5\u51b5\uff0c\u6211 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"emotion":"","emotion_color":"","title_style":"","license":"","footnotes":""},"categories":[3],"tags":[20],"class_list":["post-1248","post","type-post","status-publish","format-standard","hentry","category-3","tag-20"],"_links":{"self":[{"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/posts\/1248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eve2333.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1248"}],"version-history":[{"count":7,"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/posts\/1248\/revisions"}],"predecessor-version":[{"id":1314,"href":"https:\/\/eve2333.top\/index.php?rest_route=\/wp\/v2\/posts\/1248\/revisions\/1314"}],"wp:attachment":[{"href":"https:\/\/eve2333.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eve2333.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1248"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eve2333.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}