中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis高可用架構設計的方法是什么

發布時間:2021-11-01 10:17:08 來源:億速云 閱讀:152 作者:iii 欄目:開發技術

本篇內容主要講解“Redis高可用架構設計的方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Redis高可用架構設計的方法是什么”吧!

 一、高可用架構設計原理

1、概述

Qunar Redis 集群是一個分布式的高可用架構,整個架構主要由以下幾個重要部分組成:

  •  Redis Server 節點:每個節點有一主一從兩個實例,多個節點組成一份完整的集群數據,其中每個節點只有主庫對外提供服務,從庫僅僅用于節點高可用、數據持久化及定時備份。

  •  Zookeeper 集群:由五個 zk 節點組成,Redis 集群配置變更后,通知客戶端進行重連。

  •  Redis Sentinel 集群:由五個 Sentinel 節點組成,用于 Reids Server 節點的高可用,主從切換、故障轉移、配置更新等。

  •  配置中心集群:由五個 MySQL 節點組成的 PXC 集群,用于存儲 Redis 集群的分片信息,即每個節點的 Master 實例信息及分配 key 的一致性 hash 值范圍。

  •  應用程序客戶端:監聽 zk 變化,在配置中心獲取 Redis 實例信息進行連接。

2、架構原理圖

Redis高可用架構設計的方法是什么

3、客戶端實現

1)當客戶端根據 Redis 集群的 namespace 建立連接時,會先從 zk 中查找/config_addr 節點, 該節點下存放的是配置中心集群的實例信息,從中隨機選擇一個數據庫實例進行連接。

2)在配置中心的特定庫表中,根據 Redis 的 namespace 查詢集群的節點的連接配置,然后建立 Redis 連接。

3)客戶端建立 Redis 連接后,會啟動了兩個線程:

  •  一個用于監聽 zk 的地址的變化。每個 Redis 集群在 zk 中都會有一個/redis/namespace 的節點 ,如果集群配置發生變化,哨兵會通知 zk 更新此節點的值,客戶端感知到 zk 配置變化, 將會去配置中心獲取新的連接配置,重新建立連接。

  •  一個用于輪詢配置中心的連接配置。為了防止 zk 通知失敗,客戶端會通過這個線程,每隔 10s 去輪詢配置中心的配置信息,如果發現配置中心的配置和本地緩存的不一樣,就會使用配置中心的配置建立新的連接。

客戶端與其他組件的關系示意圖如下:

Redis高可用架構設計的方法是什么

4、數據分片方法

開發人員提交 Redis 集群申請工單信息后,DBA 會依據工單中的內存大小、QPS 大小等幾項主要的數據,規劃集群分片節點數量為 N,所有節點平均分配 0~4294967295 范圍內的值,即共有 2 的 32 次方個 key 的值,某一個 key 使用 murmurhash3 算法計算哈希值后,只會落在集群的一個節點上。

分片節點示意圖如下:

Redis高可用架構設計的方法是什么

分片節點信息在配置中心的存儲信息如下:

Redis高可用架構設計的方法是什么

5、架構特點

Quanr Redis 高可用架構具有以下特點:

  •  實現自己的 Redis 客戶端,客戶端不再訪問 Sentinel, Sentinel 只負責高可用。

  •  通過 ZK 集群和配置中心來實現配置的集中管理。

  •  將端口視作一種資源,即集群的一個節點的主從實例使用一個端口,下線的集群端口可復用。

  •  弱化了哨兵機器的地位, 降低了哨兵和集群之間直接的耦合度。

  •  減少了哨兵機器的使用量, 目前只使用了 5 臺哨兵機器組成集群。

  •  客戶端使用 namespace 訪問集群, 將端口和 namespace 對應,namespace 和業務部門對應,方便 DBA 管理和運維,對應用透明。

6、架構局限性

Quanr Redis 高可用架構具有以下局限性:

  •  支持的客戶端比較少。目前客戶端僅支持 Java 和 Python。

  •  不支持快速水平擴容。當集群內存不足時可以快速擴大各個節點實例的內存大小,以此來增加整個集群大小,但單個實例的內存大小也有一定的限度,不能無限擴展。當需要增加集群節點個數時,由于各個節點的一致性哈希范圍發生了變化,所有的 key 需要重新分配,對于比較大的集群,過程比較繁瑣和耗時。

  •  整個架構依賴的組件比較多。雖然架構中的 zookeeper、配置中心、Sentinel 等都是多節點的高可用集群,但依賴的組件越多,發生故障的可能性也越大,運維難度和工作量也會隨著增加,無疑對運維人員有更高的要求。

  •  部分 Redis 原生功能無法使用。由于客戶端的限制,部分 Redis 原生功能無法使用,如不支持事務、Lua 腳本等。

二、安全機制

Redis 被設計成僅供可信環境下的可信用戶才可以訪問,并沒有最大化的去優化安全方面,而是盡量可能的去優化高性能和易用性,因此 Redis 沒有類似關系型數據庫那樣嚴格的權限控制,因此將 Redis 實例直接暴露在網絡上或者讓不可信的用戶直接訪問 Redis 的 TCP 端口,是非常危險的行為。

為了提高 Redis 使用的安全性,去哪兒網使用的 Redis Server 是在官方 Redis 4.0.14 版本上進行了部分的源代碼改造,增加了一個白名單參數 trustedip,屏蔽了部分高危指令,除了 trustedip 中配置的 IP 之外,任何其他客戶端連接都無法執行這些高危指令,同時為了提高 Redis 的性能,對主從實例進行了差異性配置。

1、clientcipher和IP白名單

Qunar Redis 客戶端并沒有直接通過 TCP 方式去連接 Redis 實例,而是首先要通過集群 namespace 和該集群唯一的 clientcipher 的驗證,然后從配置中心獲取真正的連接信息后,才可以連接 Redis 實例。同時白名單機制對客戶端請求中的高危指令進行過濾,避免對線上 Redis 執行不合理的操作,進一步加強了其安全性。

  •  客戶端使用 namespace 和 clientcipher 方式訪問集群。

  •  不同 namespace 對應的 clientcipher 不同,在創建集群時通過隨機生成的密碼再次加密生成 clientcipher。

  •  即使知道密碼,也無法使用屏蔽的危險命令,除非 IP 地址在白名單中。

  •  本地登陸和 IP 白名單登陸,命令不受限制,方便 DBA 管理和兼容各種監控統計腳本。

  •  IP 白名單可以動態配置,最大支持 32 個 IP 白名單。

IP 白名單功能涉及修改代碼的地方:

1)在 config.c 文件的 configGetCommand 方法中增加參數 trustedip

void configGetCommand(client *c) {  robj *o = c->argv[2];  void *replylen = addDeferredMultiBulkLength(c);  char *pattern = o->ptr;  char buf[128];  int matches = 0;  serverAssertWithInfo(c,o,sdsEncodedObject(o));  ...  /* 增加trustedip參數 */  if (stringmatch(pattern,"trustedip",0)) {  sds buf = sdsempty();  int j;  int numips;  numips = server.trusted_ips.numips;  for (j = 0; j < numips; j++) { buf = sdscat(buf, server.trusted_ips.ips[j]);  if (j != numips - 1)  buf = sdscatlen(buf," ",1);  }  addReplyBulkCString(c,"trustedip");  addReplyBulkCString(c,buf);  sdsfree(buf);  matches++;  }  setDeferredMultiBulkLength(c,replylen,matches*2);  }

2)在 server.c 文件的 processCommand 方法中增加對 issuperclient 的認證

typedef struct trustedIPArray {  int numips;  sds* ips;  } trustedIPArray;

3)在 networking.c 文件中增加 isTrustedIP 方法

/* 判斷客戶端IP是否在IP白名單中 */  int isTrustedIP(int fd) {  char ip[128];  int i, port;  anetPeerToString(fd,ip,128,&port); if (strcmp(ip, "127.0.0.1") == 0) {  return 1;  }  for (i = 0; i < server.trusted_ips.numips; i++) {  if (strcmp(ip, server.trusted_ips.ips[i]) == 0) {  return 1;  }  }  return 0;  }

4)在 networking.c 文件的 createClient 方法中增加 issuperclient 的設置

client *createClient(int fd) {  client *c = zmalloc(sizeof(client));  /* passing -1 as fd it is possible to create a non connected client.  * This is useful since all the commands needs to be executed  * in the context of a client. When commands are executed in other  * contexts (for instance a Lua script) we need a non connected client. */  if (fd != -1) {  anetNonBlock(NULL,fd);  anetEnableTcpNoDelay(NULL,fd);  if (server.tcpkeepalive)  anetKeepAlive(NULL,fd,server.tcpkeepalive);  if (aeCreateFileEvent(server.el,fd,AE_READABLE,  readQueryFromClient, c) == AE_ERR)  {  close(fd);  zfree(c);  return NULL;  }  ...  /* 設置is_super_client */  if (isTrustedIP(fd)) {  c->is_super_client = 1;  } else {  c->is_super_client = 0;  }  ...  return c;  }

5)在 server.c 文件的 processCommand 方法中增加對 issuperclient 的認證

int processCommand(client *c) {  /* The QUIT command is handled separately. Normal command procs will  * go through checking for replication and QUIT will cause trouble  * when FORCE_REPLICATION is enabled and would be implemented in  * a regular command proc. */ if (!strcasecmp(c->argv[0]->ptr,"quit")) {  addReply(c,shared.ok);  c->flags |= CLIENT_CLOSE_AFTER_REPLY;  return C_ERR;  }  ...  /* Check if the user is authenticated */  /* 增加is_super_client認證 */  if (!c->is_super_client && server.requirepass && !c->authenticated && c->cmd->proc != authCommand)  ...  return C_OK;  }

6)在 db.c 文件中增加 checkCommandBeforeExec 方法

/* 如果是super client或者是master,返回1,否則返回0  * 因為在master-slave下,master(client)需要向slave執行危險命令*/  int checkCommandBeforeExec(client *c) {  if (c->is_super_client || (server.masterhost && (c->flags & CLIENT_MASTER))) {  return 1;  }  addReplyError(c,"No permission to execute this command");  return 0;  }

2、屏蔽高危指令

通過修改 Redis 源代碼,在 Server 端屏蔽部分危險指令,規定只有通過白名單檢查的客戶端連接才可以執行這些指令。在執行高危指令前進行檢查,如需對 save 指令進行屏蔽,可對 rdb.c 文件的 saveCommand 方法的第一行增加 checkCommandBeforeExec 檢查。

void saveCommand(client *c) {  if (!checkCommandBeforeExec(c)) return; /* 執行指令之前進行檢查,如不通過直接返回 */   if (server.rdb_child_pid != -1) {  addReplyError(c,"Background save already in progress");  return;  }  rdbSaveInfo rsi, *rsiptr;  rsiptr = rdbPopulateSaveInfo(&rsi);  if (rdbSave(server.rdb_filename,rsiptr) == C_OK) { addReply(c,shared.ok);  } else {  addReply(c,shared.err);  }  }

屏蔽的高危指令有:

  •  比較耗時類指令:info、keys *。

  •  清空數據類指令:shutdown、flushdb、 flushall。

  •  數據持久化類指令:save、bgsave、bgrewriteaof。

  •  配置類指令:config get、config set、config rewrite。

  •  運維管理類指令:slaveof、monitor、client list、client kill。

在 Redis 源代碼涉及這些指令的地方,都需要加上 checkCommandBeforeExec 方法進行檢查。

3、配置優化

針對集群各個節點的主從實例進行差異化配置,由于每個節點只有主庫對外提供服務,為了最大限度的提高主庫的并發能力,一些比較耗時的操作可以放到從庫去執行。

幾項主要的配置如下:

  •  主庫關閉 bgsave、bgrewriteaof 功能。

  •  從庫開啟 aof 功能,定時調度重寫 aof 文件,釋放服務器磁盤空間。

  •  從庫定時執行 bgsave 操作,備份 rdb 文件。

  •  從庫開啟 slave-read-only 參數,只讀。

當 Redis 集群部署完之后,會有定時任務去檢查服務器上各個 Redis 實例的角色,根據角色的不同修改相關的配置參數,同時將修改后的持久化到配置文件。

三、自動化運維

1、初始化系統環境

在 Redis 服務器上部署集群之前,首先需要初始化系統環境,將這些環境配置添加到 Redis 的 rpm 打包程序的 spec 文件中,安裝 Redis 軟件包時會自動更改相關配置,主要的系統環境參數有以下幾個:

sed -i -r '/vm.overcommit_memory.*/d' /etc/sysctl.conf  sed -i -r '/vm.swappiness.*/d' /etc/sysctl.conf  sed -i -r '/vm.dirty_bytes.*/d' /etc/sysctl.conf  echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf  echo "vm.swappiness = 0" >> /etc/sysctl.conf  echo "vm.dirty_bytes = 33554432" >> /etc/sysctl.conf  /sbin/sysctl -q -p /etc/sysctl.conf  groupadd redis >/dev/null 2>&1 || true  useradd -M -g redis redis -s /sbin/nologin >/dev/null 2>&1 || true  sed -i -r '/redis soft nofile.*/d' /etc/security/limits.conf  sed -i -r '/redis hard nofile.*/d' /etc/security/limits.conf  echo "redis soft nofile 288000" >> /etc/security/limits.conf  echo "redis hard nofile 288000" >> /etc/security/limits.conf  sed -i -r '/redis soft nproc.*/d' /etc/security/limits.conf  sed -i -r '/redis hard nproc.*/d' /etc/security/limits.conf  echo "redis soft nproc unlimited" >> /etc/security/limits.conf  echo "redis hard nproc unlimited" >> /etc/security/limits.conf  echo never > /sys/kernel/mm/transparent_hugepage/enabled

2、統一運維管理工具

Qunar Redis 集群的統一管理套件,封裝了系統環境初始化、實例安裝、實例啟動、實例關閉、監控報警、定時任務等腳本,實現了監控、統計、注冊等自動化操作。

/etc/cron.d/appendonly_switch  /etc/cron.d/auto_upgrade_toolkit  /etc/cron.d/bgrewriteaof  /etc/cron.d/check_maxmemory  /etc/cron.d/dump_rdb_keys  /etc/cron.d/rdb_backup  /etc/profile.d/q_redis_path.sh  /xxx/collectd/etc/collectd.d/collect_redis.conf  /xxx/collectd/lib/collectd/collect_redis.py  /xxx/collectd/share/collectd/types_redis.db  /xxx/nrpe/libexec/q-check-redis-cpu-usage  /xxx/nrpe/libexec/q-check-redis-latency  /xxx/nrpe/libexec/q-check-redis-memory-usage  /xxx/nrpe/libexec/q-check-zookeeper-ruok  /xxx/redis/tools/cron_appendonly_switch.sh  /xxx/redis/tools/cron_bgrewrite_aof.sh  /xxx/redis/tools/cron_check_maxmemory.sh  /xxx/redis/tools/cron_dump_rdb_keys.sh  /xxx/redis/tools/cron_rdb_backup.sh  /xxx/redis/tools/dump_rdb_keys.py  /xxx/redis/tools/redis-cli5  /xxx/redis/tools/redis-latency  /xxx/redis/tools/redis_install.sh  /xxx/redis/tools/redis_start.sh  /xxx/redis/tools/redis_stop.sh

3、單機多實例多版本部署

Qunar Redis 的安裝工具包支持單機多實例安裝,安裝腳本提供選項和配置文件模板,可以自定義安裝不同版本的 Redis,目前支持的 Redis Server 版本有 2.8.6、3.0.7 以及 4.0.14。

/* 安裝包及Redis實例目錄結構 */  .  ├── multi  │ ├── server_2800 /* Redis2.8.6軟件包 */  │ │ ├── bin  │ │ └── utils  │ ├── server_3000 /* Redis3.0.7軟件包 */  │ │ ├── bin  │ │ └── utils  │ └── server_4000 /* Redis4.0.14軟件包 */  │ ├── bin  │ └── utils  ├── redis10088 /* 端口為10088的Redis實例數據目錄,用于存放該實例的配置文件、日志、AOF文件及RDB文件 */  │ ├── bin  │ └── utils  ├── redis10803 /* 端口為10803的Redis實例數據目錄,用于存放該實例的配置文件、日志、AOF文件及RDB文件 */  │ ├── bin  │ └── utils  ├── redis11459 /* 端口為11459的Redis實例數據目錄,用于存放該實例的配置文件、日志、AOF文件及RDB文件 */  │ ├── bin  │ └── utils  /* Redis實例安裝程序用法 */  Usage: redis_install.sh -P <port> -v [2.8|3.0|4.0] -p <password> -m <size>  必選參數:  -P redis端口  -p redis密碼  -v 將要安裝的redis版本,強烈推薦4.0版本  -m redis實例允許的最大內存大小,單位是G  可選參數:  --cluster 集群模式,version>=3.0  --testenv 測試環境  example:  sudo redis_install.sh -P 6379 -v 4.0 -m 20 -p 1qaz2wsx

4、使用git管理Redis哨兵

使用 git 集中管理所有的哨兵配置,一個地方發生變更,哨兵集群的所有服務器同時拉取進行同步更新。同時詳細的 commit log,方便跟蹤配置文件修改歷史。Qunar Redis 哨兵具有以下特點:

  •  一套哨兵只管理一個節點,即只對端口號相同的一組 Redis(一主一從或一主多從)實例進行監控和故障轉移。

  •  哨兵只負責節點的高可用,客戶端不需要通過哨兵來訪問 Redis 實例。

  •  哨兵配置文件使用 git 統一管理,配置文件以[節點端口號+20000]_集群 namespace.conf 方式統一命名,例如 30708_redis_delay_test.conf,通過集群任意一個節點的端口號或者 namespace 可以獲取集群全部節點的信息。

  •  當哨兵監控的節點發生切換時,會更新配置中心對應節點的主庫配置和 zookeeper 中對應節點的 dataVersion,客戶端檢測到 zookeeper 的變化會去配置中心獲取節點最新的信息進行重連,同時哨兵會將切換信息發送至 DBA 和運維事件平臺。

  • 哨兵服務器的 IP 默認都添加到 Redis 實例的白名單中,即通過哨兵服務器可以訪問任何一個 Redis 實例進行所有的操作,所以哨兵服務器的權限必須嚴格控制,只有 DBA 才有權限登陸。

5、運維操作平臺化

以上幾項規范統一的標準化流程,為 Qunar Redis 的整個運維平臺化提供了有力的支撐,目前 Qunar Redis 的 90% 以上的運維操作都實現了平臺自動化,包括工單申請及審核、集群部署、實例遷移、集群垂直伸縮、不同維度(服務器、集群、實例)的信息查看等,下面主要介紹下 Qunar Redis 集群部署和實例遷移的實現過程。

集群部署

Qunar Redis 集群部署時主要有以下步驟:

1)開發人員通過平臺提交集群申請工單發起流程,TL 審核完成后流程扭轉到 DBA。

2)DBA 根據申請工單的信息規劃集群規模,如節點個數、內存大小、部署機房、Redis 版本等。

3)根據集群規劃在 Redis 集群部署頁面填寫部署信息。

Redis高可用架構設計的方法是什么

4)提交部署信息后平臺會自動篩選資源空閑的服務器進行集群部署。

Redis高可用架構設計的方法是什么

5)集群部署完成后會在在 Qtalk 上通知 DBA,集群的 clientcipher 會通過郵件方式通知開發人員,同時會將集群部署情況推送到公司運維事件平臺,保留操作記錄。

實例遷移

運維過程中實例遷移主要分為兩大類:

1)部分實例遷移。當某臺服務器的可用資源不足時,將這臺機器上的部分實例遷移到其他資源比較空閑的服務器上。在頁面輸入實例的源主機和目前主機,提交后會自動生成遷移任務。

Redis高可用架構設計的方法是什么

2)整機實例遷移。主要是替換過保服務器或者服務器需要停機維護時,將該機器上的所有實例自動遷移到其他資源比較空間的服務器上。在頁面輸入需要遷移的主機名,提交后會自動生成遷移任務。

Redis高可用架構設計的方法是什么

遷移任務開始后,整個遷移過程無須人工介入,會自動更新執行進度并輸出日志。

Redis高可用架構設計的方法是什么

到此,相信大家對“Redis高可用架構設計的方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永清县| 夏邑县| 景泰县| 建平县| 寻乌县| 石城县| 随州市| 吉安市| 丰台区| 汝阳县| 嵩明县| 呼玛县| 华池县| 满城县| 五大连池市| 武夷山市| 湟源县| 凌海市| 萝北县| 什邡市| 石棉县| 凯里市| 湟中县| 资阳市| 屏山县| 苍山县| 长宁区| 视频| 玉门市| 大邑县| 诸暨市| 黎城县| 兴文县| 巴彦淖尔市| 合作市| 晴隆县| 平陆县| 纳雍县| 虹口区| 沅江市| 弥渡县|