知识点

  • Redis启动默认就是主节点
  • 使用slaveof <hostname> <port>命令将主节点转换为从节点

    启动服务

    准备三份配置文件:master.conf、slave-1.conf、slave-2.conf

master.conf

  1. port 9000 #监听9000端口
  2. logfile "/data/log" #配置log文件位置
  3. appendonly yes #打开AOF

slave-1.conf

  1. port 9001 #监听9001端口
  2. slaveof localhost 9000 #指定主节点的主机名和端口
  3. logfile "/data/log" #配置log文件位置
  4. appendonly yes #打开AOF

slave-2.conf

  1. port 9002 #监听9002端口
  2. slaveof localhost 9000 #指定主节点的主机名和端口
  3. logfile "/data/log" #配置log文件位置
  4. appendonly yes #打开AOF

然后使用Docker运行三个节点:

master

  1. docker run -d --name redis-master-9000 --net=host -v $PWD/master-data:/data \
  2. -v $PWD/master.conf:/etc/redis.conf redis redis-server /etc/redis.conf

slave1

  1. docker run -d --name redis-slave1-9001 --net=host -v $PWD/slave1-data:/data \
  2. -v $PWD/slave-1.conf:/etc/redis.conf redis redis-server /etc/redis.conf

slave2

  1. docker run -d --name redis-slave2-9002 --net=host -v $PWD/slave2-data:/data \
  2. -v $PWD/slave-2.conf:/etc/redis.conf redis redis-server /etc/redis.conf

连接服务(Go)

注意修改代码中的主机名和端口号

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-redis/redis"
  5. "math/rand"
  6. "strconv"
  7. "testing"
  8. )
  9. const MasterSlaveSycnKey = "m-s-sync"
  10. var (
  11. masterOptions = redis.Options{
  12. Addr: "192.168.124.25:9000",
  13. Password: "",
  14. DB: 0,
  15. }
  16. slave1Options = redis.Options{
  17. Addr: "192.168.124.25:9001",
  18. Password: "",
  19. DB: 0,
  20. }
  21. slave2Options = redis.Options{
  22. Addr: "192.168.124.25:9002",
  23. Password: "",
  24. DB: 0,
  25. }
  26. )
  27. func TestConnect(t *testing.T) {
  28. masterClient := redis.NewClient(&masterOptions)
  29. slave1Client := redis.NewClient(&slave1Options)
  30. slave2Client := redis.NewClient(&slave2Options)
  31. _, err := masterClient.Ping().Result()
  32. if err != nil {
  33. t.Fatal("主节点连接失败。原因:", err)
  34. }
  35. _, err = slave1Client.Ping().Result()
  36. if err != nil {
  37. t.Fatal("1号从节点连接失败。原因:", err)
  38. }
  39. _, err = slave2Client.Ping().Result()
  40. if err != nil {
  41. t.Fatal("2号从节点连接失败。原因:", err)
  42. }
  43. fmt.Println("所有节点连接成功")
  44. }
  45. func TestSycn(t *testing.T) {
  46. masterClient := redis.NewClient(&masterOptions)
  47. slave1Client := redis.NewClient(&slave1Options)
  48. slave2Client := redis.NewClient(&slave2Options)
  49. randomNum := rand.Int()
  50. _, err := masterClient.Set(MasterSlaveSycnKey, randomNum, 0).Result()
  51. if err != nil {
  52. t.Fatal("主节点设置随机值失败!原因:", err)
  53. }
  54. resNum, err := slave1Client.Get(MasterSlaveSycnKey).Result()
  55. if err != nil {
  56. t.Fatal("1号从节点读取随机值失败!原因:", err)
  57. }
  58. if resNum != strconv.Itoa(randomNum) {
  59. t.Fatal("1号从节点复制同步失败。期望值:", randomNum, "; 实际值:", resNum)
  60. }
  61. resNum, err = slave2Client.Get(MasterSlaveSycnKey).Result()
  62. if err != nil {
  63. t.Fatal("2号从节点读取随机值失败!原因:", err)
  64. }
  65. if resNum != strconv.Itoa(randomNum) {
  66. t.Fatal("2号从节点复制同步失败。期望值:", randomNum, "实际值:", resNum)
  67. }
  68. fmt.Println("一主二从同步成功")
  69. }