Rumah > Artikel > pangkalan data > Analisis mendalam tentang failover sentinel di Redis
Artikel ini akan membawa anda melalui failover (sentinel) dalam Redis saya harap ia akan membantu anda!
Apabila dua atau lebih kejadian Redis membentuk hubungan sedia induk, kelompok yang mereka bentuk mempunyai tahap ketersediaan tinggi tertentu: apabila tuan gagal, hamba boleh menjadi The master baru menyediakan perkhidmatan membaca dan menulis luaran, dan mekanisme operasi ini menjadi failover. [Cadangan berkaitan: Tutorial video Redis]
Jadi siapa yang akan menemui kesalahan tuan dan membuat keputusan failover?
Salah satu cara ialah dengan mengekalkan proses daemo untuk memantau semua nod tuan-hamba, seperti yang ditunjukkan dalam rajah berikut:
Sekelompok Redis mempunyai Satu induk dan dua hamba, proses daemon ini memantau ketiga-tiga nod ini. Walau bagaimanapun, daemon adalah satu nod dan ketersediaannya tidak dapat dijamin. Daemon berbilang perlu diperkenalkan, seperti yang ditunjukkan dalam rajah di bawah:
Daemon berbilang menyelesaikan masalah ketersediaan, tetapi masalah konsisten timbul tuan ada? Sebagai contoh, dalam rajah di atas, dua rangkaian daemon1 dan master disekat, tetapi sambungan antara daemon dan master adalah lancar Adakah nod induk perlu failover pada masa ini?
Redis sentinel menyediakan satu set mekanisme interaksi antara berbilang daemon membentuk gugusan dan menjadi nod sentinel juga dipanggil nod sentinel. Seperti yang ditunjukkan dalam rajah di bawah:
Nod ini berkomunikasi, memilih, berunding antara satu sama lain dan kesalahan nod induk ialah dijumpai, keputusan failover.
Kluster sentinel memantau sebarang bilangan tuan dan hamba di bawah tuan, dan secara automatik meningkatkan tuan luar talian daripada hamba di bawahnya kepada tuan baharu dan bukannya terus memproses permintaan arahan../redis-sentinel ../sentinel.confatau arahan:
./redis-server ../sentinel.conf --sentinelApabila Sentinel bermula, ia perlu melakukan langkah berikut:
Memulakan pelayan
Sentinel pada asasnya ialah Redis pelayan berjalan dalam mod khas , ia melakukan kerja yang berbeza daripada pelayan Redis biasa, dan proses pemulaannya tidak betul-betul sama. Sebagai contoh, permulaan pelayan Redis biasa akan memuatkan fail RDB atau AOF untuk memulihkan data, tetapi Sentinel tidak akan memuatkannya apabila ia bermula kerana Sentinel tidak menggunakan pangkalan data.Gantikan kod yang digunakan oleh pelayan Redis biasa dengan kod khusus Sentinel
Ganti beberapa kod yang digunakan oleh pelayan Redis biasa dengan Sentinel- kod tertentu. Contohnya, pelayan Redis biasa menggunakan server.c/redisCommandTable sebagai jadual arahan pelayan:truct redisCommand redisCommandTable[] = { {"module",moduleCommand,-2,"as",0,NULL,0,0,0,0,0}, {"get",getCommand,2,"rF",0,NULL,1,1,1,0,0}, {"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0}, {"setnx",setnxCommand,3,"wmF",0,NULL,1,1,1,0,0}, {"setex",setexCommand,4,"wm",0,NULL,1,1,1,0,0}, {"psetex",psetexCommand,4,"wm",0,NULL,1,1,1,0,0}, {"append",appendCommand,3,"wm",0,NULL,1,1,1,0,0}, ..... {"del",delCommand,-2,"w",0,NULL,1,-1,1,0,0}, {"unlink",unlinkCommand,-2,"wF",0,NULL,1,-1,1,0,0}, {"exists",existsCommand,-2,"rF",0,NULL,1,-1,1,0,0}, {"setbit",setbitCommand,4,"wm",0,NULL,1,1,1,0,0}, {"getbit",getbitCommand,3,"rF",0,NULL,1,1,1,0,0}, {"bitfield",bitfieldCommand,-2,"wm",0,NULL,1,1,1,0,0}, {"setrange",setrangeCommand,4,"wm",0,NULL,1,1,1,0,0}, {"getrange",getrangeCommand,4,"r",0,NULL,1,1,1,0,0}, {"substr",getrangeCommand,4,"r",0,NULL,1,1,1,0,0}, {"incr",incrCommand,2,"wmF",0,NULL,1,1,1,0,0}, {"decr",decrCommand,2,"wmF",0,NULL,1,1,1,0,0}, {"mget",mgetCommand,-2,"rF",0,NULL,1,-1,1,0,0}, {"rpush",rpushCommand,-3,"wmF",0,NULL,1,1,1,0,0}, {"lpush",lpushCommand,-3,"wmF",0,NULL,1,1,1,0,0} ...... }Sentinel menggunakan sentinel.c/sentinelcmds sebagai senarai pelayan, seperti ditunjukkan di bawah:
struct redisCommand sentinelcmds[] = { {"ping",pingCommand,1,"",0,NULL,0,0,0,0,0}, {"sentinel",sentinelCommand,-2,"",0,NULL,0,0,0,0,0}, {"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0}, {"unsubscribe",unsubscribeCommand,-1,"",0,NULL,0,0,0,0,0}, {"psubscribe",psubscribeCommand,-2,"",0,NULL,0,0,0,0,0}, {"punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0}, {"publish",sentinelPublishCommand,3,"",0,NULL,0,0,0,0,0}, {"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}, {"role",sentinelRoleCommand,1,"l",0,NULL,0,0,0,0,0}, {"client",clientCommand,-2,"rs",0,NULL,0,0,0,0,0}, {"shutdown",shutdownCommand,-1,"",0,NULL,0,0,0,0,0}, {"auth",authCommand,2,"sltF",0,NULL,0,0,0,0,0} }
Memulakan keadaan Sentinel
Pelayan akan memulakan struktur sentinel.c/sentinelState (menyimpan semua status yang berkaitan dengan fungsi Sentinel dalam pelayan).struct sentinelState { char myid[CONFIG_RUN_ID_SIZE+1]; /* This sentinel ID. */ //当前纪元,用于实现故障转移 uint64_t current_epoch; /* Current epoch. */ //监视的主服务器 //字典的键是主服务器的名字 //字典的值则是一个指向sentinelRedisInstances结构的指针 dict *masters; /* Dictionary of master sentinelRedisInstances. Key is the instance name, value is the sentinelRedisInstance structure pointer. */ //是否进入tilt模式 int tilt; /* Are we in TILT mode? */ //目前正在执行的脚本数量 int running_scripts; /* Number of scripts in execution right now. */ //进入tilt模式的时间 mstime_t tilt_start_time; /* When TITL started. */ //最后一次执行时间处理器的时间 mstime_t previous_time; /* Last time we ran the time handler. */ // 一个FIFO队列,包含了所有需要执行的用户脚本 list *scripts_queue; /* Queue of user scripts to execute. */ char *announce_ip; /* IP addr that is gossiped to other sentinels if not NULL. */ int announce_port; /* Port that is gossiped to other sentinels if non zero. */ unsigned long simfailure_flags; /* Failures simulation. */ int deny_scripts_reconfig; /* Allow SENTINEL SET ... to change script paths at runtime? */ }
Memulakan senarai induk pemantauan Sentinel berdasarkan fail konfigurasi yang diberikan
Pemulaan status Sentinel akan mencetuskan panggilan ke Kamus induk pemulaan dan pemulaan kamus induk adalah berdasarkan fail konfigurasi Sentinel yang dimuatkan. Kunci kamus ialah nama pelayan utama pemantauan dan nilai kamus ialah struktur sentinel.c/sentinelRedisInstance yang sepadan dengan pelayan utama yang dipantau. Beberapa atribut struktur sentinelRedisInstance adalah seperti berikut:typedef struct sentinelRedisInstance { //标识值,记录了实例的类型,以及该实例的当前状态 int flags; /* See SRI_... defines */ //实例的名字 //主服务器的名字由用户在配置文件中设置 //从服务器以及Sentinel的名字由Sentinel自动设置 //格式为ip:port,例如“127.0.0.1:26379” char *name; /* Master name from the point of view of this sentinel. */ //实例运行的ID char *runid; /* Run ID of this instance, or unique ID if is a Sentinel.*/ //配置纪元,用于实现故障转移 uint64_t config_epoch; /* Configuration epoch. */ //实例的地址 sentinelAddr *addr; /* Master host. */ //sentinel down-after-milliseconds选项设定的值 //实例无响应多少毫秒之后才会被判断为主观下线(subjectively down) mstime_t down_after_period; /* Consider it down after that period. */ //sentinel monitor <master-name> <ip> <redis-port> <quorum>选项中的quorum //判断这个实例为客观下线(objective down)所需的支持投票的数量 unsigned int quorum;/* Number of sentinels that need to agree on failure. */ //sentinel parallel-syncs <master-name> <numreplicas> 选项的numreplicas值 //在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量 int parallel_syncs; /* How many slaves to reconfigure at same time. */ //sentinel failover-timeout <master-name> <milliseconds>选项的值 //刷新故障迁移状态的最大时限 mstime_t failover_timeout; /* Max time to refresh failover state. */ }Contohnya, apabila memulakan Sentinel, fail konfigurasi berikut dikonfigurasikan:
# sentinel monitor <master-name> <ip> <redis-port> <quorum> sentinel monitor master1 127.0.0.1 6379 2 # sentinel down-after-milliseconds <master-name> <milliseconds> sentinel down-after-milliseconds master1 30000 # sentinel parallel-syncs <master-name> <numreplicas> sentinel parallel-syncs master1 1 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout master1 900000Kemudian Sentinel akan menjadi induk pelayan utama1 Cipta struktur contoh seperti yang ditunjukkan di bawah: Struktur status Sentinel dan kamus induk adalah seperti berikut:
Buat sambungan rangkaian ke pelayan utama
Buat sambungan rangkaian ke pelayan utama yang dipantau akan menjadi pelanggan utama pelayan, hantar arahan ke pelayan utama dan Dapatkan maklumat daripada balasan arahan. Sentinel akan membuat dua sambungan rangkaian tak segerak ke pelayan utama:Sentinel默认会以每十秒一次的频率,通过命令连接向被监视的master和slave发送INFO命令。
通过master的回复可获取master本身信息,包括run_id域记录的服务器运行ID,以及role域记录的服务器角色。另外还会获取到master下的所有的从服务器信息,包括slave的ip地址和port端口号。Sentinel无需用户提供从服务器的地址信息,由master返回的slave的ip地址和port端口号,可以自动发现slave。
当Sentinel发现master有新的slave出现时,Sentinel会为这个新的slave创建相应的实例外,Sentinel还会创建到slave的命令连接和订阅连接。
根据slave的INFO命令的回复,Sentinel会提取如下信息:
1.slave的运行ID run_id
2.slave的角色role
3.master的ip地址和port端口
4.master和slave的连接状态master_link_status
5.slave的优先级slave_priority
6.slave的复制偏移量slave_repl_offset
Sentinel在默认情况下会以每两秒一次的频率,通过命令连接向所有被监视的master和slave的_sentinel_:hello频道发送一条信息
发送以下格式的命令:
PUBLISH _sentinel_:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
以上命令相关参数意义:
参数 | 意义 |
---|---|
s_ip | Sentinel的ip地址 |
s_port | Sentinel的端口号 |
s_runid | Sentinel的运行ID |
s_runid | Sentinel的运行ID |
m_name | 主服务器的名字 |
m_ip | 主服务器的IP地址 |
m_port | 主服务器的端口号 |
m_epoch | 主服务器当前的配置纪元 |
命令如下所示:
SUBSCRIBE sentinel:hello
如上图所示,对于每个与Sentinel连接的服务器 ,Sentinel既可以通过命令连接向服务器频道_sentinel_:hello频道发送信息,又通过订阅连接从服务器的_sentinel_:hello频道接收信息。
相互连接的各个Sentinel可以进行信息交换。Sentinel为master创建的实例结构中的sentinels字典保存了除Sentinel本身之外,所有同样监视这个主服务器的其它Sentinel信息。
前面也讲到sentinel会为slave创建实例(在master实例的slaves字典中)。现在我们也知道通过sentinel相互信息交换,也创建了其它sentinel的实例(在master实例的sentinels字典中)。我们将一个sentinel中保存的实例结构大概情况理一下,如下图所示:
从上图可以看到slave和sentinel字典的键由其ip地址和port端口组成,格式为ip:port,其字典的值为其对应的sentinelRedisInstance实例。
主观不可用
默认情况下Sentinel会以每秒一次的频率向所有与它创建了命令连接的master(包括master、slave、其它Sentinel)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。
PING命令回复分为下面两种情况:
有效回复:实例返回 +PONG、-LOADING、-MASTERDOWN三种回复的一种
无效回复:除上面有效回复外的其它回复或者在指定时限内没有任何返回
Sentinel配置文件中的设置down-after-milliseconds毫秒时效内(各个sentinel可能配置的不相同),连续向Sentinel返回无效回复,那么sentinel将此实例置为主观下线状态,在sentinel中维护的该实例flags属性中打开SRI_S_DOWN标识,例如master如下所示:
客观不可用
在sentinel发现主观不可用状态后,它会将“主观不可用状态”发给其它sentinel进行确认,当确认的sentinel节点数>=quorum,则判定该master为客观不可用,随后进入failover流程。
上面说到将主观不可用状态发给其它sentinel使用如下命令:
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
各个参数的意义如下:
接受到以上命令的sentinel会反回一条包含三个参数的Multi Bulk回复:
1)down_state> 目标sentinel对该master检查结果,1:master已下线 2:master未下线
2)leader_runid> 两种情况,*表示仅用于检测master下线状态 ,否则表示局部领头Sentinel的运行ID(选举领头Sentinel)
3)leader_epoch> 当leader_runid为时,leader_epoch始终为0。不为时则表示目标Sentinel的局部领头Sentinel的配置纪元(用于选举领头Sentinel)
其中节点数量限制quorum为sentinel配置文件中配置的
sentinel monitor <master-name> <ip> <redis-port> <quorum>
quorum选项,不同的sentinel配置的可能不相同。
当sentinel认为master为客观下线状态,则会将master属性中的flags的SRI_O_DOWN标识打开,例如master如下图所示:
Apabila induk turun, berbilang nod sentinel boleh menemui dan mengesahkan "status ketidaksediaan subjektif" satu sama lain melalui interaksi pada masa yang sama, sambil mencapai "objektif Tidak Tersedia status" dan berhasrat untuk memulakan failover. Tetapi pada akhirnya hanya boleh ada satu nod sentinel sebagai pemula failover, maka adalah perlu untuk memilih Ketua Sentinel dan memulakan proses pemilihan Ketua Sentinel.
Mekanisme Sentinel Redis menggunakan sesuatu yang serupa dengan protokol Raft untuk melaksanakan algoritma pilihan raya ini:
1 Pembolehubah zaman sentinelState adalah serupa dengan istilah (pusingan pilihan raya) dalam protokol rakit.
2. Setiap nod sentinel yang mengesahkan bahawa induk "tidak tersedia secara objektif" akan menyiarkan permintaan pilihan rayanya sendiri kepada persekitaran(SENTINEL is-master-down-by-addr
jika niat telah dinyatakan dalam pusingan ini, calon lain akan melakukannya ditolak. , dan akan membalas dengan niat (Balasan Berbilang Pukal dengan tiga parameter seperti yang diperkenalkan di atas, down_state ialah 1, leader_runid ialah ID berjalan bagi pengawal sumber yang memulakan permintaan pilihan raya yang diterima buat kali pertama, leader_epoch ialah pilihan raya pertama yang diterima permintaan Epok konfigurasi sentinel yang menjadi sumber permintaan) 4 Jika setiap nod sentinel yang memulakan permintaan calon menerima
lebih separuh daripada niat untuk bersetuju dengan sentinel calon(mungkin sendiri), Kemudian ditentukan bahawa sentinel adalah ketua. Jika pusingan ini berlangsung cukup lama dan tiada ketua dipilih, pusingan seterusnya akan bermula ketua pengawal Selepas pengesahan,
ketua pengawal memilih seorang daripada semua hamba tuan mengikut peraturan tertentu sebagai tuan baru.
Failover failoveryang berada dalam keadaan baik dan mempunyai data lengkap antara semua hamba tuan luar talian, dan kemudian menghantar:SAVEOF no one perintah kepada hamba ini untuk memindahkan ini hamba ditukar kepada tuan. Mari kita lihat bagaimana tuan baharu dipilih? Pemimpin Sentinel akan menyimpan semua hamba luar talian ke dalam senarai, dan kemudian menapis mengikut peraturan berikut:
, dikenal pasti oleh pilihan keutamaan replika dalam konfigurasi redis.conf, lalai ialah 100, lebih rendah keutamaan replika, lebih tinggi keutamaan. 0 ialah keutamaan khas, menunjukkan bahawa ia tidak boleh dinaik taraf kepada induk.
Jika terdapat berbilang hamba dengan keutamaan yang sama dan pengimbang replikasi maksimum terbesar, maka
Selepas memilih hamba yang perlu dinaik taraf kepada tuan baru, Ketua Sentinel akan menghantar HAMBA tiada siapa perintah kepada hamba.
pemimpin sentinel menghantar arahan SLAVEOF (SLAVEOF
Tetapkan tuan lama sebagai hamba tuan baharu dan teruskan memantaunya Apabila ia kembali dalam talian, Sentinel akan melaksanakan arahan untuk menjadikannya hamba tuan baharu.
Pengenalan kepada Pengaturcaraan
! !Atas ialah kandungan terperinci Analisis mendalam tentang failover sentinel di Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!