{"id":3306,"date":"2025-03-24T08:46:29","date_gmt":"2025-03-23T23:46:29","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=3306"},"modified":"2025-03-24T08:46:59","modified_gmt":"2025-03-23T23:46:59","slug":"redis-cluster%e3%81%ae%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9aphp%e3%81%a7%e3%81%ae%e6%a7%8b%e7%af%89%e3%81%8b%e3%82%89%e9%81%8b%e7%94%a8%e3%81%be%e3%81%a7%e5%be%b9%e5%ba%95%e8%a7%a3","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=3306","title":{"rendered":"Redis Cluster\u306e\u5b8c\u5168\u30ac\u30a4\u30c9\uff1aPHP\u3067\u306e\u69cb\u7bc9\u304b\u3089\u904b\u7528\u307e\u3067\u5fb9\u5e95\u89e3\u8aac"},"content":{"rendered":"\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>116<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>121<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>128<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\" data-dialog-title=\"\u76ee\u6b21\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">  <li class=\"first\">    <a href=\"#i-0\">Redis Cluster\u3068\u306f\uff1a\u5206\u6563\u30ad\u30e3\u30c3\u30b7\u30e5\u30b7\u30b9\u30c6\u30e0\u306e\u9769\u65b0\u7684\u30a2\u30d7\u30ed\u30fc\u30c1<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">\u5f93\u6765\u306eRedis\u3068\u6bd4\u8f03\u3057\u305f\u969b\u306eCluster\u306e\u7279\u5fb4\u3068\u5229\u70b9<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u3068\u30d5\u30a9\u30fc\u30eb\u30c8\u30c8\u30ec\u30e9\u30f3\u30b9\u306e\u4ed5\u7d44\u307f<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-4\">Redis Cluster\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u8a73\u89e3<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-5\">\u30de\u30b9\u30bf\u30fc\u30fb\u30b9\u30ec\u30fc\u30d6\u30ce\u30fc\u30c9\u306e\u5f79\u5272\u3068\u95a2\u4fc2\u6027<\/a>      <\/li>      <li>        <a href=\"#i-8\">\u30b7\u30e3\u30fc\u30c7\u30a3\u30f3\u30b0\u306e\u4ed5\u7d44\u307f\u3068\u52b9\u679c\u7684\u306a\u30c7\u30fc\u30bf\u5206\u6563\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-11\">\u30af\u30e9\u30b9\u30bf\u30fc\u30c8\u30dd\u30ed\u30b8\u30fc\u306e\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-15\">PHP\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306eRedis Cluster\u74b0\u5883\u69cb\u7bc9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-16\">\u5fc5\u8981\u306a\u62e1\u5f35\u6a5f\u80fd\u3068\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/a>      <\/li>      <li>        <a href=\"#i-19\">\u57fa\u672c\u7684\u306a\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u89e3\u8aac\u3068\u6700\u9069\u5316\u306e\u30dd\u30a4\u30f3\u30c8<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-23\">\u30af\u30e9\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306e\u8ffd\u52a0\u3068\u524a\u9664\u306e\u5b9f\u8df5\u7684\u306a\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-27\">PHP\u3067\u306eRedis Cluster\u5b9f\u88c5\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-28\">\u52b9\u7387\u7684\u306a\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u30d7\u30fc\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/a>      <\/li>      <li>        <a href=\"#i-31\">\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u3068\u6574\u5408\u6027\u306e\u78ba\u4fdd<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-34\">\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3068\u30ea\u30c8\u30e9\u30a4\u30e1\u30ab\u30cb\u30ba\u30e0<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-37\">Redis Cluster\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-38\">\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316\u3068\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u624b\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-41\">\u30ec\u30a4\u30c6\u30f3\u30b7\u30fc\u6539\u5584\u306e\u305f\u3081\u306e\u5177\u4f53\u7684\u306a\u8a2d\u5b9a\u8abf\u6574<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-44\">\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u30b9\u30b1\u30fc\u30eb\u30a2\u30c3\u30d7\u3068\u30b9\u30b1\u30fc\u30eb\u30a2\u30a6\u30c8\u6226\u7565<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-47\">Redis Cluster\u306e\u904b\u7528\u7ba1\u7406\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-48\">\u52b9\u679c\u7684\u306a\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3068\u30a2\u30e9\u30fc\u30c8\u8a2d\u5b9a\u306e\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-51\">\u4e00\u822c\u7684\u306a\u969c\u5bb3\u30d1\u30bf\u30fc\u30f3\u3068\u89e3\u6c7a\u30a2\u30d7\u30ed\u30fc\u30c1<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-53\">\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3068\u707d\u5bb3\u5fa9\u65e7\u8a08\u753b\u306e\u7b56\u5b9a<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-55\">Redis Cluster\u306e\u6d3b\u7528\u4e8b\u4f8b\u3068\u5fdc\u7528\u30d1\u30bf\u30fc\u30f3<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-56\">\u5927\u898f\u6a21Web\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u5c0e\u5165\u4e8b\u4f8b<\/a>      <\/li>      <li>        <a href=\"#i-59\">\u30de\u30a4\u30af\u30ed\u30b5\u30fc\u30d3\u30b9\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306b\u304a\u3051\u308b\u6d3b\u7528\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-62\">\u5c06\u6765\u7684\u306a\u62e1\u5f35\u6027\u3092\u8003\u616e\u3057\u305f\u8a2d\u8a08\u306e\u30dd\u30a4\u30f3\u30c8<\/a>      <\/li>    <\/ul>  <\/li><\/ul>\n      <a href=\"#\" class=\"sgb-toc-button js-toc-button\" rel=\"nofollow\" data-open-dialog=\"true\"><i class=\"fa fa-list\"><\/i><span class=\"sgb-toc-button__text\">\u76ee\u6b21\u3078<\/span><\/a>\n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">Redis Cluster\u3068\u306f\uff1a\u5206\u6563\u30ad\u30e3\u30c3\u30b7\u30e5\u30b7\u30b9\u30c6\u30e0\u306e\u9769\u65b0\u7684\u30a2\u30d7\u30ed\u30fc\u30c1<\/h2>\n\n\n\n<p>Redis Cluster\u306f\u3001\u5927\u898f\u6a21\u306a\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u3092\u8907\u6570\u306e\u30ce\u30fc\u30c9\u306b\u5206\u6563\u3055\u305b\u3066\u7ba1\u7406\u3059\u308b\u3001Redis\u306e\u5206\u6563\u30b7\u30b9\u30c6\u30e0\u5b9f\u88c5\u3067\u3059\u3002\u5358\u4e00\u306eRedis\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u5236\u9650\u3092\u8d85\u3048\u3066\u3001\u6c34\u5e73\u65b9\u5411\u306b\u30b9\u30b1\u30fc\u30eb\u30a2\u30a6\u30c8\u3059\u308b\u3053\u3068\u3092\u53ef\u80fd\u306b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">\u5f93\u6765\u306eRedis\u3068\u6bd4\u8f03\u3057\u305f\u969b\u306eCluster\u306e\u7279\u5fb4\u3068\u5229\u70b9<\/h3>\n\n\n\n<p>\u5f93\u6765\u306eRedis\u3068Cluster\u7248\u306e\u4e3b\u306a\u9055\u3044\u3092\u4ee5\u4e0b\u306e\u8868\u3067\u6bd4\u8f03\u3057\u3066\u307f\u307e\u3057\u3087\u3046\uff1a<\/p>\n\n\n<div id=\"id-0b291009-e091-4a74-91ec-56c104086470\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u7279\u5fb4<\/th><th>\u5f93\u6765\u306eRedis<\/th><th>Redis Cluster<\/th><\/tr><\/thead><tbody><tr><td>\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3<\/td><td>\u5782\u76f4\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\uff08\u30e1\u30e2\u30ea\u5897\u8a2d\uff09<\/td><td>\u6c34\u5e73\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\uff08\u30ce\u30fc\u30c9\u8ffd\u52a0\uff09<\/td><\/tr><tr><td>\u30c7\u30fc\u30bf\u5206\u6563<\/td><td>\u5358\u4e00\u30ce\u30fc\u30c9\u307e\u305f\u306f\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3<\/td><td>\u30b7\u30e3\u30fc\u30c7\u30a3\u30f3\u30b0\u306b\u3088\u308b\u81ea\u52d5\u5206\u6563<\/td><\/tr><tr><td>\u53ef\u7528\u6027<\/td><td>\u30de\u30b9\u30bf\u30fc\u30fb\u30b9\u30ec\u30fc\u30d6\u69cb\u6210<\/td><td>\u30de\u30eb\u30c1\u30de\u30b9\u30bf\u30fc\u69cb\u6210<\/td><\/tr><tr><td>\u6574\u5408\u6027\u4fdd\u8a3c<\/td><td>\u5f37\u3044\u6574\u5408\u6027<\/td><td>\u7d50\u679c\u6574\u5408\u6027<\/td><\/tr><tr><td>\u8a2d\u5b9a\u306e\u8907\u96d1\u3055<\/td><td>\u6bd4\u8f03\u7684\u30b7\u30f3\u30d7\u30eb<\/td><td>\u3088\u308a\u8907\u96d1\u306a\u8a2d\u5b9a\u304c\u5fc5\u8981<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p>Redis Cluster\u306e\u4e3b\u306a\u5229\u70b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u9ad8\u53ef\u7528\u6027<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30ce\u30fc\u30c9\u969c\u5bb3\u6642\u306e\u81ea\u52d5\u30d5\u30a7\u30a4\u30eb\u30aa\u30fc\u30d0\u30fc<\/li>\n\n\n\n<li>\u30de\u30eb\u30c1\u30de\u30b9\u30bf\u30fc\u69cb\u6210\u306b\u3088\u308b\u8ca0\u8377\u5206\u6563<\/li>\n\n\n\n<li>\u30af\u30e9\u30b9\u30bf\u30fc\u5168\u4f53\u3067\u306e\u5197\u9577\u6027\u78ba\u4fdd<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6700\u59271000\u30ce\u30fc\u30c9\u307e\u3067\u306e\u30af\u30e9\u30b9\u30bf\u30fc\u69cb\u6210\u304c\u53ef\u80fd<\/li>\n\n\n\n<li>\u30aa\u30f3\u30e9\u30a4\u30f3\u3067\u306e\u30ce\u30fc\u30c9\u8ffd\u52a0\u30fb\u524a\u9664<\/li>\n\n\n\n<li>\u52d5\u7684\u306a\u30c7\u30fc\u30bf\u518d\u914d\u5206<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u904b\u7528\u306e\u67d4\u8edf\u6027<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6bb5\u968e\u7684\u306a\u5bb9\u91cf\u62e1\u5f35\u304c\u53ef\u80fd<\/li>\n\n\n\n<li>\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u6642\u306e\u90e8\u5206\u7684\u306a\u505c\u6b62\u5bfe\u5fdc<\/li>\n\n\n\n<li>\u5730\u7406\u7684\u5206\u6563\u914d\u7f6e\u306e\u30b5\u30dd\u30fc\u30c8<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u3068\u30d5\u30a9\u30fc\u30eb\u30c8\u30c8\u30ec\u30e9\u30f3\u30b9\u306e\u4ed5\u7d44\u307f<\/h3>\n\n\n\n<p>Redis Cluster\u306f\u300116384\u500b\u306e\u30b9\u30ed\u30c3\u30c8\u3092\u4f7f\u7528\u3057\u3066\u30c7\u30fc\u30bf\u3092\u5206\u6563\u7ba1\u7406\u3057\u307e\u3059\u3002\u3053\u306e\u4ed5\u7d44\u307f\u306b\u3064\u3044\u3066\u8a73\u3057\u304f\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-3\">\u30cf\u30c3\u30b7\u30e5\u30b9\u30ed\u30c3\u30c8\u306e\u6982\u5ff5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30ad\u30fc\u306e\u30cf\u30c3\u30b7\u30e5\u30b9\u30ed\u30c3\u30c8\u8a08\u7b97\u4f8b\n$key = \"user:1001\";\n$slot = crc16($key) % 16384;  \/\/ 0-16383\u306e\u5024\u306b\u5206\u6563<\/pre>\n\n\n\n<p>\u30c7\u30fc\u30bf\u306e\u5206\u6563\u30e1\u30ab\u30cb\u30ba\u30e0\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30b7\u30e3\u30fc\u30c7\u30a3\u30f3\u30b0\u51e6\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5404\u30ad\u30fc\u306f\u30cf\u30c3\u30b7\u30e5\u95a2\u6570\u306b\u3088\u3063\u3066\u7279\u5b9a\u306e\u30b9\u30ed\u30c3\u30c8\u306b\u5272\u308a\u5f53\u3066<\/li>\n\n\n\n<li>\u30b9\u30ed\u30c3\u30c8\u306f\u5404\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306b\u5206\u914d<\/li>\n\n\n\n<li>\u30ad\u30fc\u64cd\u4f5c\u306f\u9069\u5207\u306a\u30ce\u30fc\u30c9\u306b\u81ea\u52d5\u7684\u306b\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d5\u30a9\u30fc\u30eb\u30c8\u30c8\u30ec\u30e9\u30f3\u30b9<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5404\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306b1\u3064\u4ee5\u4e0a\u306e\u30ec\u30d7\u30ea\u30ab\u3092\u914d\u7f6e<\/li>\n\n\n\n<li>\u30ce\u30fc\u30c9\u9593\u3067\u306e\u5b9a\u671f\u7684\u306aheartbeat\u78ba\u8a8d<\/li>\n\n\n\n<li>\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u969c\u5bb3\u6642\u306e\u81ea\u52d5\u30d5\u30a7\u30a4\u30eb\u30aa\u30fc\u30d0\u30fc<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30af\u30e9\u30b9\u30bf\u30fc\u7ba1\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30ce\u30fc\u30c9\u9593\u3067\u306e\u30b4\u30b7\u30c3\u30d7\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u306b\u3088\u308b\u72b6\u614b\u540c\u671f<\/li>\n\n\n\n<li>\u30b9\u30d7\u30ea\u30c3\u30c8\u30d6\u30ec\u30a4\u30f3\u9632\u6b62\u306e\u305f\u3081\u306e\u904e\u534a\u6570\u5408\u610f\u65b9\u5f0f<\/li>\n\n\n\n<li>\u81ea\u52d5\u7684\u306a\u30af\u30e9\u30b9\u30bf\u30fc\u30c8\u30dd\u30ed\u30b8\u30fc\u306e\u518d\u69cb\u6210<\/li>\n<\/ul>\n\n\n\n<p>\u5b9f\u88c5\u4f8b\uff1a\u57fa\u672c\u7684\u306a\u30af\u30e9\u30b9\u30bf\u30fc\u63a5\u7d9a\u8a2d\u5b9a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ Redis Cluster\u63a5\u7d9a\u306e\u57fa\u672c\u5b9f\u88c5\u4f8b\n$nodes = [\n    'redis-node1:6379',\n    'redis-node2:6379',\n    'redis-node3:6379'\n];\n\ntry {\n    $redisCluster = new RedisCluster(null, $nodes, 1.5, 1.5, true, null);\n\n    \/\/ \u30af\u30e9\u30b9\u30bf\u30fc\u306e\u72b6\u614b\u78ba\u8a8d\n    $clusterInfo = $redisCluster-&gt;info();\n\n    \/\/ \u30ad\u30fc\u306e\u64cd\u4f5c\u306f\u30ce\u30fc\u30c9\u3092\u610f\u8b58\u305b\u305a\u306b\u5b9f\u884c\u53ef\u80fd\n    $redisCluster-&gt;set('user:1001', json_encode(['name' =&gt; 'Test User']));\n    $userData = $redisCluster-&gt;get('user:1001');\n\n} catch (RedisClusterException $e) {\n    error_log('Redis Cluster\u63a5\u7d9a\u30a8\u30e9\u30fc: ' . $e-&gt;getMessage());\n}<\/pre>\n\n\n\n<p>\u3053\u306e\u3088\u3046\u306a\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306b\u3088\u308a\u3001Redis Cluster\u306f\u9ad8\u3044\u53ef\u7528\u6027\u3068\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u3092\u5b9f\u73fe\u3057\u3066\u3044\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3088\u308a\u8a73\u7d30\u306a\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u89e3\u8aac\u3068\u3001\u5b9f\u969b\u306e\u904b\u7528\u65b9\u6cd5\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-4\">Redis Cluster\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u8a73\u89e3<\/h2>\n\n\n\n<p>Redis Cluster\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306f\u3001\u5206\u6563\u30b7\u30b9\u30c6\u30e0\u306e\u4fe1\u983c\u6027\u3068\u62e1\u5f35\u6027\u3092\u5b9f\u73fe\u3059\u308b\u305f\u3081\u306b\u7dbf\u5bc6\u306b\u8a2d\u8a08\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u3053\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u305d\u306e\u8a73\u7d30\u306a\u69cb\u9020\u3068\u52d5\u4f5c\u539f\u7406\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">\u30de\u30b9\u30bf\u30fc\u30fb\u30b9\u30ec\u30fc\u30d6\u30ce\u30fc\u30c9\u306e\u5f79\u5272\u3068\u95a2\u4fc2\u6027<\/h3>\n\n\n\n<p>Redis Cluster\u306b\u304a\u3051\u308b\u30ce\u30fc\u30c9\u306e\u5f79\u5272\u5206\u62c5\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u306e\u4fe1\u983c\u6027\u3092\u78ba\u4fdd\u3059\u308b\u4e0a\u3067\u91cd\u8981\u306a\u8981\u7d20\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-6\">\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306e\u8cac\u52d9<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30d7\u30e9\u30a4\u30de\u30ea\u30c7\u30fc\u30bf\u306e\u4fdd\u6301\u3068\u7ba1\u7406<\/li>\n\n\n\n<li>\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u306e\u53d7\u4ed8\u3068\u5b9f\u884c<\/li>\n\n\n\n<li>\u30b9\u30ec\u30fc\u30d6\u30ce\u30fc\u30c9\u3078\u306e\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3<\/li>\n\n\n\n<li>\u30af\u30e9\u30b9\u30bf\u30fc\u69cb\u6210\u60c5\u5831\u306e\u7ba1\u7406<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-7\">\u30b9\u30ec\u30fc\u30d6\u30ce\u30fc\u30c9\u306e\u8cac\u52d9<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306e\u30c7\u30fc\u30bf\u8907\u88fd<\/li>\n\n\n\n<li>\u8aad\u307f\u53d6\u308a\u64cd\u4f5c\u306e\u8ca0\u8377\u5206\u6563<\/li>\n\n\n\n<li>\u30d5\u30a7\u30a4\u30eb\u30aa\u30fc\u30d0\u30fc\u6642\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7<\/li>\n\n\n\n<li>\u30af\u30e9\u30b9\u30bf\u30fc\u72b6\u614b\u306e\u76e3\u8996<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u30de\u30b9\u30bf\u30fc\u30fb\u30b9\u30ec\u30fc\u30d6\u69cb\u6210\u306e\u78ba\u8a8d\u4f8b\n$cluster = new RedisCluster(null, ['localhost:6379']);\n\n\/\/ \u30af\u30e9\u30b9\u30bf\u30fc\u5185\u306e\u5168\u30ce\u30fc\u30c9\u60c5\u5831\u53d6\u5f97\n$nodes = $cluster-&gt;_masters();\nforeach ($nodes as $node) {\n    \/\/ \u30ce\u30fc\u30c9\u306e\u5f79\u5272\u3068\u72b6\u614b\u3092\u78ba\u8a8d\n    $info = $cluster-&gt;info($node);\n    $role = $info['role'];\n    $connected_slaves = $info['connected_slaves'] ?? 0;\n\n    echo \"Node: {$node}\\n\";\n    echo \"Role: {$role}\\n\";\n    echo \"Connected slaves: {$connected_slaves}\\n\";\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u30b7\u30e3\u30fc\u30c7\u30a3\u30f3\u30b0\u306e\u4ed5\u7d44\u307f\u3068\u52b9\u679c\u7684\u306a\u30c7\u30fc\u30bf\u5206\u6563\u65b9\u6cd5<\/h3>\n\n\n\n<p>Redis Cluster\u3067\u306f\u3001CRC16\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3092\u4f7f\u7528\u3057\u3066\u30ad\u30fc\u3092\u30cf\u30c3\u30b7\u30e5\u30b9\u30ed\u30c3\u30c8\u306b\u5272\u308a\u5f53\u3066\u307e\u3059\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-9\">\u30cf\u30c3\u30b7\u30e5\u30b9\u30ed\u30c3\u30c8\u306e\u5272\u308a\u5f53\u3066\u65b9\u5f0f<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u30cf\u30c3\u30b7\u30e5\u30bf\u30b0\u3092\u4f7f\u7528\u3057\u305f\u30ad\u30fc\u8a2d\u5b9a\u4f8b\nclass RedisClusterKeyManager {\n    private $cluster;\n\n    public function __construct(array $nodes) {\n        $this-&gt;cluster = new RedisCluster(null, $nodes);\n    }\n\n    public function setUserData($userId, $data) {\n        \/\/ \u30cf\u30c3\u30b7\u30e5\u30bf\u30b0\u3092\u4f7f\u7528\u3057\u3066\u540c\u4e00\u30b9\u30ed\u30c3\u30c8\u306b\u4fdd\u5b58\n        $key = \"user:{$userId}\";  \/\/ {user}\u304c\u30cf\u30c3\u30b7\u30e5\u30bf\u30b0\u3068\u3057\u3066\u6a5f\u80fd\n        $this-&gt;cluster-&gt;set($key, json_encode($data));\n\n        \/\/ \u95a2\u9023\u30c7\u30fc\u30bf\u3082\u540c\u3058\u30b9\u30ed\u30c3\u30c8\u306b\u4fdd\u5b58\n        $this-&gt;cluster-&gt;set(\"user:{$userId}:profile\", json_encode($data['profile']));\n        $this-&gt;cluster-&gt;set(\"user:{$userId}:settings\", json_encode($data['settings']));\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-10\">\u52b9\u679c\u7684\u306a\u30c7\u30fc\u30bf\u5206\u6563\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30cf\u30c3\u30b7\u30e5\u30bf\u30b0\u306e\u6d3b\u7528<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u95a2\u9023\u30c7\u30fc\u30bf\u306e\u540c\u4e00\u30ce\u30fc\u30c9\u914d\u7f6e<\/li>\n\n\n\n<li>\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u306e\u52b9\u7387\u5316<\/li>\n\n\n\n<li>\u30af\u30a8\u30ea\u306e\u6700\u9069\u5316<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30ad\u30fc\u8a2d\u8a08\u306e\u6307\u91dd<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u660e\u78ba\u306a\u547d\u540d\u898f\u5247\u306e\u63a1\u7528<\/li>\n\n\n\n<li>\u30c7\u30fc\u30bf\u30a2\u30af\u30bb\u30b9\u30d1\u30bf\u30fc\u30f3\u306e\u8003\u616e<\/li>\n\n\n\n<li>\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u3092\u8003\u616e\u3057\u305f\u8a2d\u8a08<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-11\">\u30af\u30e9\u30b9\u30bf\u30fc\u30c8\u30dd\u30ed\u30b8\u30fc\u306e\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3<\/h3>\n\n\n\n<p>Redis Cluster\u306e\u30c8\u30dd\u30ed\u30b8\u30fc\u8a2d\u8a08\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u306e\u8981\u4ef6\u306b\u5fdc\u3058\u3066\u9069\u5207\u306b\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-12\">\u57fa\u672c\u7684\u306a\u30c8\u30dd\u30ed\u30b8\u30fc\u30d1\u30bf\u30fc\u30f3<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u6700\u5c0f\u69cb\u6210\uff083\u30de\u30b9\u30bf\u30fc \u00d7 3\u30b9\u30ec\u30fc\u30d6\uff09<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   Master A \u2190\u2192 Slave A'\n   Master B \u2190\u2192 Slave B'\n   Master C \u2190\u2192 Slave C'<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u4e2d\u898f\u6a21\u69cb\u6210\uff086\u30de\u30b9\u30bf\u30fc \u00d7 6\u30b9\u30ec\u30fc\u30d6\uff09<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   &lt;?php\n   \/\/ \u4e2d\u898f\u6a21\u30af\u30e9\u30b9\u30bf\u30fc\u69cb\u6210\u4f8b\n   $nodes = [\n       'redis-master-1:6379',  \/\/ DC1 \u30d7\u30e9\u30a4\u30de\u30ea\n       'redis-master-2:6379',  \/\/ DC1 \u30d7\u30e9\u30a4\u30de\u30ea\n       'redis-master-3:6379',  \/\/ DC1 \u30d7\u30e9\u30a4\u30de\u30ea\n       'redis-master-4:6379',  \/\/ DC2 \u30d7\u30e9\u30a4\u30de\u30ea\n       'redis-master-5:6379',  \/\/ DC2 \u30d7\u30e9\u30a4\u30de\u30ea\n       'redis-master-6:6379',  \/\/ DC2 \u30d7\u30e9\u30a4\u30de\u30ea\n   ];\n\n   $options = [\n       'timeout' =&gt; 1.5,\n       'read_timeout' =&gt; 1.5,\n       'persistent' =&gt; true\n   ];\n\n   $cluster = new RedisCluster(null, $nodes, \n       $options['timeout'],\n       $options['read_timeout'],\n       $options['persistent']\n   );<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-13\">\u5730\u7406\u5206\u6563\u30d1\u30bf\u30fc\u30f3<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u5730\u7406\u5206\u6563\u69cb\u6210\u3067\u306e\u63a5\u7d9a\u8a2d\u5b9a\u4f8b\n$config = [\n    'dc1' =&gt; [\n        'masters' =&gt; ['dc1-master1:6379', 'dc1-master2:6379'],\n        'slaves' =&gt; ['dc1-slave1:6379', 'dc1-slave2:6379']\n    ],\n    'dc2' =&gt; [\n        'masters' =&gt; ['dc2-master1:6379', 'dc2-master2:6379'],\n        'slaves' =&gt; ['dc2-slave1:6379', 'dc2-slave2:6379']\n    ]\n];\n\n\/\/ \u5730\u57df\u3054\u3068\u306e\u63a5\u7d9a\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u7ba1\u7406\n$clusters = [];\nforeach ($config as $dc =&gt; $nodes) {\n    $allNodes = array_merge($nodes['masters'], $nodes['slaves']);\n    $clusters[$dc] = new RedisCluster(null, $allNodes);\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-14\">\u30c8\u30dd\u30ed\u30b8\u30fc\u8a2d\u8a08\u306e\u8003\u616e\u70b9<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u53ef\u7528\u6027\u8981\u4ef6<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5fc5\u8981\u306a\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u6570<\/li>\n\n\n\n<li>\u30d5\u30a7\u30a4\u30eb\u30aa\u30fc\u30d0\u30fc\u6642\u306e\u5f71\u97ff\u7bc4\u56f2<\/li>\n\n\n\n<li>\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u9593\u306e\u5197\u9577\u6027<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u8981\u4ef6<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30ec\u30a4\u30c6\u30f3\u30b7\u30fc\u306e\u5236\u7d04<\/li>\n\n\n\n<li>\u30b9\u30eb\u30fc\u30d7\u30c3\u30c8\u306e\u76ee\u6a19<\/li>\n\n\n\n<li>\u30ea\u30bd\u30fc\u30b9\u4f7f\u7528\u52b9\u7387<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u904b\u7528\u7ba1\u7406\u306e\u5bb9\u6613\u3055<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u76e3\u8996\u306e\u8907\u96d1\u3055<\/li>\n\n\n\n<li>\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u6027<\/li>\n\n\n\n<li>\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u306e\u67d4\u8edf\u6027<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u8a2d\u8a08\u306e\u77e5\u8b58\u306f\u3001\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u8aac\u660e\u3059\u308b\u5b9f\u969b\u306e\u74b0\u5883\u69cb\u7bc9\u3068\u5b9f\u88c5\u306b\u304a\u3044\u3066\u91cd\u8981\u306a\u57fa\u790e\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-15\">PHP\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306eRedis Cluster\u74b0\u5883\u69cb\u7bc9<\/h2>\n\n\n\n<p>PHP\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067Redis Cluster\u3092\u69cb\u7bc9\u3059\u308b\u969b\u306e\u5177\u4f53\u7684\u306a\u624b\u9806\u3068\u3001\u5b9f\u88c5\u6642\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u5fc5\u8981\u306a\u62e1\u5f35\u6a5f\u80fd\u3068\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-17\">1. PHP\u306eRedis\u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/h4>\n\n\n\n<p>Ubuntu\u306e\u5834\u5408:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u4f9d\u5b58\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nsudo apt-get update\nsudo apt-get install php-dev php-pear build-essential\n\n# Redis\u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nsudo pecl install redis\n\n# PHP\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306bRedis\u62e1\u5f35\u3092\u8ffd\u52a0\necho \"extension=redis.so\" | sudo tee \/etc\/php\/7.4\/mods-available\/redis.ini\nsudo phpenmod redis<\/pre>\n\n\n\n<p>MacOS\u306e\u5834\u5408:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">brew install php@7.4\npecl install redis<\/pre>\n\n\n\n<p>Docker\u306e\u5834\u5408:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FROM php:7.4-fpm\n\nRUN pecl install redis \\\n    &amp;&amp; docker-php-ext-enable redis<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-18\">2. Composer\u306b\u3088\u308b\u4f9d\u5b58\u95a2\u4fc2\u306e\u7ba1\u7406<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">composer require predis\/predis<\/pre>\n\n\n\n<p><code>composer.json<\/code>\u306e\u8a2d\u5b9a\u4f8b:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n    \"require\": {\n        \"predis\/predis\": \"^2.0\",\n        \"php\": \"&gt;=7.4\"\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-19\">\u57fa\u672c\u7684\u306a\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u89e3\u8aac\u3068\u6700\u9069\u5316\u306e\u30dd\u30a4\u30f3\u30c8<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-20\">Redis Cluster\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\uff08redis.conf\uff09<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u57fa\u672c\u8a2d\u5b9a\nport 6379\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 5000\nappendonly yes\n\n# \u30e1\u30e2\u30ea\u8a2d\u5b9a\nmaxmemory 4gb\nmaxmemory-policy allkeys-lru\n\n# \u6c38\u7d9a\u5316\u8a2d\u5b9a\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u8a2d\u5b9a\nbind 0.0.0.0\nprotected-mode yes<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-21\">PHP\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5074\u306e\u8a2d\u5b9a<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ config\/redis.php\n\nreturn [\n    'cluster' =&gt; [\n        'enabled' =&gt; true,\n        'nodes' =&gt; [\n            ['host' =&gt; 'redis-node1', 'port' =&gt; 6379],\n            ['host' =&gt; 'redis-node2', 'port' =&gt; 6379],\n            ['host' =&gt; 'redis-node3', 'port' =&gt; 6379],\n        ],\n        'options' =&gt; [\n            'cluster' =&gt; 'redis',\n            'prefix' =&gt; 'app:',\n            'parameters' =&gt; [\n                'password' =&gt; env('REDIS_PASSWORD', null),\n                'database' =&gt; 0,\n                'timeout' =&gt; 1.5,\n                'read_timeout' =&gt; 1.5,\n                'retry_interval' =&gt; 100\n            ]\n        ]\n    ]\n];<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-22\">Redis\u30af\u30e9\u30b9\u30bf\u30fcManager\u30af\u30e9\u30b9\u306e\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\nnamespace App\\Services;\n\nuse RedisCluster;\nuse RedisClusterException;\n\nclass RedisClusterManager\n{\n    private ?RedisCluster $cluster = null;\n    private array $config;\n    private array $options;\n\n    public function __construct(array $config)\n    {\n        $this-&gt;config = $config;\n        $this-&gt;options = $config['options'] ?? [];\n        $this-&gt;initializeCluster();\n    }\n\n    private function initializeCluster(): void\n    {\n        try {\n            $nodes = array_map(function ($node) {\n                return $node['host'] . ':' . $node['port'];\n            }, $this-&gt;config['nodes']);\n\n            $this-&gt;cluster = new RedisCluster(\n                null,\n                $nodes,\n                $this-&gt;options['timeout'] ?? 1.5,\n                $this-&gt;options['read_timeout'] ?? 1.5,\n                true,\n                $this-&gt;options['parameters']['password'] ?? null\n            );\n\n            \/\/ \u30af\u30e9\u30b9\u30bf\u30fc\u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u8a2d\u5b9a\n            $this-&gt;cluster-&gt;setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_ERROR);\n\n        } catch (RedisClusterException $e) {\n            throw new \\RuntimeException('Redis Cluster\u521d\u671f\u5316\u30a8\u30e9\u30fc: ' . $e-&gt;getMessage());\n        }\n    }\n\n    public function getCluster(): RedisCluster\n    {\n        if ($this-&gt;cluster === null) {\n            $this-&gt;initializeCluster();\n        }\n        return $this-&gt;cluster;\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-23\">\u30af\u30e9\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u306e\u8ffd\u52a0\u3068\u524a\u9664\u306e\u5b9f\u8df5\u7684\u306a\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-24\">1. \u30ce\u30fc\u30c9\u8ffd\u52a0\u624b\u9806<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u65b0\u898f\u30ce\u30fc\u30c9\u306e\u8d77\u52d5\nredis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf\n\n# \u30af\u30e9\u30b9\u30bf\u30fc\u3078\u306e\u30ce\u30fc\u30c9\u8ffd\u52a0\nredis-cli --cluster add-node \u65b0\u30ce\u30fc\u30c9IP:6379 \u65e2\u5b58\u30ce\u30fc\u30c9IP:6379\n\n# \u30b9\u30ed\u30c3\u30c8\u306e\u518d\u5206\u6563\nredis-cli --cluster reshard \u65e2\u5b58\u30ce\u30fc\u30c9IP:6379<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-25\">PHP\u3067\u306e\u30ce\u30fc\u30c9\u7ba1\u7406\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass ClusterNodeManager\n{\n    private RedisCluster $cluster;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n    }\n\n    public function addNode(string $newNodeHost, int $port): bool\n    {\n        try {\n            \/\/ \u30ce\u30fc\u30c9\u306e\u72b6\u614b\u78ba\u8a8d\n            $masters = $this-&gt;cluster-&gt;_masters();\n            if (empty($masters)) {\n                throw new \\RuntimeException('\u30de\u30b9\u30bf\u30fc\u30ce\u30fc\u30c9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093');\n            }\n\n            \/\/ \u65b0\u30ce\u30fc\u30c9\u306e\u8ffd\u52a0\u51e6\u7406\n            $result = $this-&gt;cluster-&gt;rawCommand(\n                $masters[0],\n                'CLUSTER',\n                'MEET',\n                $newNodeHost,\n                $port\n            );\n\n            return $result === 'OK';\n        } catch (\\Exception $e) {\n            error_log('\u30ce\u30fc\u30c9\u8ffd\u52a0\u30a8\u30e9\u30fc: ' . $e-&gt;getMessage());\n            return false;\n        }\n    }\n\n    public function redistributeSlots(string $targetNode, int $slotCount): bool\n    {\n        try {\n            \/\/ \u30b9\u30ed\u30c3\u30c8\u306e\u518d\u5206\u914d\u30ed\u30b8\u30c3\u30af\n            $masters = $this-&gt;cluster-&gt;_masters();\n            $slotsPerNode = floor(16384 \/ count($masters));\n\n            \/\/ ... \u30b9\u30ed\u30c3\u30c8\u518d\u5206\u914d\u306e\u5b9f\u88c5 ...\n\n            return true;\n        } catch (\\Exception $e) {\n            error_log('\u30b9\u30ed\u30c3\u30c8\u518d\u5206\u914d\u30a8\u30e9\u30fc: ' . $e-&gt;getMessage());\n            return false;\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-26\">\u904b\u7528\u4e0a\u306e\u6ce8\u610f\u70b9<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u6bb5\u968e\u7684\u306a\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4e00\u5ea6\u306b\u591a\u6570\u306e\u30ce\u30fc\u30c9\u3092\u8ffd\u52a0\u3057\u306a\u3044<\/li>\n\n\n\n<li>\u30b9\u30ed\u30c3\u30c8\u518d\u5206\u6563\u306e\u5f71\u97ff\u3092\u76e3\u8996<\/li>\n\n\n\n<li>\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u4e8b\u524d\u306b\u53d6\u5f97<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3078\u306e\u914d\u616e<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30d4\u30fc\u30af\u6642\u3092\u907f\u3051\u305f\u4f5c\u696d\u5b9f\u65bd<\/li>\n\n\n\n<li>\u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u306e\u76e3\u8996<\/li>\n\n\n\n<li>\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5e2f\u57df\u306e\u78ba\u4fdd<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d5\u30a7\u30a4\u30eb\u30aa\u30fc\u30d0\u30fc\u8a2d\u5b9a<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u5024\u306e\u9069\u5207\u306a\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u76e3\u8996\u306e\u4ed5\u7d44\u307f\u306e\u78ba\u8a8d<\/li>\n\n\n\n<li>\u81ea\u52d5\u5fa9\u65e7\u306e\u691c\u8a3c<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u306e\u74b0\u5883\u69cb\u7bc9\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u8aac\u660e\u3059\u308b\u5b9f\u88c5\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u306b\u9032\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-27\">PHP\u3067\u306eRedis Cluster\u5b9f\u88c5\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h2>\n\n\n\n<p>\u5927\u898f\u6a21\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067Redis Cluster\u3092\u52b9\u7387\u7684\u306b\u6d3b\u7528\u3059\u308b\u305f\u3081\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3068\u5b9f\u88c5\u30d1\u30bf\u30fc\u30f3\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-28\">\u52b9\u7387\u7684\u306a\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u30d7\u30fc\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-29\">\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u30d7\u30fc\u30eb\u30de\u30cd\u30fc\u30b8\u30e3\u30fc\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Redis;\n\nclass RedisClusterPool\n{\n    private static ?RedisClusterPool $instance = null;\n    private array $connections = [];\n    private array $config;\n    private int $maxConnections;\n\n    private function __construct(array $config, int $maxConnections = 10)\n    {\n        $this-&gt;config = $config;\n        $this-&gt;maxConnections = $maxConnections;\n    }\n\n    public static function getInstance(array $config): self\n    {\n        if (self::$instance === null) {\n            self::$instance = new self($config);\n        }\n        return self::$instance;\n    }\n\n    public function getConnection(): RedisCluster\n    {\n        \/\/ \u5229\u7528\u53ef\u80fd\u306a\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u3092\u63a2\u3059\n        foreach ($this-&gt;connections as $key =&gt; $conn) {\n            if (!$this-&gt;isConnectionBusy($conn)) {\n                return $conn;\n            }\n        }\n\n        \/\/ \u65b0\u3057\u3044\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u306e\u4f5c\u6210\n        if (count($this-&gt;connections) &lt; $this-&gt;maxConnections) {\n            $connection = $this-&gt;createNewConnection();\n            $this-&gt;connections[] = $connection;\n            return $connection;\n        }\n\n        \/\/ \u63a5\u7d9a\u6570\u4e0a\u9650\u306b\u9054\u3057\u305f\u5834\u5408\u306f\u5f85\u6a5f\n        throw new \\RuntimeException('\u63a5\u7d9a\u30d7\u30fc\u30eb\u304c\u6e80\u676f\u3067\u3059\u3002\u3057\u3070\u3089\u304f\u5f85\u3063\u3066\u304b\u3089\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    }\n\n    private function createNewConnection(): RedisCluster\n    {\n        $nodes = array_map(function ($node) {\n            return $node['host'] . ':' . $node['port'];\n        }, $this-&gt;config['nodes']);\n\n        return new RedisCluster(\n            null,\n            $nodes,\n            $this-&gt;config['timeout'] ?? 1.5,\n            $this-&gt;config['read_timeout'] ?? 1.5,\n            true,\n            $this-&gt;config['password'] ?? null\n        );\n    }\n\n    private function isConnectionBusy(RedisCluster $connection): bool\n    {\n        try {\n            $connection-&gt;ping();\n            return false;\n        } catch (\\RedisClusterException $e) {\n            return true;\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-30\">\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u4f7f\u7528\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u4f7f\u7528\u4f8b\n$config = [\n    'nodes' =&gt; [\n        ['host' =&gt; 'redis-1', 'port' =&gt; 6379],\n        ['host' =&gt; 'redis-2', 'port' =&gt; 6379],\n        ['host' =&gt; 'redis-3', 'port' =&gt; 6379]\n    ],\n    'timeout' =&gt; 1.5,\n    'read_timeout' =&gt; 1.5,\n    'password' =&gt; 'your_password'\n];\n\ntry {\n    $pool = RedisClusterPool::getInstance($config);\n    $redis = $pool-&gt;getConnection();\n\n    \/\/ Redis\u306e\u64cd\u4f5c\u3092\u5b9f\u884c\n    $redis-&gt;set('key', 'value');\n    $value = $redis-&gt;get('key');\n\n} catch (\\Exception $e) {\n    \/\/ \u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\n    error_log('Redis\u64cd\u4f5c\u30a8\u30e9\u30fc: ' . $e-&gt;getMessage());\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-31\">\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u3068\u6574\u5408\u6027\u306e\u78ba\u4fdd<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-32\">\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u30de\u30cd\u30fc\u30b8\u30e3\u30fc\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass RedisClusterTransaction\n{\n    private RedisCluster $cluster;\n    private array $operations = [];\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n    }\n\n    public function addOperation(string $command, array $args): self\n    {\n        $this-&gt;operations[] = [\n            'command' =&gt; $command,\n            'args' =&gt; $args\n        ];\n        return $this;\n    }\n\n    public function execute(): array\n    {\n        try {\n            \/\/ \u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u958b\u59cb\n            $this-&gt;cluster-&gt;multi();\n\n            \/\/ \u64cd\u4f5c\u306e\u5b9f\u884c\n            foreach ($this-&gt;operations as $op) {\n                $this-&gt;cluster-&gt;{$op['command']}(...$op['args']);\n            }\n\n            \/\/ \u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u30b3\u30df\u30c3\u30c8\n            $results = $this-&gt;cluster-&gt;exec();\n\n            return [\n                'success' =&gt; true,\n                'results' =&gt; $results\n            ];\n\n        } catch (\\RedisClusterException $e) {\n            \/\/ \u30a8\u30e9\u30fc\u767a\u751f\u6642\u306f\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\n            $this-&gt;cluster-&gt;discard();\n\n            return [\n                'success' =&gt; false,\n                'error' =&gt; $e-&gt;getMessage()\n            ];\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-33\">\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u306e\u4f7f\u7528\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u30e6\u30fc\u30b6\u30fc\u30dd\u30a4\u30f3\u30c8\u66f4\u65b0\u306e\u4f8b\nfunction updateUserPoints(RedisCluster $cluster, string $userId, int $points): bool\n{\n    $transaction = new RedisClusterTransaction($cluster);\n\n    try {\n        $result = $transaction\n            -&gt;addOperation('hIncrBy', [\"user:{$userId}\", 'points', $points])\n            -&gt;addOperation('zIncrBy', ['user_ranking', $points, $userId])\n            -&gt;addOperation('hSet', [\"user:{$userId}\", 'last_updated', time()])\n            -&gt;execute();\n\n        return $result['success'];\n\n    } catch (\\Exception $e) {\n        error_log(\"\u30dd\u30a4\u30f3\u30c8\u66f4\u65b0\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n        return false;\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-34\">\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3068\u30ea\u30c8\u30e9\u30a4\u30e1\u30ab\u30cb\u30ba\u30e0<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-35\">\u30ea\u30c8\u30e9\u30a4\u53ef\u80fd\u306a\u64cd\u4f5c\u306e\u30e9\u30c3\u30d1\u30fc\u30af\u30e9\u30b9<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass RedisClusterRetry\n{\n    private RedisCluster $cluster;\n    private int $maxRetries;\n    private int $retryDelay;\n\n    public function __construct(\n        RedisCluster $cluster,\n        int $maxRetries = 3,\n        int $retryDelay = 100\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;maxRetries = $maxRetries;\n        $this-&gt;retryDelay = $retryDelay;\n    }\n\n    public function execute(callable $operation)\n    {\n        $attempts = 0;\n        $lastException = null;\n\n        while ($attempts &lt; $this-&gt;maxRetries) {\n            try {\n                return $operation($this-&gt;cluster);\n            } catch (\\RedisClusterException $e) {\n                $lastException = $e;\n                $attempts++;\n\n                if ($this-&gt;shouldRetry($e)) {\n                    usleep($this-&gt;getBackoffTime($attempts));\n                    continue;\n                }\n\n                throw $e;\n            }\n        }\n\n        throw new \\RuntimeException(\n            \"\u6700\u5927\u30ea\u30c8\u30e9\u30a4\u56de\u6570\u306b\u9054\u3057\u307e\u3057\u305f: {$lastException-&gt;getMessage()}\",\n            0,\n            $lastException\n        );\n    }\n\n    private function shouldRetry(\\RedisClusterException $e): bool\n    {\n        $retryableErrors = [\n            'CLUSTERDOWN',\n            'TRYAGAIN',\n            'MOVED',\n            'ASK'\n        ];\n\n        foreach ($retryableErrors as $error) {\n            if (strpos($e-&gt;getMessage(), $error) !== false) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    private function getBackoffTime(int $attempt): int\n    {\n        \/\/ \u6307\u6570\u30d0\u30c3\u30af\u30aa\u30d5\u306e\u5b9f\u88c5\n        return $this-&gt;retryDelay * pow(2, $attempt - 1);\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-36\">\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3092\u542b\u3080Redis\u64cd\u4f5c\u306e\u4f8b\nclass RedisClusterOperation\n{\n    private RedisClusterRetry $retry;\n    private RedisClusterPool $pool;\n\n    public function __construct(RedisClusterPool $pool)\n    {\n        $this-&gt;pool = $pool;\n        $this-&gt;retry = new RedisClusterRetry($pool-&gt;getConnection());\n    }\n\n    public function setCacheWithRetry(string $key, $value, int $ttl = 3600)\n    {\n        try {\n            return $this-&gt;retry-&gt;execute(function ($redis) use ($key, $value, $ttl) {\n                $success = $redis-&gt;setex($key, $ttl, serialize($value));\n\n                if (!$success) {\n                    throw new \\RuntimeException('\u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u8a2d\u5b9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f');\n                }\n\n                return true;\n            });\n\n        } catch (\\Exception $e) {\n            error_log(\"Redis\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            \/\/ \u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u51e6\u7406\u3084\u30a8\u30e9\u30fc\u901a\u77e5\u306e\u5b9f\u88c5\n            return false;\n        }\n    }\n\n    public function getCacheWithRetry(string $key)\n    {\n        try {\n            return $this-&gt;retry-&gt;execute(function ($redis) use ($key) {\n                $value = $redis-&gt;get($key);\n\n                if ($value === false) {\n                    return null;\n                }\n\n                return unserialize($value);\n            });\n\n        } catch (\\Exception $e) {\n            error_log(\"Redis\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            return null;\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u30d1\u30bf\u30fc\u30f3\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u3088\u308a\u4fe1\u983c\u6027\u306e\u9ad8\u3044Redis Cluster\u64cd\u4f5c\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3053\u308c\u3089\u306e\u5b9f\u88c5\u3092\u30d9\u30fc\u30b9\u306b\u3057\u305f\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-37\">Redis Cluster\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0<\/h2>\n\n\n\n<p>Redis Cluster\u306e\u6027\u80fd\u3092\u6700\u5927\u9650\u306b\u5f15\u304d\u51fa\u3059\u305f\u3081\u306e\u3001\u5177\u4f53\u7684\u306a\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0\u624b\u6cd5\u3068\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u65b9\u6cd5\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-38\">\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316\u3068\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u624b\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-39\">\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u76e3\u8996\u30af\u30e9\u30b9\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Monitoring;\n\nclass RedisMemoryMonitor\n{\n    private RedisCluster $cluster;\n    private array $thresholds;\n\n    public function __construct(RedisCluster $cluster, array $thresholds = [\n        'warning' =&gt; 70,  \/\/ 70%\n        'critical' =&gt; 85  \/\/ 85%\n    ])\n    {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;thresholds = $thresholds;\n    }\n\n    public function getMemoryStats(): array\n    {\n        $stats = [];\n        $masters = $this-&gt;cluster-&gt;_masters();\n\n        foreach ($masters as $master) {\n            $info = $this-&gt;cluster-&gt;info($master);\n\n            $used_memory = $info['used_memory'] ?? 0;\n            $total_memory = $info['total_system_memory'] ?? 0;\n            $usage_percentage = ($used_memory \/ $total_memory) * 100;\n\n            $stats[$master] = [\n                'used_memory' =&gt; $this-&gt;formatBytes($used_memory),\n                'total_memory' =&gt; $this-&gt;formatBytes($total_memory),\n                'usage_percentage' =&gt; round($usage_percentage, 2),\n                'status' =&gt; $this-&gt;getMemoryStatus($usage_percentage),\n                'peak_memory' =&gt; $this-&gt;formatBytes($info['used_memory_peak'] ?? 0),\n                'fragmentation_ratio' =&gt; $info['mem_fragmentation_ratio'] ?? 0\n            ];\n        }\n\n        return $stats;\n    }\n\n    private function getMemoryStatus(float $usage): string\n    {\n        if ($usage &gt;= $this-&gt;thresholds['critical']) {\n            return 'CRITICAL';\n        } elseif ($usage &gt;= $this-&gt;thresholds['warning']) {\n            return 'WARNING';\n        }\n        return 'OK';\n    }\n\n    private function formatBytes(int $bytes): string\n    {\n        $units = ['B', 'KB', 'MB', 'GB', 'TB'];\n        $bytes = max($bytes, 0);\n        $pow = floor(($bytes ? log($bytes) : 0) \/ log(1024));\n        $pow = min($pow, count($units) - 1);\n\n        return round($bytes \/ pow(1024, $pow), 2) . ' ' . $units[$pow];\n    }\n\n    public function getMemoryRecommendations(): array\n    {\n        $recommendations = [];\n        $stats = $this-&gt;getMemoryStats();\n\n        foreach ($stats as $node =&gt; $stat) {\n            if ($stat['fragmentation_ratio'] &gt; 1.5) {\n                $recommendations[] = [\n                    'node' =&gt; $node,\n                    'type' =&gt; 'fragmentation',\n                    'message' =&gt; \"\u30e1\u30e2\u30ea\u30d5\u30e9\u30b0\u30e1\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u6bd4\u304c\u9ad8\u3059\u304e\u307e\u3059\uff08{$stat['fragmentation_ratio']}\uff09\"\n                ];\n            }\n\n            if ($stat['status'] === 'WARNING' || $stat['status'] === 'CRITICAL') {\n                $recommendations[] = [\n                    'node' =&gt; $node,\n                    'type' =&gt; 'memory_usage',\n                    'message' =&gt; \"\u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u304c{$stat['usage_percentage']}%\u306b\u9054\u3057\u3066\u3044\u307e\u3059\"\n                ];\n            }\n        }\n\n        return $recommendations;\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-40\">\u30e1\u30e2\u30ea\u6700\u9069\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30ad\u30fc\u8a2d\u8a08\u306e\u6700\u9069\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ \u52b9\u7387\u7684\u306a\u30ad\u30fc\u8a2d\u8a08\u306e\u4f8b\nclass OptimizedKeyManager\n{\n    private RedisCluster $cluster;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n    }\n\n    public function setUserSession(int $userId, array $data): bool\n    {\n        \/\/ \u77ed\u3044\u30ad\u30fc\u540d\u3092\u4f7f\u7528\n        $key = \"u:{$userId}:s\";\n\n        \/\/ \u5fc5\u8981\u306a\u30c7\u30fc\u30bf\u306e\u307f\u3092\u4fdd\u5b58\n        $sessionData = array_intersect_key($data, array_flip([\n            'id', 'name', 'role', 'last_access'\n        ]));\n\n        return $this-&gt;cluster-&gt;setex(\n            $key,\n            3600, \/\/ 1\u6642\u9593\u306eTTL\n            json_encode($sessionData, JSON_THROW_ON_ERROR)\n        );\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-41\">\u30ec\u30a4\u30c6\u30f3\u30b7\u30fc\u6539\u5584\u306e\u305f\u3081\u306e\u5177\u4f53\u7684\u306a\u8a2d\u5b9a\u8abf\u6574<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-42\">\u30ec\u30a4\u30c6\u30f3\u30b7\u30fc\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass RedisLatencyMonitor\n{\n    private RedisCluster $cluster;\n    private array $latencyThresholds;\n\n    public function __construct(\n        RedisCluster $cluster,\n        array $latencyThresholds = [\n            'warning' =&gt; 10,    \/\/ 10ms\n            'critical' =&gt; 50    \/\/ 50ms\n        ]\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;latencyThresholds = $latencyThresholds;\n    }\n\n    public function measureOperationLatency(callable $operation, int $samples = 100): array\n    {\n        $latencies = [];\n\n        for ($i = 0; $i &lt; $samples; $i++) {\n            $start = microtime(true);\n\n            try {\n                $operation($this-&gt;cluster);\n            } catch (\\Exception $e) {\n                continue;\n            }\n\n            $end = microtime(true);\n            $latencies[] = ($end - $start) * 1000; \/\/ \u30df\u30ea\u79d2\u306b\u5909\u63db\n        }\n\n        if (empty($latencies)) {\n            throw new \\RuntimeException('\u30ec\u30a4\u30c6\u30f3\u30b7\u30fc\u6e2c\u5b9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f');\n        }\n\n        return [\n            'avg' =&gt; array_sum($latencies) \/ count($latencies),\n            'min' =&gt; min($latencies),\n            'max' =&gt; max($latencies),\n            'p95' =&gt; $this-&gt;percentile($latencies, 95),\n            'p99' =&gt; $this-&gt;percentile($latencies, 99)\n        ];\n    }\n\n    private function percentile(array $latencies, int $percentile): float\n    {\n        sort($latencies);\n        $index = ceil(count($latencies) * $percentile \/ 100) - 1;\n        return $latencies[$index];\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-43\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u8a2d\u5b9a\u306e\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/\/ Redis Cluster\u8a2d\u5b9a\u306e\u6700\u9069\u5316\nclass ClusterOptimizer\n{\n    private RedisCluster $cluster;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n    }\n\n    public function applyOptimalSettings(): array\n    {\n        $results = [];\n        $masters = $this-&gt;cluster-&gt;_masters();\n\n        foreach ($masters as $master) {\n            try {\n                \/\/ TCP-keepalive\u8a2d\u5b9a\n                $results[] = $this-&gt;cluster-&gt;rawCommand($master, 'CONFIG', 'SET', 'tcp-keepalive', '300');\n\n                \/\/ \u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u8a2d\u5b9a\u306e\u6700\u9069\u5316\n                $results[] = $this-&gt;cluster-&gt;rawCommand($master, 'CONFIG', 'SET', 'save', '900 1 300 10 60 10000');\n\n                \/\/ \u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u9045\u5ef6\u306e\u6700\u5c0f\u5316\n                $results[] = $this-&gt;cluster-&gt;rawCommand($master, 'CONFIG', 'SET', 'repl-disable-tcp-nodelay', 'no');\n\n                \/\/ \u30e1\u30e2\u30ea\u7ba1\u7406\u306e\u6700\u9069\u5316\n                $results[] = $this-&gt;cluster-&gt;rawCommand($master, 'CONFIG', 'SET', 'maxmemory-policy', 'volatile-lru');\n\n            } catch (\\RedisClusterException $e) {\n                $results[] = \"Error on {$master}: {$e-&gt;getMessage()}\";\n            }\n        }\n\n        return $results;\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-44\">\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u30b9\u30b1\u30fc\u30eb\u30a2\u30c3\u30d7\u3068\u30b9\u30b1\u30fc\u30eb\u30a2\u30a6\u30c8\u6226\u7565<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-45\">\u8ca0\u8377\u5206\u6563\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u30af\u30e9\u30b9<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass ClusterLoadBalanceMonitor\n{\n    private RedisCluster $cluster;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n    }\n\n    public function analyzeClusterLoad(): array\n    {\n        $masters = $this-&gt;cluster-&gt;_masters();\n        $loadStats = [];\n\n        foreach ($masters as $master) {\n            $info = $this-&gt;cluster-&gt;info($master);\n\n            $loadStats[$master] = [\n                'connected_clients' =&gt; $info['connected_clients'] ?? 0,\n                'total_commands_processed' =&gt; $info['total_commands_processed'] ?? 0,\n                'keyspace_hits' =&gt; $info['keyspace_hits'] ?? 0,\n                'keyspace_misses' =&gt; $info['keyspace_misses'] ?? 0,\n                'used_memory' =&gt; $info['used_memory'] ?? 0\n            ];\n        }\n\n        return $this-&gt;calculateLoadImbalance($loadStats);\n    }\n\n    private function calculateLoadImbalance(array $stats): array\n    {\n        $totalLoad = array_sum(array_column($stats, 'connected_clients'));\n        $nodeCount = count($stats);\n        $expectedLoadPerNode = $totalLoad \/ $nodeCount;\n\n        $imbalance = [];\n        foreach ($stats as $node =&gt; $stat) {\n            $deviation = abs($stat['connected_clients'] - $expectedLoadPerNode);\n            $deviationPercent = ($deviation \/ $expectedLoadPerNode) * 100;\n\n            $imbalance[$node] = [\n                'current_load' =&gt; $stat['connected_clients'],\n                'expected_load' =&gt; $expectedLoadPerNode,\n                'deviation_percent' =&gt; round($deviationPercent, 2)\n            ];\n        }\n\n        return $imbalance;\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-46\">\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u5224\u65ad\u306e\u81ea\u52d5\u5316<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass ClusterScalingAdvisor\n{\n    private RedisMemoryMonitor $memoryMonitor;\n    private RedisLatencyMonitor $latencyMonitor;\n    private ClusterLoadBalanceMonitor $loadMonitor;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;memoryMonitor = new RedisMemoryMonitor($cluster);\n        $this-&gt;latencyMonitor = new RedisLatencyMonitor($cluster);\n        $this-&gt;loadMonitor = new ClusterLoadBalanceMonitor($cluster);\n    }\n\n    public function getScalingRecommendations(): array\n    {\n        $recommendations = [];\n\n        \/\/ \u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u306e\u5206\u6790\n        $memoryStats = $this-&gt;memoryMonitor-&gt;getMemoryStats();\n        foreach ($memoryStats as $node =&gt; $stats) {\n            if ($stats['usage_percentage'] &gt; 80) {\n                $recommendations[] = [\n                    'type' =&gt; 'memory',\n                    'action' =&gt; 'scale_up',\n                    'node' =&gt; $node,\n                    'reason' =&gt; \"\u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u304c{$stats['usage_percentage']}%\u306b\u9054\u3057\u3066\u3044\u307e\u3059\"\n                ];\n            }\n        }\n\n        \/\/ \u8ca0\u8377\u5206\u6563\u306e\u5206\u6790\n        $loadImbalance = $this-&gt;loadMonitor-&gt;analyzeClusterLoad();\n        $highDeviationNodes = array_filter($loadImbalance, function($node) {\n            return $node['deviation_percent'] &gt; 20;\n        });\n\n        if (!empty($highDeviationNodes)) {\n            $recommendations[] = [\n                'type' =&gt; 'load_balance',\n                'action' =&gt; 'rebalance',\n                'affected_nodes' =&gt; array_keys($highDeviationNodes),\n                'reason' =&gt; '\u8ca0\u8377\u304c\u4e0d\u5747\u8861\u3067\u3059'\n            ];\n        }\n\n        return $recommendations;\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001Redis Cluster\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u7d99\u7d9a\u7684\u306b\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3057\u3001\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u6700\u9069\u5316\u3092\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3053\u308c\u3089\u306e\u30c4\u30fc\u30eb\u3092\u4f7f\u7528\u3057\u305f\u5b9f\u969b\u306e\u904b\u7528\u7ba1\u7406\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-47\">Redis Cluster\u306e\u904b\u7528\u7ba1\u7406\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/h2>\n\n\n\n<p>Redis Cluster\u306e\u5b89\u5b9a\u7684\u306a\u904b\u7528\u3068\u3001\u767a\u751f\u3059\u308b\u53ef\u80fd\u6027\u306e\u3042\u308b\u554f\u984c\u3078\u306e\u52b9\u679c\u7684\u306a\u5bfe\u51e6\u65b9\u6cd5\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-48\">\u52b9\u679c\u7684\u306a\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3068\u30a2\u30e9\u30fc\u30c8\u8a2d\u5b9a\u306e\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-49\">\u7dcf\u5408\u7684\u306a\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Monitoring;\n\nclass RedisClusterMonitor\n{\n    private RedisCluster $cluster;\n    private array $alertChannels;\n    private array $thresholds;\n\n    public function __construct(\n        RedisCluster $cluster,\n        array $alertChannels,\n        array $thresholds = [\n            'memory_usage' =&gt; 80,        \/\/ 80%\n            'latency' =&gt; 100,            \/\/ 100ms\n            'connection_count' =&gt; 5000,   \/\/ 5000\u63a5\u7d9a\n            'replication_delay' =&gt; 10     \/\/ 10\u79d2\n        ]\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;alertChannels = $alertChannels;\n        $this-&gt;thresholds = $thresholds;\n    }\n\n    public function runHealthCheck(): array\n    {\n        $healthStatus = [];\n        $masters = $this-&gt;cluster-&gt;_masters();\n\n        foreach ($masters as $master) {\n            try {\n                $nodeStatus = $this-&gt;checkNodeHealth($master);\n                $healthStatus[$master] = $nodeStatus;\n\n                \/\/ \u30a2\u30e9\u30fc\u30c8\u6761\u4ef6\u306e\u78ba\u8a8d\n                $this-&gt;checkAlertConditions($master, $nodeStatus);\n\n            } catch (\\Exception $e) {\n                $this-&gt;sendAlert(\"\u30ce\u30fc\u30c9{$master}\u306e\u5065\u5eb7\u8a3a\u65ad\u306b\u5931\u6557: {$e-&gt;getMessage()}\");\n                $healthStatus[$master] = ['status' =&gt; 'ERROR', 'error' =&gt; $e-&gt;getMessage()];\n            }\n        }\n\n        return $healthStatus;\n    }\n\n    private function checkNodeHealth(string $node): array\n    {\n        $info = $this-&gt;cluster-&gt;info($node);\n\n        return [\n            'status' =&gt; 'OK',\n            'memory_usage' =&gt; [\n                'used' =&gt; $info['used_memory_human'],\n                'peak' =&gt; $info['used_memory_peak_human'],\n                'percentage' =&gt; $this-&gt;calculateMemoryUsage($info)\n            ],\n            'connections' =&gt; [\n                'current' =&gt; $info['connected_clients'],\n                'rejected' =&gt; $info['rejected_connections']\n            ],\n            'replication' =&gt; [\n                'role' =&gt; $info['role'],\n                'connected_slaves' =&gt; $info['connected_slaves'] ?? 0,\n                'replication_delay' =&gt; $this-&gt;getReplicationDelay($info)\n            ],\n            'performance' =&gt; [\n                'ops_per_sec' =&gt; $info['instantaneous_ops_per_sec'],\n                'hit_rate' =&gt; $this-&gt;calculateHitRate($info)\n            ]\n        ];\n    }\n\n    private function checkAlertConditions(string $node, array $status): void\n    {\n        \/\/ \u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u30c1\u30a7\u30c3\u30af\n        if ($status['memory_usage']['percentage'] &gt;= $this-&gt;thresholds['memory_usage']) {\n            $this-&gt;sendAlert(\n                \"\u8b66\u544a: \u30ce\u30fc\u30c9{$node}\u306e\u30e1\u30e2\u30ea\u4f7f\u7528\u7387\u304c{$status['memory_usage']['percentage']}%\u306b\u9054\u3057\u3066\u3044\u307e\u3059\"\n            );\n        }\n\n        \/\/ \u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u6570\u30c1\u30a7\u30c3\u30af\n        if ($status['connections']['current'] &gt;= $this-&gt;thresholds['connection_count']) {\n            $this-&gt;sendAlert(\n                \"\u8b66\u544a: \u30ce\u30fc\u30c9{$node}\u306e\u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u6570\u304c{$status['connections']['current']}\u306b\u9054\u3057\u3066\u3044\u307e\u3059\"\n            );\n        }\n\n        \/\/ \u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u9045\u5ef6\u30c1\u30a7\u30c3\u30af\n        if ($status['replication']['replication_delay'] &gt;= $this-&gt;thresholds['replication_delay']) {\n            $this-&gt;sendAlert(\n                \"\u8b66\u544a: \u30ce\u30fc\u30c9{$node}\u306e\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u9045\u5ef6\u304c{$status['replication']['replication_delay']}\u79d2\u306b\u9054\u3057\u3066\u3044\u307e\u3059\"\n            );\n        }\n    }\n\n    private function sendAlert(string $message): void\n    {\n        foreach ($this-&gt;alertChannels as $channel) {\n            $channel-&gt;send([\n                'message' =&gt; $message,\n                'timestamp' =&gt; date('Y-m-d H:i:s'),\n                'severity' =&gt; 'WARNING'\n            ]);\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-50\">\u30a2\u30e9\u30fc\u30c8\u30c1\u30e3\u30f3\u30cd\u30eb\u306e\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\ninterface AlertChannel\n{\n    public function send(array $alert): bool;\n}\n\nclass SlackAlertChannel implements AlertChannel\n{\n    private string $webhookUrl;\n\n    public function __construct(string $webhookUrl)\n    {\n        $this-&gt;webhookUrl = $webhookUrl;\n    }\n\n    public function send(array $alert): bool\n    {\n        $payload = json_encode([\n            'text' =&gt; \"\ud83d\udea8 Redis Cluster Alert\\n{$alert['message']}\",\n            'attachments' =&gt; [[\n                'color' =&gt; $this-&gt;getSeverityColor($alert['severity']),\n                'fields' =&gt; [\n                    [\n                        'title' =&gt; 'Severity',\n                        'value' =&gt; $alert['severity'],\n                        'short' =&gt; true\n                    ],\n                    [\n                        'title' =&gt; 'Timestamp',\n                        'value' =&gt; $alert['timestamp'],\n                        'short' =&gt; true\n                    ]\n                ]\n            ]]\n        ]);\n\n        $ch = curl_init($this-&gt;webhookUrl);\n        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');\n        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application\/json']);\n\n        $result = curl_exec($ch);\n        curl_close($ch);\n\n        return $result !== false;\n    }\n\n    private function getSeverityColor(string $severity): string\n    {\n        return match($severity) {\n            'CRITICAL' =&gt; '#FF0000',\n            'WARNING' =&gt; '#FFA500',\n            default =&gt; '#36a64f'\n        };\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-51\">\u4e00\u822c\u7684\u306a\u969c\u5bb3\u30d1\u30bf\u30fc\u30f3\u3068\u89e3\u6c7a\u30a2\u30d7\u30ed\u30fc\u30c1<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-52\">\u969c\u5bb3\u691c\u77e5\u3068\u81ea\u52d5\u5fa9\u65e7\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass ClusterFailureHandler\n{\n    private RedisCluster $cluster;\n    private RedisClusterMonitor $monitor;\n    private array $recoveryStrategies;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;monitor = new RedisClusterMonitor($cluster, [new SlackAlertChannel('webhook_url')]);\n        $this-&gt;initializeRecoveryStrategies();\n    }\n\n    private function initializeRecoveryStrategies(): void\n    {\n        $this-&gt;recoveryStrategies = [\n            'memory_pressure' =&gt; function ($node) {\n                \/\/ \u30e1\u30e2\u30ea\u5727\u8feb\u6642\u306e\u5bfe\u5fdc\n                return $this-&gt;handleMemoryPressure($node);\n            },\n            'connection_overflow' =&gt; function ($node) {\n                \/\/ \u30b3\u30cd\u30af\u30b7\u30e7\u30f3\u6570\u8d85\u904e\u6642\u306e\u5bfe\u5fdc\n                return $this-&gt;handleConnectionOverflow($node);\n            },\n            'replication_failure' =&gt; function ($node) {\n                \/\/ \u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5931\u6557\u6642\u306e\u5bfe\u5fdc\n                return $this-&gt;handleReplicationFailure($node);\n            }\n        ];\n    }\n\n    public function handleFailure(string $node, string $failureType): bool\n    {\n        try {\n            if (isset($this-&gt;recoveryStrategies[$failureType])) {\n                $strategy = $this-&gt;recoveryStrategies[$failureType];\n                return $strategy($node);\n            }\n\n            throw new \\RuntimeException(\"\u672a\u77e5\u306e\u969c\u5bb3\u30bf\u30a4\u30d7: {$failureType}\");\n\n        } catch (\\Exception $e) {\n            $this-&gt;monitor-&gt;sendAlert(\"\u969c\u5bb3\u5fa9\u65e7\u5931\u6557: {$e-&gt;getMessage()}\");\n            return false;\n        }\n    }\n\n    private function handleMemoryPressure(string $node): bool\n    {\n        try {\n            \/\/ 1. \u6709\u52b9\u671f\u9650\u5207\u308c\u30ad\u30fc\u306e\u524a\u9664\u3092\u5f37\u5236\u5b9f\u884c\n            $this-&gt;cluster-&gt;rawCommand($node, 'EXPIRE', '*', 0);\n\n            \/\/ 2. volatile-lru\u30dd\u30ea\u30b7\u30fc\u306e\u9069\u7528\n            $this-&gt;cluster-&gt;rawCommand($node, 'CONFIG', 'SET', 'maxmemory-policy', 'volatile-lru');\n\n            \/\/ 3. \u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u518d\u78ba\u8a8d\n            $info = $this-&gt;cluster-&gt;info($node);\n            $memoryUsage = ($info['used_memory'] \/ $info['total_system_memory']) * 100;\n\n            return $memoryUsage &lt; 80;\n\n        } catch (\\Exception $e) {\n            throw new \\RuntimeException(\"\u30e1\u30e2\u30ea\u5727\u8feb\u306e\u51e6\u7406\u306b\u5931\u6557: {$e-&gt;getMessage()}\");\n        }\n    }\n\n    private function handleConnectionOverflow(string $node): bool\n    {\n        try {\n            \/\/ 1. \u30a2\u30a4\u30c9\u30eb\u63a5\u7d9a\u306e\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u5024\u3092\u8abf\u6574\n            $this-&gt;cluster-&gt;rawCommand($node, 'CONFIG', 'SET', 'timeout', '300');\n\n            \/\/ 2. \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u63a5\u7d9a\u306e\u5236\u9650\u5024\u3092\u4e00\u6642\u7684\u306b\u5f15\u304d\u4e0a\u3052\n            $this-&gt;cluster-&gt;rawCommand($node, 'CONFIG', 'SET', 'maxclients', '10000');\n\n            \/\/ 3. \u30a2\u30a4\u30c9\u30eb\u63a5\u7d9a\u306e\u5f37\u5236\u5207\u65ad\n            $this-&gt;cluster-&gt;rawCommand($node, 'CLIENT', 'KILL', 'TYPE', 'normal', 'IDLE', 'GT', '1800');\n\n            return true;\n\n        } catch (\\Exception $e) {\n            throw new \\RuntimeException(\"\u63a5\u7d9a\u30aa\u30fc\u30d0\u30fc\u30d5\u30ed\u30fc\u306e\u51e6\u7406\u306b\u5931\u6557: {$e-&gt;getMessage()}\");\n        }\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-53\">\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3068\u707d\u5bb3\u5fa9\u65e7\u8a08\u753b\u306e\u7b56\u5b9a<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-54\">\u81ea\u52d5\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass RedisClusterBackup\n{\n    private RedisCluster $cluster;\n    private string $backupPath;\n    private array $config;\n\n    public function __construct(\n        RedisCluster $cluster,\n        string $backupPath,\n        array $config = [\n            'retention_days' =&gt; 7,\n            'compression' =&gt; true,\n            'encrypt' =&gt; true\n        ]\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;backupPath = $backupPath;\n        $this-&gt;config = $config;\n    }\n\n    public function createBackup(): array\n    {\n        $backupResults = [];\n        $masters = $this-&gt;cluster-&gt;_masters();\n\n        foreach ($masters as $master) {\n            try {\n                \/\/ 1. BGSAVE\u5b9f\u884c\n                $this-&gt;cluster-&gt;rawCommand($master, 'BGSAVE');\n\n                \/\/ 2. \u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30d5\u30a1\u30a4\u30eb\u306e\u5f85\u6a5f\n                $this-&gt;waitForBgsave($master);\n\n                \/\/ 3. RDB\u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\n                $backupFile = $this-&gt;copyRdbFile($master);\n\n                \/\/ 4. \u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u306e\u5727\u7e2e\u3068\u6697\u53f7\u5316\n                if ($this-&gt;config['compression']) {\n                    $backupFile = $this-&gt;compressBackup($backupFile);\n                }\n\n                if ($this-&gt;config['encrypt']) {\n                    $backupFile = $this-&gt;encryptBackup($backupFile);\n                }\n\n                $backupResults[$master] = [\n                    'status' =&gt; 'SUCCESS',\n                    'file' =&gt; $backupFile,\n                    'timestamp' =&gt; date('Y-m-d H:i:s')\n                ];\n\n            } catch (\\Exception $e) {\n                $backupResults[$master] = [\n                    'status' =&gt; 'FAILED',\n                    'error' =&gt; $e-&gt;getMessage()\n                ];\n            }\n        }\n\n        \/\/ \u53e4\u3044\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u306e\u524a\u9664\n        $this-&gt;cleanupOldBackups();\n\n        return $backupResults;\n    }\n\n    private function waitForBgsave(string $node, int $timeout = 600): bool\n    {\n        $start = time();\n        while (time() - $start &lt; $timeout) {\n            $info = $this-&gt;cluster-&gt;info($node);\n            if ($info['rdb_bgsave_in_progress'] === 0) {\n                return true;\n            }\n            sleep(1);\n        }\n\n        throw new \\RuntimeException(\"BGSAVE\u304c\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3057\u307e\u3057\u305f\");\n    }\n\n    private function cleanupOldBackups(): void\n    {\n        $retention = $this-&gt;config['retention_days'] * 86400;\n        $files = glob($this-&gt;backupPath . '\/*.rdb*');\n\n        foreach ($files as $file) {\n            if (time() - filemtime($file) &gt; $retention) {\n                unlink($file);\n            }\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001Redis Cluster\u306e\u5b89\u5b9a\u7684\u306a\u904b\u7528\u3068\u8fc5\u901f\u306a\u554f\u984c\u89e3\u6c7a\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u5b9f\u969b\u306e\u6d3b\u7528\u4e8b\u4f8b\u3068\u5fdc\u7528\u30d1\u30bf\u30fc\u30f3\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-55\">Redis Cluster\u306e\u6d3b\u7528\u4e8b\u4f8b\u3068\u5fdc\u7528\u30d1\u30bf\u30fc\u30f3<\/h2>\n\n\n\n<p>\u5b9f\u969b\u306e\u73fe\u5834\u3067Redis Cluster\u304c\u3069\u306e\u3088\u3046\u306b\u6d3b\u7528\u3055\u308c\u3066\u3044\u308b\u304b\u3001\u5177\u4f53\u7684\u306a\u5b9f\u88c5\u4f8b\u3068\u3068\u3082\u306b\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-56\">\u5927\u898f\u6a21Web\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u5c0e\u5165\u4e8b\u4f8b<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-57\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Session;\n\nclass RedisClusterSessionHandler implements \\SessionHandlerInterface\n{\n    private RedisCluster $cluster;\n    private int $ttl;\n    private string $prefix;\n\n    public function __construct(\n        RedisCluster $cluster,\n        int $ttl = 3600,\n        string $prefix = 'session:'\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;ttl = $ttl;\n        $this-&gt;prefix = $prefix;\n    }\n\n    public function open($path, $name): bool\n    {\n        return true;\n    }\n\n    public function close(): bool\n    {\n        return true;\n    }\n\n    public function read($id): string|false\n    {\n        $data = $this-&gt;cluster-&gt;get($this-&gt;prefix . $id);\n        return $data === false ? '' : $data;\n    }\n\n    public function write($id, $data): bool\n    {\n        return $this-&gt;cluster-&gt;setex(\n            $this-&gt;prefix . $id,\n            $this-&gt;ttl,\n            $data\n        );\n    }\n\n    public function destroy($id): bool\n    {\n        return $this-&gt;cluster-&gt;del($this-&gt;prefix . $id) &gt; 0;\n    }\n\n    public function gc($max_lifetime): int|false\n    {\n        \/\/ Redis handles expiration automatically\n        return 0;\n    }\n}\n\n\/\/ \u4f7f\u7528\u4f8b\n$sessionHandler = new RedisClusterSessionHandler($redisCluster);\nsession_set_save_handler($sessionHandler, true);\nsession_start();<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-58\">\u5927\u898f\u6a21\u30ad\u30e3\u30c3\u30b7\u30e5\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Cache;\n\nclass DistributedCache\n{\n    private RedisCluster $cluster;\n    private array $options;\n\n    public function __construct(\n        RedisCluster $cluster,\n        array $options = [\n            'default_ttl' =&gt; 3600,\n            'prefix' =&gt; 'cache:',\n            'serializer' =&gt; 'json'\n        ]\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;options = $options;\n    }\n\n    public function remember(string $key, callable $callback, ?int $ttl = null): mixed\n    {\n        $value = $this-&gt;get($key);\n\n        if ($value !== null) {\n            return $value;\n        }\n\n        $value = $callback();\n        $this-&gt;set($key, $value, $ttl);\n\n        return $value;\n    }\n\n    public function set(string $key, mixed $value, ?int $ttl = null): bool\n    {\n        $key = $this-&gt;options['prefix'] . $key;\n        $ttl = $ttl ?? $this-&gt;options['default_ttl'];\n\n        $serialized = $this-&gt;serialize($value);\n\n        return $this-&gt;cluster-&gt;setex($key, $ttl, $serialized);\n    }\n\n    public function get(string $key): mixed\n    {\n        $key = $this-&gt;options['prefix'] . $key;\n        $value = $this-&gt;cluster-&gt;get($key);\n\n        if ($value === false) {\n            return null;\n        }\n\n        return $this-&gt;unserialize($value);\n    }\n\n    private function serialize(mixed $value): string\n    {\n        return match($this-&gt;options['serializer']) {\n            'json' =&gt; json_encode($value, JSON_THROW_ON_ERROR),\n            'php' =&gt; serialize($value),\n            default =&gt; throw new \\InvalidArgumentException('Unsupported serializer')\n        };\n    }\n\n    private function unserialize(string $value): mixed\n    {\n        return match($this-&gt;options['serializer']) {\n            'json' =&gt; json_decode($value, true, 512, JSON_THROW_ON_ERROR),\n            'php' =&gt; unserialize($value),\n            default =&gt; throw new \\InvalidArgumentException('Unsupported serializer')\n        };\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-59\">\u30de\u30a4\u30af\u30ed\u30b5\u30fc\u30d3\u30b9\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306b\u304a\u3051\u308b\u6d3b\u7528\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-60\">\u30b5\u30fc\u30d3\u30b9\u9593\u901a\u4fe1\u306e\u305f\u3081\u306e\u5206\u6563\u30ed\u30c3\u30af\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\DistributedLock;\n\nclass RedisClusterLock\n{\n    private RedisCluster $cluster;\n    private string $prefix;\n    private int $defaultTtl;\n\n    public function __construct(\n        RedisCluster $cluster,\n        string $prefix = 'lock:',\n        int $defaultTtl = 30\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;prefix = $prefix;\n        $this-&gt;defaultTtl = $defaultTtl;\n    }\n\n    public function acquire(string $resource, int $ttl = null): string|false\n    {\n        $token = bin2hex(random_bytes(16));\n        $key = $this-&gt;prefix . $resource;\n        $ttl = $ttl ?? $this-&gt;defaultTtl;\n\n        $script = &lt;&lt;&lt;LUA\n        if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then\n            return redis.call('expire', KEYS[1], ARGV[2])\n        end\n        return 0\n        LUA;\n\n        try {\n            $result = $this-&gt;cluster-&gt;eval(\n                $script,\n                [$key],\n                [$token, $ttl]\n            );\n\n            return $result ? $token : false;\n\n        } catch (\\RedisClusterException $e) {\n            error_log(\"\u30ed\u30c3\u30af\u53d6\u5f97\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            return false;\n        }\n    }\n\n    public function release(string $resource, string $token): bool\n    {\n        $key = $this-&gt;prefix . $resource;\n\n        $script = &lt;&lt;&lt;LUA\n        if redis.call('get', KEYS[1]) == ARGV[1] then\n            return redis.call('del', KEYS[1])\n        end\n        return 0\n        LUA;\n\n        try {\n            return (bool)$this-&gt;cluster-&gt;eval(\n                $script,\n                [$key],\n                [$token]\n            );\n\n        } catch (\\RedisClusterException $e) {\n            error_log(\"\u30ed\u30c3\u30af\u89e3\u653e\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            return false;\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-61\">\u30a4\u30d9\u30f3\u30c8\u30b9\u30c8\u30ea\u30fc\u30df\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\EventStream;\n\nclass RedisEventStream\n{\n    private RedisCluster $cluster;\n    private string $streamPrefix;\n\n    public function __construct(\n        RedisCluster $cluster,\n        string $streamPrefix = 'stream:'\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;streamPrefix = $streamPrefix;\n    }\n\n    public function publish(string $stream, array $event): string\n    {\n        $streamKey = $this-&gt;streamPrefix . $stream;\n\n        try {\n            return $this-&gt;cluster-&gt;xAdd(\n                $streamKey,\n                '*',\n                $event\n            );\n\n        } catch (\\RedisClusterException $e) {\n            throw new \\RuntimeException(\"\u30a4\u30d9\u30f3\u30c8\u767a\u884c\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n        }\n    }\n\n    public function subscribe(\n        array $streams,\n        int $count = 100,\n        int $block = 0\n    ): array {\n        $streamKeys = array_map(\n            fn($stream) =&gt; $this-&gt;streamPrefix . $stream,\n            $streams\n        );\n\n        $lastIds = array_fill(0, count($streamKeys), '0');\n        $streamMapping = array_combine($streamKeys, $lastIds);\n\n        try {\n            return $this-&gt;cluster-&gt;xRead(\n                $streamMapping,\n                $count,\n                $block\n            );\n\n        } catch (\\RedisClusterException $e) {\n            throw new \\RuntimeException(\"\u30a4\u30d9\u30f3\u30c8\u8cfc\u8aad\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n        }\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-62\">\u5c06\u6765\u7684\u306a\u62e1\u5f35\u6027\u3092\u8003\u616e\u3057\u305f\u8a2d\u8a08\u306e\u30dd\u30a4\u30f3\u30c8<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-63\">\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb\u306a\u30ad\u30e3\u30c3\u30b7\u30e5\u30d5\u30a1\u30b5\u30fc\u30c9\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace App\\Cache;\n\nclass RedisCacheFacade\n{\n    private RedisCluster $cluster;\n    private array $strategies;\n\n    public function __construct(RedisCluster $cluster)\n    {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;initializeStrategies();\n    }\n\n    private function initializeStrategies(): void\n    {\n        $this-&gt;strategies = [\n            'simple' =&gt; new SimpleCache($this-&gt;cluster),\n            'distributed' =&gt; new DistributedCache($this-&gt;cluster),\n            'session' =&gt; new SessionCache($this-&gt;cluster)\n        ];\n    }\n\n    public function strategy(string $name): CacheStrategy\n    {\n        if (!isset($this-&gt;strategies[$name])) {\n            throw new \\InvalidArgumentException(\"Unknown cache strategy: {$name}\");\n        }\n\n        return $this-&gt;strategies[$name];\n    }\n\n    public function extend(string $name, CacheStrategy $strategy): void\n    {\n        $this-&gt;strategies[$name] = $strategy;\n    }\n}\n\ninterface CacheStrategy\n{\n    public function get(string $key): mixed;\n    public function set(string $key, mixed $value, ?int $ttl = null): bool;\n    public function delete(string $key): bool;\n    public function clear(): bool;\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-64\">\u5c06\u6765\u306e\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u3092\u898b\u636e\u3048\u305f\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30b7\u30e3\u30fc\u30c7\u30a3\u30f3\u30b0\u30ad\u30fc\u8a2d\u8a08<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass ShardingKeyGenerator\n{\n    private array $config;\n\n    public function __construct(array $config = [\n        'algorithm' =&gt; 'crc32',\n        'slots' =&gt; 16384\n    ]) {\n        $this-&gt;config = $config;\n    }\n\n    public function generate(string $key): int\n    {\n        $hash = match($this-&gt;config['algorithm']) {\n            'crc32' =&gt; crc32($key),\n            'md5' =&gt; hexdec(substr(md5($key), 0, 8)),\n            default =&gt; throw new \\InvalidArgumentException('Unsupported algorithm')\n        };\n\n        return $hash % $this-&gt;config['slots'];\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u62e1\u5f35\u53ef\u80fd\u306a\u30ad\u30e3\u30c3\u30b7\u30e5\u30bf\u30b0\u30b7\u30b9\u30c6\u30e0<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nclass CacheTagManager\n{\n    private RedisCluster $cluster;\n    private string $prefix;\n\n    public function __construct(\n        RedisCluster $cluster,\n        string $prefix = 'tags:'\n    ) {\n        $this-&gt;cluster = $cluster;\n        $this-&gt;prefix = $prefix;\n    }\n\n    public function tagKeys(string $tag, array $keys): bool\n    {\n        $tagKey = $this-&gt;prefix . $tag;\n\n        try {\n            $pipeline = $this-&gt;cluster-&gt;multi();\n\n            foreach ($keys as $key) {\n                $pipeline-&gt;sAdd($tagKey, $key);\n            }\n\n            $pipeline-&gt;exec();\n            return true;\n\n        } catch (\\RedisClusterException $e) {\n            error_log(\"\u30bf\u30b0\u4ed8\u3051\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            return false;\n        }\n    }\n\n    public function invalidateTag(string $tag): bool\n    {\n        $tagKey = $this-&gt;prefix . $tag;\n\n        try {\n            $keys = $this-&gt;cluster-&gt;sMembers($tagKey);\n\n            if (!empty($keys)) {\n                $pipeline = $this-&gt;cluster-&gt;multi();\n                $pipeline-&gt;del($keys);\n                $pipeline-&gt;del($tagKey);\n                $pipeline-&gt;exec();\n            }\n\n            return true;\n\n        } catch (\\RedisClusterException $e) {\n            error_log(\"\u30bf\u30b0\u7121\u52b9\u5316\u30a8\u30e9\u30fc: {$e-&gt;getMessage()}\");\n            return false;\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u4f8b\u3068\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb\u3067\u4fe1\u983c\u6027\u306e\u9ad8\u3044Redis Cluster\u30d9\u30fc\u30b9\u306e\u30b7\u30b9\u30c6\u30e0\u3092\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u3001\u3053\u308c\u3089\u306e\u30b3\u30fc\u30c9\u3092\u57fa\u306b\u3001\u81ea\u8eab\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8981\u4ef6\u306b\u5408\u308f\u305b\u3066\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3057\u3066\u3044\u304f\u3053\u3068\u3092\u63a8\u5968\u3057\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: Undefined array key &#8220;is_admin&#8221; in \/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/ &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":{"0":"post-3306","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-php","7":"nothumb"},"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/3306","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3306"}],"version-history":[{"count":1,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/3306\/revisions"}],"predecessor-version":[{"id":3307,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/3306\/revisions\/3307"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3306"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3306"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3306"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}