0x00--在单台PC服务器上部署Redis集群,通过不同的TCP端口启动多实例,模拟多台独立PC组成集群。
0x01--环境描述:
1 Centos版本:CentOS Linux release 7.4.1708 (Core) 2 Redis版本:Redis 4.0.10 (00000000/0) 64 bit 3 安装方式:源码安装
0x02--编辑Redis实例配置文件
在根目录下新建/redis_cluster目录,用于存放多实例配置文件,这里使用6个TCP端口,编写6029--6034共计6个配置文件,使用折6个配置文件启动实例,并搭建Redis集群。
1 port 6029 ##端口号,用于模拟不同主机不同实例,6029,6030,6031,6032,6033,6034 2 bind 10.118.128.223 ##实例IP地址,默认为127.0.0.1,根据实际情况修改,集群节点间需要保证IP地址能相互通讯,网络层面需要放开相应端口的访问权限 3 daemonize yes ##允许Redis后台运行 4 pidfile /redis_cluster/redis_6029.pid ##pidfile 文件,每个实例一个,分别对应6029.6030.6031,6032,6033,6034 5 cluster-enabled yes ##开启集群cluster 6 cluster-config-file nodes_6029.conf ##集群配置文件 7 cluster-node-timeout 15000 ##请求超时时长,默认15秒,可依据网络情况自行修改配置
0x03--启动多个Redis实例
1 [root@centos7 6030]# redis-server /redis_cluster/6029/redis.conf 2 21267:C 29 Jun 16:45:41.271 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 3 21267:C 29 Jun 16:45:41.271 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21267, just started 4 21267:C 29 Jun 16:45:41.271 # Configuration loaded 5 [root@centos7 6030]# redis-server /redis_cluster/6030/redis.conf 6 21272:C 29 Jun 16:45:47.325 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7 21272:C 29 Jun 16:45:47.325 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21272, just started 8 21272:C 29 Jun 16:45:47.325 # Configuration loaded 9 [root@centos7 6030]# redis-server /redis_cluster/6031/redis.conf 10 21277:C 29 Jun 16:45:50.637 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 11 21277:C 29 Jun 16:45:50.637 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21277, just started 12 21277:C 29 Jun 16:45:50.637 # Configuration loaded 13 [root@centos7 6030]# redis-server /redis_cluster/6032/redis.conf 14 21282:C 29 Jun 16:45:53.938 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 15 21282:C 29 Jun 16:45:53.939 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21282, just started 16 21282:C 29 Jun 16:45:53.939 # Configuration loaded 17 [root@centos7 6030]# redis-server /redis_cluster/6033/redis.conf 18 21287:C 29 Jun 16:45:57.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 19 21287:C 29 Jun 16:45:57.490 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21287, just started 20 21287:C 29 Jun 16:45:57.490 # Configuration loaded 21 [root@centos7 6030]# redis-server /redis_cluster/6034/redis.conf 22 21292:C 29 Jun 16:46:00.787 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 23 21292:C 29 Jun 16:46:00.788 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=21292, just started 24 21292:C 29 Jun 16:46:00.788 # Configuration loaded
查看进程,可看到已经有6个Redis实例启动,且端口号也可以明显看到
1 [root@centos7 src]# ps -ef|grep redis|grep cluster 2 root 21268 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6029 [cluster] 3 root 21273 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6030 [cluster] 4 root 21278 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6031 [cluster] 5 root 21283 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6032 [cluster] 6 root 21288 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6033 [cluster] 7 root 21293 1 0 16:45 ? 00:00:03 redis-server 10.118.128.223:6034 [cluster]
0x04--配置Ruby环境-redis-trib.rb脚本
Redis3.0以后开始支持集群功能,官方推出了一个管理redis集群的工具--一个ruby脚本:redis-trib.rb
该脚本集成在redis的源码SRC目录下,所以,需要系统安装配置ruby环境,才能使用该脚本进行Redis集群的创建、配置和管理。
以下是该脚本的内容,仅供学习参考,redis版本为4.0.10
1 [root@centos7 src]# cat redis-trib.rb 2 #!/usr/bin/env ruby 3 4 # TODO (temporary here, we'll move this into the Github issues once 5 # redis-trib initial implementation is completed). 6 # 7 # - Make sure that if the rehashing fails in the middle redis-trib will try 8 # to recover. 9 # - When redis-trib performs a cluster check, if it detects a slot move in 10 # progress it should prompt the user to continue the move from where it 11 # stopped. 12 # - Gracefully handle Ctrl+C in move_slot to prompt the user if really stop 13 # while rehashing, and performing the best cleanup possible if the user 14 # forces the quit. 15 # - When doing "fix" set a global Fix to true, and prompt the user to 16 # fix the problem if automatically fixable every time there is something 17 # to fix. For instance: 18 # 1) If there is a node that pretend to receive a slot, or to migrate a 19 # slot, but has no entries in that slot, fix it. 20 # 2) If there is a node having keys in slots that are not owned by it 21 # fix this condition moving the entries in the same node. 22 # 3) Perform more possibly slow tests about the state of the cluster. 23 # 4) When aborted slot migration is detected, fix it. 24 25 require 'rubygems' 26 require 'redis' 27 28 ClusterHashSlots = 16384 29 MigrateDefaultTimeout = 60000 30 MigrateDefaultPipeline = 10 31 RebalanceDefaultThreshold = 2 32 33 $verbose = false 34 35 def xputs(s) 36 case s[0..2] 37 when ">>>" 38 color="29;1" 39 when "[ER" 40 color="31;1" 41 when "[WA" 42 color="31;1" 43 when "[OK" 44 color="32" 45 when "[FA","***" 46 color="33" 47 else 48 color=nil 49 end 50 51 color = nil if ENV['TERM'] != "xterm" 52 print "\033[#{color}m" if color 53 print s 54 print "\033[0m" if color 55 print "\n" 56 end 57 58 class ClusterNode 59 def initialize(addr) 60 s = addr.split("@")[0].split(":") 61 if s.length < 2 62 puts "Invalid IP or Port (given as #{addr}) - use IP:Port format" 63 exit 1 64 end 65 port = s.pop # removes port from split array 66 ip = s.join(":") # if s.length > 1 here, it's IPv6, so restore address 67 @r = nil 68 @info = {} 69 @info[:host] = ip 70 @info[:port] = port 71 @info[:slots] = {} 72 @info[:migrating] = {} 73 @info[:importing] = {} 74 @info[:replicate] = false 75 @dirty = false # True if we need to flush slots info into node. 76 @friends = [] 77 end 78 79 def friends 80 @friends 81 end 82 83 def slots 84 @info[:slots] 85 end 86 87 def has_flag?(flag) 88 @info[:flags].index(flag) 89 end 90 91 def to_s 92 "#{@info[:host]}:#{@info[:port]}" 93 end 94 95 def connect(o={}) 96 return if @r 97 print "Connecting to node #{self}: " if $verbose 98 STDOUT.flush 99 begin 100 @r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60) 101 @r.ping 102 rescue 103 xputs "[ERR] Sorry, can't connect to node #{self}" 104 exit 1 if o[:abort] 105 @r = nil 106 end 107 xputs "OK" if $verbose 108 end 109 110 def assert_cluster 111 info = @r.info 112 if !info["cluster_enabled"] || info["cluster_enabled"].to_i == 0 113 xputs "[ERR] Node #{self} is not configured as a cluster node." 114 exit 1 115 end 116 end 117 118 def assert_empty 119 if !(@r.cluster("info").split("\r\n").index("cluster_known_nodes:1")) || 120 (@r.info['db0']) 121 0." 122 exit 1 123 end 124 end 125 126 def load_info(o={}) 127 self.connect 128 nodes = @r.cluster("nodes").split("\n") 129 nodes.each{|n| 130 # name addr flags role ping_sent ping_recv link_status slots 131 split = n.split 132 name,addr,flags,master_id,ping_sent,ping_recv,config_epoch,link_status = split[0..6] 133 slots = split[8..-1] 134 info = { 135 :name => name, 136 :addr => addr, 137 :flags => flags.split(","), 138 :replicate => master_id, 139 :ping_sent => ping_sent.to_i, 140 :ping_recv => ping_recv.to_i, 141 :link_status => link_status 142 } 143 info[:replicate] = false if master_id == "-" 144 145 if info[:flags].index("myself") 146 @info = @info.merge(info) 147 @info[:slots] = {} 148 slots.each{|s| 149 if s[0..0] == '[' 150 if s.index("->-") # Migrating 151 slot,dst = s[1..-1].split("->-") 152 @info[:migrating][slot.to_i] = dst 153 elsif s.index("-<-") # Importing 154 slot,src = s[1..-1].split("-<-") 155 @info[:importing][slot.to_i] = src 156 end 157 elsif s.index("-") 158 start,stop = s.split("-") 159 self.add_slots((start.to_i)..(stop.to_i)) 160 else 161 self.add_slots((s.to_i)..(s.to_i)) 162 end 163 } if slots 164 @dirty = false 165 @r.cluster("info").split("\n").each{|e| 166 k,v=e.split(":") 167 k = k.to_sym 168 v.chop! 169 if k != :cluster_state 170 @info[k] = v.to_i 171 else 172 @info[k] = v 173 end 174 } 175 elsif o[:getfriends] 176 @friends << info 177 end 178 } 179 end 180 181 def add_slots(slots) 182 slots.each{|s| 183 @info[:slots][s] = :new 184 } 185 @dirty = true 186 end 187 188 def set_as_replica(node_id) 189 @info[:replicate] = node_id 190 @dirty = true 191 end 192 193 def flush_node_config 194 return if !@dirty 195 if @info[:replicate] 196 begin 197 @r.cluster("replicate",@info[:replicate]) 198 rescue 199 # If the cluster did not already joined it is possible that 200 # the slave does not know the master node yet. So on errors 201 # we return ASAP leaving the dirty flag set, to flush the 202 # config later. 203 return 204 end 205 else 206 new = [] 207 @info[:slots].each{|s,val| 208 if val == :new 209 new << s 210 @info[:slots][s] = true 211 end 212 } 213 @r.cluster("addslots",*new) 214 end 215 @dirty = false 216 end 217 218 def info_string 219 # We want to display the hash slots assigned to this node 220 # as ranges, like in: "1-5,8-9,20-25,30" 221 # 222 # Note: this could be easily written without side effects, 223 # we use 'slots' just to split the computation into steps. 224 225 # First step: we want an increasing array of integers 226 # for instance: [1,2,3,4,5,8,9,20,21,22,23,24,25,30] 227 slots = @info[:slots].keys.sort 228 229 # As we want to aggregate adjacent slots we convert all the 230 # slot integers into ranges (with just one element) 231 # So we have something like [1..1,2..2, ... and so forth. 232 slots.map!{|x| x..x} 233 234 # Finally we group ranges with adjacent elements. 235 slots = slots.reduce([]) {|a,b| 236 if !a.empty? && b.first == (a[-1].last)+1 237 a[0..-2] + [(a[-1].first)..(b.last)] 238 else 239 a + [b] 240 end 241 } 242 243 # Now our task is easy, we just convert ranges with just one 244 # element into a number, and a real range into a start-end format. 245 # Finally we join the array using the comma as separator. 246 slots = slots.map{|x| 247 x.count == 1 ? x.first.to_s : "#{x.first}-#{x.last}" 248 }.join(",") 249 250 role = self.has_flag?("master") ? "M" : "S" 251 252 if self.info[:replicate] and @dirty 253 is = "S: #{self.info[:name]} #{self.to_s}" 254 else 255 is = "#{role}: #{self.info[:name]} #{self.to_s}\n"+ 256 " slots:#{slots} (#{self.slots.length} slots) "+ 257 "#{(self.info[:flags]-["myself"]).join(",")}" 258 end 259 if self.info[:replicate] 260 is += "\n replicates #{info[:replicate]}" 261 elsif self.has_flag?("master") && self.info[:replicas] 262 is += "\n #{info[:replicas].length} additional replica(s)" 263 end 264 is 265 end 266 267 # Return a single string representing nodes and associated slots. 268 # TODO: remove slaves from config when slaves will be handled 269 # by Redis Cluster. 270 def get_config_signature 271 config = [] 272 @r.cluster("nodes").each_line{|l| 273 s = l.split 274 slots = s[8..-1].select {|x| x[0..0] != "["} 275 next if slots.length == 0 276 config << s[0]+":"+(slots.sort.join(",")) 277 } 278 config.sort.join("|") 279 end 280 281 def info 282 @info 283 end 284 285 def is_dirty? 286 @dirty 287 end 288 289 def r 290 @r 291 end 292 end 293 294 class RedisTrib 295 def initialize 296 @nodes = [] 297 @fix = false 298 @errors = [] 299 @timeout = MigrateDefaultTimeout 300 end 301 302 def check_arity(req_args, num_args) 303 if ((req_args > 0 and num_args != req_args) || 304 (req_args < 0 and num_args < req_args.abs)) 305 xputs "[ERR] Wrong number of arguments for specified sub command" 306 exit 1 307 end 308 end 309 310 def add_node(node) 311 @nodes << node 312 end 313 314 def reset_nodes 315 @nodes = [] 316 end 317 318 def cluster_error(msg) 319 @errors << msg 320 xputs msg 321 end 322 323 # Return the node with the specified ID or Nil. 324 def get_node_by_name(name) 325 @nodes.each{|n| 326 return n if n.info[:name] == name.downcase 327 } 328 return nil 329 end 330 331 # Like get_node_by_name but the specified name can be just the first 332 # part of the node ID as long as the prefix in unique across the 333 # cluster. 334 def get_node_by_abbreviated_name(name) 335 l = name.length 336 candidates = [] 337 @nodes.each{|n| 338 if n.info[:name][0...l] == name.downcase 339 candidates << n 340 end 341 } 342 return nil if candidates.length != 1 343 candidates[0] 344 end 345 346 # This function returns the master that has the least number of replicas 347 # in the cluster. If there are multiple masters with the same smaller 348 # number of replicas, one at random is returned. 349 def get_master_with_least_replicas 350 masters = @nodes.select{|n| n.has_flag? "master"} 351 sorted = masters.sort{|a,b| 352 a.info[:replicas].length <=> b.info[:replicas].length 353 } 354 sorted[0] 355 end 356 357 def check_cluster(opt={}) 358 xputs ">>> Performing Cluster Check (using node #{@nodes[0]})" 359 show_nodes if !opt[:quiet] 360 check_config_consistency 361 check_open_slots 362 check_slots_coverage 363 end 364 365 def show_cluster_info 366 masters = 0 367 keys = 0 368 @nodes.each{|n| 369 if n.has_flag?("master") 370 puts "#{n} (#{n.info[:name][0...8]}...) -> #{n.r.dbsize} keys | #{n.slots.length} slots | "+ 371 "#{n.info[:replicas].length} slaves." 372 masters += 1 373 keys += n.r.dbsize 374 end 375 } 376 xputs "[OK] #{keys} keys in #{masters} masters." 377 keys_per_slot = sprintf("%.2f",keys/16384.0) 378 puts "#{keys_per_slot} keys per slot on average." 379 end 380 381 # Merge slots of every known node. If the resulting slots are equal 382 # to ClusterHashSlots, then all slots are served. 383 def covered_slots 384 slots = {} 385 @nodes.each{|n| 386 slots = slots.merge(n.slots) 387 } 388 slots 389 end 390 391 def check_slots_coverage 392 xputs ">>> Check slots coverage..." 393 slots = covered_slots 394 if slots.length == ClusterHashSlots 395 xputs "[OK] All #{ClusterHashSlots} slots covered." 396 else 397 cluster_error \ 398 "[ERR] Not all #{ClusterHashSlots} slots are covered by nodes." 399 fix_slots_coverage if @fix 400 end 401 end 402 403 def check_open_slots 404 xputs ">>> Check for open slots..." 405 open_slots = [] 406 @nodes.each{|n| 407 if n.info[:migrating].size > 0 408 cluster_error \ 409 "[WARNING] Node #{n} has slots in migrating state (#{n.info[:migrating].keys.join(",")})." 410 open_slots += n.info[:migrating].keys 411 end 412 if n.info[:importing].size > 0 413 cluster_error \ 414 "[WARNING] Node #{n} has slots in importing state (#{n.info[:importing].keys.join(",")})." 415 open_slots += n.info[:importing].keys 416 end 417 } 418 open_slots.uniq! 419 if open_slots.length > 0 420 xputs "[WARNING] The following slots are open: #{open_slots.join(",")}" 421 end 422 if @fix 423 open_slots.each{|slot| fix_open_slot slot} 424 end 425 end 426 427 def nodes_with_keys_in_slot(slot) 428 nodes = [] 429 @nodes.each{|n| 430 next if n.has_flag?("slave") 431 nodes << n if n.r.cluster("getkeysinslot",slot,1).length > 0 432 } 433 nodes 434 end 435 436 def fix_slots_coverage 437 not_covered = (0...ClusterHashSlots).to_a - covered_slots.keys 438 xputs ">>> Fixing slots coverage..." 439 xputs "List of not covered slots: " + not_covered.join(",") 440 441 # For every slot, take action depending on the actual condition: 442 # 1) No node has keys for this slot. 443 # 2) A single node has keys for this slot. 444 # 3) Multiple nodes have keys for this slot. 445 slots = {} 446 not_covered.each{|slot| 447 nodes = nodes_with_keys_in_slot(slot) 448 slots[slot] = nodes 449 xputs "Slot #{slot} has keys in #{nodes.length} nodes: #{nodes.join(", ")}" 450 } 451 452 none = slots.select {|k,v| v.length == 0} 453 single = slots.select {|k,v| v.length == 1} 454 multi = slots.select {|k,v| v.length > 1} 455 456 # Handle case "1": keys in no node. 457 if none.length > 0 458 xputs "The folowing uncovered slots have no keys across the cluster:" 459 xputs none.keys.join(",") 460 yes_or_die "Fix these slots by covering with a random node?" 461 none.each{|slot,nodes| 462 node = @nodes.sample 463 xputs ">>> Covering slot #{slot} with #{node}" 464 node.r.cluster("addslots",slot) 465 } 466 end 467 468 # Handle case "2": keys only in one node. 469 if single.length > 0 470 xputs "The folowing uncovered slots have keys in just one node:" 471 puts single.keys.join(",") 472 yes_or_die "Fix these slots by covering with those nodes?" 473 single.each{|slot,nodes| 474 xputs ">>> Covering slot #{slot} with #{nodes[0]}" 475 nodes[0].r.cluster("addslots",slot) 476 } 477 end 478 479 # Handle case "3": keys in multiple nodes. 480 if multi.length > 0 481 xputs "The folowing uncovered slots have keys in multiple nodes:" 482 xputs multi.keys.join(",") 483 yes_or_die "Fix these slots by moving keys into a single node?" 484 multi.each{|slot,nodes| 485 target = get_node_with_most_keys_in_slot(nodes,slot) 486 xputs ">>> Covering slot #{slot} moving keys to #{target}" 487 488 target.r.cluster('addslots',slot) 489 target.r.cluster('setslot',slot,'stable') 490 nodes.each{|src| 491 next if src == target 492 # Set the source node in 'importing' state (even if we will 493 # actually migrate keys away) in order to avoid receiving 494 # redirections for MIGRATE. 495 src.r.cluster('setslot',slot,'importing',target.info[:name]) 496 move_slot(src,target,slot,:dots=>true,:fix=>true,:cold=>true) 497 src.r.cluster('setslot',slot,'stable') 498 } 499 } 500 end 501 end 502 503 # Return the owner of the specified slot 504 def get_slot_owners(slot) 505 owners = [] 506 @nodes.each{|n| 507 next if n.has_flag?("slave") 508 n.slots.each{|s,_| 509 owners << n if s == slot 510 } 511 } 512 owners 513 end 514 515 # Return the node, among 'nodes' with the greatest number of keys 516 # in the specified slot. 517 def get_node_with_most_keys_in_slot(nodes,slot) 518 best = nil 519 best_numkeys = 0 520 @nodes.each{|n| 521 next if n.has_flag?("slave") 522 numkeys = n.r.cluster("countkeysinslot",slot) 523 if numkeys > best_numkeys || best == nil 524 best = n 525 best_numkeys = numkeys 526 end 527 } 528 return best 529 end 530 531 # Slot 'slot' was found to be in importing or migrating state in one or 532 # more nodes. This function fixes this condition by migrating keys where 533 # it seems more sensible. 534 def fix_open_slot(slot) 535 puts ">>> Fixing open slot #{slot}" 536 537 # Try to obtain the current slot owner, according to the current 538 # nodes configuration. 539 owners = get_slot_owners(slot) 540 owner = owners[0] if owners.length == 1 541 542 migrating = [] 543 importing = [] 544 @nodes.each{|n| 545 next if n.has_flag? "slave" 546 if n.info[:migrating][slot] 547 migrating << n 548 elsif n.info[:importing][slot] 549 importing << n 550 elsif n.r.cluster("countkeysinslot",slot) > 0 && n != owner 551 xputs "*** Found keys about slot #{slot} in node #{n}!" 552 importing << n 553 end 554 } 555 puts "Set as migrating in: #{migrating.join(",")}" 556 puts "Set as importing in: #{importing.join(",")}" 557 558 # If there is no slot owner, set as owner the slot with the biggest 559 # number of keys, among the set of migrating / importing nodes. 560 if !owner 561 xputs ">>> Nobody claims ownership, selecting an owner..." 562 owner = get_node_with_most_keys_in_slot(@nodes,slot) 563 564 # If we still don't have an owner, we can't fix it. 565 if !owner 566 xputs "[ERR] Can't select a slot owner. Impossible to fix." 567 exit 1 568 end 569 570 # Use ADDSLOTS to assign the slot. 571 puts "*** Configuring #{owner} as the slot owner" 572 owner.r.cluster("setslot",slot,"stable") 573 owner.r.cluster("addslots",slot) 574 # Make sure this information will propagate. Not strictly needed 575 # since there is no past owner, so all the other nodes will accept 576 # whatever epoch this node will claim the slot with. 577 owner.r.cluster("bumpepoch") 578 579 # Remove the owner from the list of migrating/importing 580 # nodes. 581 migrating.delete(owner) 582 importing.delete(owner) 583 end 584 585 # If there are multiple owners of the slot, we need to fix it 586 # so that a single node is the owner and all the other nodes 587 # are in importing state. Later the fix can be handled by one 588 # of the base cases above. 589 # 590 # Note that this case also covers multiple nodes having the slot 591 # in migrating state, since migrating is a valid state only for 592 # slot owners. 593 if owners.length > 1 594 owner = get_node_with_most_keys_in_slot(owners,slot) 595 owners.each{|n| 596 next if n == owner 597 n.r.cluster('delslots',slot) 598 n.r.cluster('setslot',slot,'importing',owner.info[:name]) 599 importing.delete(n) # Avoid duplciates 600 importing << n 601 } 602 owner.r.cluster('bumpepoch') 603 end
trib.rb脚本使用帮助:
1 [root@centos7 src]# ./redis-trib.rb help 2 Usage: redis-trib <command> <options> <arguments ...> 3 4 create host1:port1 ... hostN:portN ##创建集群 5 --replicas <arg> ##replicas参数指定当前创建的redis集群有几个Slave节点 6 check host:port ##检查集群,验证节点可用性 7 info host:port ##查看集群信息,节点信息 8 fix host:port ##修复集群 9 --timeout <arg> 10 reshard host:port ##在线迁移集群,from A to B 11 --from <arg> 12 --to <arg> 13 --slots <arg> 14 --yes 15 --timeout <arg> 16 --pipeline <arg> 17 rebalance host:port ##平衡集群节点slot数量 18 --weight <arg> 19 --auto-weights 20 --use-empty-masters 21 --timeout <arg> 22 --simulate 23 --pipeline <arg> 24 --threshold <arg> 25 add-node new_host:new_port existing_host:existing_port ##在线添加新的集群节点 26 --slave 27 --master-id <arg> 28 del-node host:port node_id ##在线删除集群节点 29 set-timeout host:port milliseconds ##redis集群节点心跳超时参数设置,默认15秒 30 call host:port command arg arg .. arg ##使命令在所有节点一起执行,慎用该参数 31 import host:port ##将外部Redis节点数据导入集群 32 --from <arg> 33 --copy 34 --replace 35 help (show this help) ##显示脚本使用帮助 36 37 For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. 38 [root@centos7 src]#
0x05--配置Ruby环境-安装Ruby
注意:redis-trib.rb的运行需要的ruby包,Ruby版本至少需要2.2,否则在安装时会出现如下报错,可以自行下载2.2.2版本以上的Ruby进行安装,也可以参照码上青天的博文进行在线升级
1 [root@centos7 6030]# gem install redis 2 Fetching: redis-4.0.1.gem (100%) 3 ERROR: Error installing redis: 4 redis requires Ruby version >= 2.2.2.
[root@centos7 6030]# yum install -y ruby ruby-devel rubygems rpm-build Loaded plugins: fastestmirror, langpacks base | 3.6 kB 00:00:00 extras | 3.4 kB 00:00:00 percona-release-noarch | 2.9 kB 00:00:00 percona-release-x86_64 | 2.9 kB 00:00:00 (1/3): extras/7/x86_64/primary_db | 149 kB 00:00:00 (2/3): percona-release-noarch/7/primary_db | 15 kB 00:00:01 (3/3): percona-release-x86_64/7/x86_64/primary_db | 784 kB 00:00:02 Loading mirror speeds from cached hostfile Resolving Dependencies --> Running transaction check ---> Package rpm-build.x86_64 0:4.11.3-32.el7 will be installed --> Processing Dependency: rpm = 4.11.3-32.el7 for package: rpm-build-4.11.3-32.el7.x86_64 --> Processing Dependency: patch >= 2.5 for package: rpm-build-4.11.3-32.el7.x86_64 --> Processing Dependency: system-rpm-config for package: rpm-build-4.11.3-32.el7.x86_64 --> Processing Dependency: perl(Thread::Queue) for package: rpm-build-4.11.3-32.el7.x86_64 ---> Package ruby.x86_64 0:2.0.0.648-33.el7_4 will be installed --> Processing Dependency: ruby-libs(x86-64) = 2.0.0.648-33.el7_4 for package: ruby-2.0.0.648-33.el7_4.x86_64 --> Processing Dependency: rubygem(bigdecimal) >= 1.2.0 for package: ruby-2.0.0.648-33.el7_4.x86_64 --> Processing Dependency: libruby.so.2.0()(64bit) for package: ruby-2.0.0.648-33.el7_4.x86_64 ---> Package ruby-devel.x86_64 0:2.0.0.648-33.el7_4 will be installed ---> Package rubygems.noarch 0:2.0.14.1-33.el7_4 will be installed --> Processing Dependency: rubygem(rdoc) >= 4.0.0 for package: rubygems-2.0.14.1-33.el7_4.noarch --> Processing Dependency: rubygem(psych) >= 2.0.0 for package: rubygems-2.0.14.1-33.el7_4.noarch --> Processing Dependency: rubygem(io-console) >= 0.4.2 for package: rubygems-2.0.14.1-33.el7_4.noarch --> Running transaction check ---> Package patch.x86_64 0:2.7.1-10.el7_5 will be installed ---> Package perl-Thread-Queue.noarch 0:3.02-2.el7 will be installed ---> Package redhat-rpm-config.noarch 0:9.1.0-80.el7.centos will be installed --> Processing Dependency: dwz >= 0.4 for package: redhat-rpm-config-9.1.0-80.el7.centos.noarch --> Processing Dependency: perl-srpm-macros for package: redhat-rpm-config-9.1.0-80.el7.centos.noarch ---> Package rpm.x86_64 0:4.11.3-25.el7 will be updated --> Processing Dependency: rpm = 4.11.3-25.el7 for package: rpm-libs-4.11.3-25.el7.x86_64 --> Processing Dependency: rpm = 4.11.3-25.el7 for package: rpm-python-4.11.3-25.el7.x86_64 ---> Package rpm.x86_64 0:4.11.3-32.el7 will be an update ---> Package ruby-libs.x86_64 0:2.0.0.648-33.el7_4 will be installed ---> Package rubygem-bigdecimal.x86_64 0:1.2.0-33.el7_4 will be installed ---> Package rubygem-io-console.x86_64 0:0.4.2-33.el7_4 will be installed ---> Package rubygem-psych.x86_64 0:2.0.0-33.el7_4 will be installed --> Processing Dependency: libyaml-0.so.2()(64bit) for package: rubygem-psych-2.0.0-33.el7_4.x86_64 ---> Package rubygem-rdoc.noarch 0:4.0.0-33.el7_4 will be installed --> Processing Dependency: ruby(irb) = 2.0.0.648 for package: rubygem-rdoc-4.0.0-33.el7_4.noarch --> Processing Dependency: rubygem(json) >= 1.7.7 for package: rubygem-rdoc-4.0.0-33.el7_4.noarch --> Running transaction check ---> Package dwz.x86_64 0:0.11-3.el7 will be installed ---> Package libyaml.x86_64 0:0.1.4-11.el7_0 will be installed ---> Package perl-srpm-macros.noarch 0:1-8.el7 will be installed ---> Package rpm-libs.x86_64 0:4.11.3-25.el7 will be updated --> Processing Dependency: rpm-libs(x86-64) = 4.11.3-25.el7 for package: rpm-build-libs-4.11.3-25.el7.x86_64 ---> Package rpm-libs.x86_64 0:4.11.3-32.el7 will be an update ---> Package rpm-python.x86_64 0:4.11.3-25.el7 will be updated ---> Package rpm-python.x86_64 0:4.11.3-32.el7 will be an update ---> Package ruby-irb.noarch 0:2.0.0.648-33.el7_4 will be installed ---> Package rubygem-json.x86_64 0:1.7.7-33.el7_4 will be installed --> Running transaction check ---> Package rpm-build-libs.x86_64 0:4.11.3-25.el7 will be updated ---> Package rpm-build-libs.x86_64 0:4.11.3-32.el7 will be an update --> Finished Dependency Resolution Dependencies Resolved ======================================================================================================================= Package Arch Version Repository Size ======================================================================================================================= Installing: rpm-build x86_64 4.11.3-32.el7 base 147 k ruby x86_64 2.0.0.648-33.el7_4 base 71 k ruby-devel x86_64 2.0.0.648-33.el7_4 base 131 k rubygems noarch 2.0.14.1-33.el7_4 base 219 k Installing for dependencies: dwz x86_64 0.11-3.el7 base 99 k libyaml x86_64 0.1.4-11.el7_0 base 55 k patch x86_64 2.7.1-10.el7_5 updates 110 k perl-Thread-Queue noarch 3.02-2.el7 base 17 k perl-srpm-macros noarch 1-8.el7 base 4.6 k redhat-rpm-config noarch 9.1.0-80.el7.centos base 79 k ruby-irb noarch 2.0.0.648-33.el7_4 base 92 k ruby-libs x86_64 2.0.0.648-33.el7_4 base 2.8 M rubygem-bigdecimal x86_64 1.2.0-33.el7_4 base 83 k rubygem-io-console x86_64 0.4.2-33.el7_4 base 54 k rubygem-json x86_64 1.7.7-33.el7_4 base 79 k rubygem-psych x86_64 2.0.0-33.el7_4 base 82 k rubygem-rdoc noarch 4.0.0-33.el7_4 base 322 k Updating for dependencies: rpm x86_64 4.11.3-32.el7 base 1.2 M rpm-build-libs x86_64 4.11.3-32.el7 base 105 k rpm-libs x86_64 4.11.3-32.el7 base 276 k rpm-python x86_64 4.11.3-32.el7 base 82 k Transaction Summary ======================================================================================================================= Install 4 Packages (+13 Dependent packages) Upgrade ( 4 Dependent packages) Total download size: 6.0 M Downloading packages: No Presto metadata available for base (1/21): dwz-0.11-3.el7.x86_64.rpm | 99 kB 00:00:00 (2/21): patch-2.7.1-10.el7_5.x86_64.rpm | 110 kB 00:00:00 (3/21): libyaml-0.1.4-11.el7_0.x86_64.rpm | 55 kB 00:00:00 (4/21): perl-Thread-Queue-3.02-2.el7.noarch.rpm | 17 kB 00:00:00 (5/21): perl-srpm-macros-1-8.el7.noarch.rpm | 4.6 kB 00:00:00 (6/21): redhat-rpm-config-9.1.0-80.el7.centos.noarch.rpm | 79 kB 00:00:00 (7/21): rpm-build-4.11.3-32.el7.x86_64.rpm | 147 kB 00:00:00 (8/21): rpm-build-libs-4.11.3-32.el7.x86_64.rpm | 105 kB 00:00:00 (9/21): rpm-libs-4.11.3-32.el7.x86_64.rpm | 276 kB 00:00:00 (10/21): rpm-python-4.11.3-32.el7.x86_64.rpm | 82 kB 00:00:00 (11/21): ruby-2.0.0.648-33.el7_4.x86_64.rpm | 71 kB 00:00:00 (12/21): rpm-4.11.3-32.el7.x86_64.rpm | 1.2 MB 00:00:00 (13/21): ruby-irb-2.0.0.648-33.el7_4.noarch.rpm | 92 kB 00:00:00 (14/21): ruby-libs-2.0.0.648-33.el7_4.x86_64.rpm | 2.8 MB 00:00:00 (15/21): rubygem-bigdecimal-1.2.0-33.el7_4.x86_64.rpm | 83 kB 00:00:00 (16/21): rubygem-io-console-0.4.2-33.el7_4.x86_64.rpm | 54 kB 00:00:00 (17/21): rubygem-json-1.7.7-33.el7_4.x86_64.rpm | 79 kB 00:00:00 (18/21): rubygem-psych-2.0.0-33.el7_4.x86_64.rpm | 82 kB 00:00:00 (19/21): rubygem-rdoc-4.0.0-33.el7_4.noarch.rpm | 322 kB 00:00:00 (20/21): rubygems-2.0.14.1-33.el7_4.noarch.rpm | 219 kB 00:00:00 (21/21): ruby-devel-2.0.0.648-33.el7_4.x86_64.rpm | 131 kB 00:00:09 ----------------------------------------------------------------------------------------------------------------------- Total 566 kB/s | 6.0 MB 00:00:10 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : ruby-libs-2.0.0.648-33.el7_4.x86_64 1/25 Updating : rpm-4.11.3-32.el7.x86_64 2/25 Updating : rpm-libs-4.11.3-32.el7.x86_64 3/25 Updating : rpm-build-libs-4.11.3-32.el7.x86_64 4/25 Installing : dwz-0.11-3.el7.x86_64 5/25 Installing : patch-2.7.1-10.el7_5.x86_64 6/25 Installing : libyaml-0.1.4-11.el7_0.x86_64 7/25 Installing : rubygem-io-console-0.4.2-33.el7_4.x86_64 8/25 Installing : rubygem-bigdecimal-1.2.0-33.el7_4.x86_64 9/25 Installing : rubygem-json-1.7.7-33.el7_4.x86_64 10/25 Installing : rubygem-psych-2.0.0-33.el7_4.x86_64 11/25 Installing : ruby-2.0.0.648-33.el7_4.x86_64 12/25 Installing : ruby-irb-2.0.0.648-33.el7_4.noarch 13/25 Installing : rubygems-2.0.14.1-33.el7_4.noarch 14/25 Installing : rubygem-rdoc-4.0.0-33.el7_4.noarch 15/25 Installing : perl-Thread-Queue-3.02-2.el7.noarch 16/25 Installing : perl-srpm-macros-1-8.el7.noarch 17/25 Installing : redhat-rpm-config-9.1.0-80.el7.centos.noarch 18/25 Installing : rpm-build-4.11.3-32.el7.x86_64 19/25 Installing : ruby-devel-2.0.0.648-33.el7_4.x86_64 20/25 Updating : rpm-python-4.11.3-32.el7.x86_64 21/25 Cleanup : rpm-python-4.11.3-25.el7.x86_64 22/25 Cleanup : rpm-build-libs-4.11.3-25.el7.x86_64 23/25 Cleanup : rpm-libs-4.11.3-25.el7.x86_64 24/25 Cleanup : rpm-4.11.3-25.el7.x86_64 25/25 Verifying : ruby-libs-2.0.0.648-33.el7_4.x86_64 1/25 Verifying : rubygem-rdoc-4.0.0-33.el7_4.noarch 2/25 Verifying : rubygem-io-console-0.4.2-33.el7_4.x86_64 3/25 Verifying : rubygem-bigdecimal-1.2.0-33.el7_4.x86_64 4/25 Verifying : perl-srpm-macros-1-8.el7.noarch 5/25 Verifying : perl-Thread-Queue-3.02-2.el7.noarch 6/25 Verifying : redhat-rpm-config-9.1.0-80.el7.centos.noarch 7/25 Verifying : ruby-devel-2.0.0.648-33.el7_4.x86_64 8/25 Verifying : libyaml-0.1.4-11.el7_0.x86_64 9/25 Verifying : rpm-build-4.11.3-32.el7.x86_64 10/25 Verifying : rubygem-json-1.7.7-33.el7_4.x86_64 11/25 Verifying : patch-2.7.1-10.el7_5.x86_64 12/25 Verifying : rubygem-psych-2.0.0-33.el7_4.x86_64 13/25 Verifying : ruby-2.0.0.648-33.el7_4.x86_64 14/25 Verifying : rpm-python-4.11.3-32.el7.x86_64 15/25 Verifying : rubygems-2.0.14.1-33.el7_4.noarch 16/25 Verifying : rpm-build-libs-4.11.3-32.el7.x86_64 17/25 Verifying : dwz-0.11-3.el7.x86_64 18/25 Verifying : rpm-libs-4.11.3-32.el7.x86_64 19/25 Verifying : ruby-irb-2.0.0.648-33.el7_4.noarch 20/25 Verifying : rpm-4.11.3-32.el7.x86_64 21/25 Verifying : rpm-4.11.3-25.el7.x86_64 22/25 Verifying : rpm-python-4.11.3-25.el7.x86_64 23/25 Verifying : rpm-build-libs-4.11.3-25.el7.x86_64 24/25 Verifying : rpm-libs-4.11.3-25.el7.x86_64 25/25 Installed: rpm-build.x86_64 0:4.11.3-32.el7 ruby.x86_64 0:2.0.0.648-33.el7_4 ruby-devel.x86_64 0:2.0.0.648-33.el7_4 rubygems.noarch 0:2.0.14.1-33.el7_4 Dependency Installed: dwz.x86_64 0:0.11-3.el7 libyaml.x86_64 0:0.1.4-11.el7_0 patch.x86_64 0:2.7.1-10.el7_5 perl-Thread-Queue.noarch 0:3.02-2.el7 perl-srpm-macros.noarch 0:1-8.el7 redhat-rpm-config.noarch 0:9.1.0-80.el7.centos ruby-irb.noarch 0:2.0.0.648-33.el7_4 ruby-libs.x86_64 0:2.0.0.648-33.el7_4 rubygem-bigdecimal.x86_64 0:1.2.0-33.el7_4 rubygem-io-console.x86_64 0:0.4.2-33.el7_4 rubygem-json.x86_64 0:1.7.7-33.el7_4 rubygem-psych.x86_64 0:2.0.0-33.el7_4 rubygem-rdoc.noarch 0:4.0.0-33.el7_4 Dependency Updated: rpm.x86_64 0:4.11.3-32.el7 rpm-build-libs.x86_64 0:4.11.3-32.el7 rpm-libs.x86_64 0:4.11.3-32.el7 rpm-python.x86_64 0:4.11.3-32.el7 Complete!
0x06--安装Ruby 2.4.1
1 [root@centos7 6030]# rvm install 2.4.1 2 Searching for binary rubies, this might take some time. 3 Found remote file https://rvm_io.global.ssl.fastly.net/binaries/centos/7/x86_64/ruby-2.4.1.tar.bz2 4 Checking requirements for centos. 5 Installing requirements for centos. 6 Installing required packages: autoconf, automake, bison, libffi-devel, libtool, readline-devel, sqlite-devel, zlib-devel, libyaml-devel, openssl-devel............................... 7 Requirements installation successful. 8 ruby-2.4.1 - #configure 9 ruby-2.4.1 - #download 10 % Total % Received % Xferd Average Speed Time Time Time Current 11 Dload Upload Total Spent Left Speed 12 100 14.1M 100 14.1M 0 0 94302 0 0:02:36 0:02:36 --:--:-- 75988 13 No checksum for downloaded archive, recording checksum in user configuration. 14 ruby-2.4.1 - #validate archive 15 ruby-2.4.1 - #extract 16 ruby-2.4.1 - #validate binary 17 ruby-2.4.1 - #setup 18 ruby-2.4.1 - #gemset created /usr/local/rvm/gems/ruby-2.4.1@global 19 ruby-2.4.1 - #importing gemset /usr/local/rvm/gemsets/global.gems.............................. 20 ruby-2.4.1 - #generating global wrappers........ 21 ruby-2.4.1 - #gemset created /usr/local/rvm/gems/ruby-2.4.1 22 ruby-2.4.1 - #importing gemsetfile /usr/local/rvm/gemsets/default.gems evaluated to empty gem list 23 ruby-2.4.1 - #generating default wrappers........
##查看安装结果
1 [root@centos7 6030]# rvm use 2.4.1 2 Using /usr/local/rvm/gems/ruby-2.4.1 3 [root@centos7 6030]# rvm remove 1.8.7 4 ruby-1.8.7-head - #already gone 5 Using /usr/local/rvm/gems/ruby-2.4.1 6 [root@centos7 6030]# ruby --version 7 ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
0x07--gem redis接口安装
1 [root@centos7 6030]# gem install redis 2 Fetching: redis-4.0.1.gem (100%) 3 Successfully installed redis-4.0.1 4 Parsing documentation for redis-4.0.1 5 Installing ri documentation for redis-4.0.1 6 Done installing documentation for redis after 4 seconds 7 1 gem installed
0x08--rubygems 安装
1 [root@centos7 6030]# yum install -y rubygems 2 Loaded plugins: fastestmirror, langpacks 3 Loading mirror speeds from cached hostfile 4 Package rubygems-2.0.14.1-33.el7_4.noarch already installed and latest version 5 Nothing to do
0x09--创建Redis集群
这里需要注意:需要将redis_home/src/redis-trib.rb 脚本复制到/usr/local/bin目录下,否则创建集群时,会报错:
1 -bash: redis-trib.rb: command not found
完整无报错创建Redis集群过程:
1 [root@centos7 src]# cp redis-trib.rb /usr/local/bin 2 [root@centos7 src]# redis-trib.rb create --replicas 1 10.118.128.223:6029 10.118.128.223:6030 10.118.128.223:6031 10.118.128.223:6032 10.118.128.223:6033 10.118.128.223:6034 3 >>> Creating cluster 4 >>> Performing hash slots allocation on 6 nodes... 5 Using 3 masters: 6 10.118.128.223:6029 7 10.118.128.223:6030 8 10.118.128.223:6031 9 Adding replica 10.118.128.223:6033 to 10.118.128.223:6029 10 Adding replica 10.118.128.223:6034 to 10.118.128.223:6030 11 Adding replica 10.118.128.223:6032 to 10.118.128.223:6031 12 >>> Trying to optimize slaves allocation for anti-affinity 13 [WARNING] Some slaves are in the same host as their master 14 M: 99f1b18c2895889884796e06a2f4384f5b110da0 10.118.128.223:6029 15 slots:0-5460 (5461 slots) master 16 M: f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 10.118.128.223:6030 17 slots:5461-10922 (5462 slots) master 18 M: bef79294b4cb57fe72eb3871f853745437da7c79 10.118.128.223:6031 19 slots:10923-16383 (5461 slots) master 20 S: b008404edf2dbaef9b5ba94e85478025f99da9b3 10.118.128.223:6032 21 replicates 99f1b18c2895889884796e06a2f4384f5b110da0 22 S: ec354db61687d8b8fd03a6c353c4d27ebe82a24b 10.118.128.223:6033 23 replicates f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 24 S: 73d4ee24ccc7685f33609ccc5862ef86b73e75d5 10.118.128.223:6034 25 replicates bef79294b4cb57fe72eb3871f853745437da7c79 26 Can I set the above configuration? (type 'yes' to accept): yes 27 >>> Nodes configuration updated 28 >>> Assign a different config epoch to each node 29 >>> Sending CLUSTER MEET messages to join the cluster 30 Waiting for the cluster to join....... 31 >>> Performing Cluster Check (using node 10.118.128.223:6029) 32 M: 99f1b18c2895889884796e06a2f4384f5b110da0 10.118.128.223:6029 33 slots:0-5460 (5461 slots) master 34 1 additional replica(s) 35 S: b008404edf2dbaef9b5ba94e85478025f99da9b3 10.118.128.223:6032 36 slots: (0 slots) slave 37 replicates 99f1b18c2895889884796e06a2f4384f5b110da0 38 M: f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 10.118.128.223:6030 39 slots:5461-10922 (5462 slots) master 40 1 additional replica(s) 41 S: 73d4ee24ccc7685f33609ccc5862ef86b73e75d5 10.118.128.223:6034 42 slots: (0 slots) slave 43 replicates bef79294b4cb57fe72eb3871f853745437da7c79 44 S: ec354db61687d8b8fd03a6c353c4d27ebe82a24b 10.118.128.223:6033 45 slots: (0 slots) slave 46 replicates f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 47 M: bef79294b4cb57fe72eb3871f853745437da7c79 10.118.128.223:6031 48 slots:10923-16383 (5461 slots) master 49 1 additional replica(s) 50 [OK] All nodes agree about slots configuration. 51 >>> Check for open slots... 52 >>> Check slots coverage... 53 [OK] All 16384 slots covered.
0x0A--Redis集群验证
redis-cli -h 10.118.128.223 -c -p 6029
说明:-h+host –p+端口号 –c 连接集群,连接Redis集群必须要加该参数
1 [root@centos7 src]# redis-cli -h 10.118.128.223 -c -p 6029 2 10.118.128.223:6029> cluster info 3 cluster_state:ok 4 cluster_slots_assigned:16384 5 cluster_slots_ok:16384 6 cluster_slots_pfail:0 7 cluster_slots_fail:0 8 cluster_known_nodes:6 9 cluster_size:3 10 cluster_current_epoch:6 11 cluster_my_epoch:1 12 cluster_stats_messages_ping_sent:69 13 cluster_stats_messages_pong_sent:78 14 cluster_stats_messages_sent:147 15 cluster_stats_messages_ping_received:73 16 cluster_stats_messages_pong_received:69 17 cluster_stats_messages_meet_received:5 18 cluster_stats_messages_received:147 19 10.118.128.223:6029> cluster nodes 20 b008404edf2dbaef9b5ba94e85478025f99da9b3 10.118.128.223:6032@16032 slave 99f1b18c2895889884796e06a2f4384f5b110da0 0 1530263318688 4 connected 21 f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 10.118.128.223:6030@16030 master - 0 1530263320705 2 connected 5461-10922 22 99f1b18c2895889884796e06a2f4384f5b110da0 10.118.128.223:6029@16029 myself,master - 0 1530263320000 1 connected 0-5460 23 73d4ee24ccc7685f33609ccc5862ef86b73e75d5 10.118.128.223:6034@16034 slave bef79294b4cb57fe72eb3871f853745437da7c79 0 1530263317678 6 connected 24 ec354db61687d8b8fd03a6c353c4d27ebe82a24b 10.118.128.223:6033@16033 slave f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 0 1530263318000 5 connected 25 bef79294b4cb57fe72eb3871f853745437da7c79 10.118.128.223:6031@16031 master - 0 1530263319697 3 connected 10923-16383 26 10.118.128.223:6029> cluster nodes 27 b008404edf2dbaef9b5ba94e85478025f99da9b3 10.118.128.223:6032@16032 slave 99f1b18c2895889884796e06a2f4384f5b110da0 0 1530263324000 4 connected 28 f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 10.118.128.223:6030@16030 master - 0 1530263324000 2 connected 5461-10922 29 99f1b18c2895889884796e06a2f4384f5b110da0 10.118.128.223:6029@16029 myself,master - 0 1530263323000 1 connected 0-5460 30 73d4ee24ccc7685f33609ccc5862ef86b73e75d5 10.118.128.223:6034@16034 slave bef79294b4cb57fe72eb3871f853745437da7c79 0 1530263325750 6 connected 31 ec354db61687d8b8fd03a6c353c4d27ebe82a24b 10.118.128.223:6033@16033 slave f202f30bcd2eabaa92a085a848b7e6bcfb5496c5 0 1530263324736 5 connected 32 bef79294b4cb57fe72eb3871f853745437da7c79 10.118.128.223:6031@16031 master - 0 1530263326764 3 connected 10923-16383