• Redis集群部署


    Redis作为目前最常用的内存NOSQL数据库,使用的场景非常的广泛.但是在3.0以前官方一直都是没有集群的方案的.相当于是一个单机内存数据库.为了其高可用,集群的部署是非常有必要的.因此,各种第三方厂商都推出了自己的集群方案.使用的最多的就是豌豆荚开源的Codis,Twitter开源的Twemproxy,NetflixDynamo.

    目前Redis是3.0.4版本,其中已经自带了Redis Cluster.但是官方的方案有一些架构上的问题.

    • 首先,官方方案是完全的去中心化的,依靠自己Server的网络通信来进行同步.那么,在节点比较多的情况下,性能上是有影响的.
    • 其二,一个redis进程既负责读写数据又负责集群交互,虽然设计者已经尽可能简化了代码和逻辑,但还是让redis从一个内存NoSQL变成了一个分布式NoSQL.
    • 其三,官方方案没有采用一致性哈希,而是预分配slot的形式来进行分片.新节点的加入不是自动的,依赖于外部的ruby脚本.
    • 其四,集群版本和单机版本数据不兼容,客户端不兼容.它的集群分发依赖于客户端的驱动. 目前只有JAVA的Jedis Driver支持了Redis Cluster的连接.而spring-data-redis目前也还没有支持官方方案.因此我们不能直接调用.
    • 其五,集群至少要分三片,加上主从备份.也就是说至少需要6个节点才能组建Redis集群.

    从上面可以看出,目前官方的方案.并不适合我们.它现在还不稳定,开源社区的支持也比较少.
    从其他三方的方案中进行对比,最后选择Codis作为我们Redis集群部署的方案.

    官方集群方案的部署

    虽然目前我们不会使用官方的方案,但是不排除以后会使用.毕竟是官方的东西,应该要靠谱些.

    1. 下载 并编译最新的Redis. 由于Redis是C写的.并且网上只有源码.因此,最好是直接下载源码到类unix机器上,然后调用 sudo make 命令自动的编译出可运行的版本.

    2. 最少集群6个节点,因此在我的磁盘上建立一个redis-test文件夹.然后建立6个子文件夹,作为6个节点.

      1
      2
      3
      mkdir redis-test
      cd redis-test
      mkdir 7000 7001 7002 7003 7004 7005
    3. 然后拷贝6分编译好的redis到各个目录中去.

    4. 修改redis.conf文件.

      1
      2
      3
      4
      5
      6
      7
      port 7005
      pidfile /Volumes/EXCHANGE/redis-test/7000/redis.pid
      cluster-enabled yes
      # 和端口对应
      cluster-config-file nodes.conf
      cluster-node-timeout 5000
      appendonly yes
    5. 修改好后,进入每一个的src文件夹,执行./redis-server ../redis.conf 启动6个服务.

    6. 随便找一个节点的src目录,找到redis-trib.rb文件.然后执行:

      1
      ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

      其中的--replicas 1指的是从服务的数量.

      执行了这句后,会显示出集群的分布情况.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      >>> Creating cluster
      Connecting to node 127.0.0.1:7000: OK
      Connecting to node 127.0.0.1:7001: OK
      Connecting to node 127.0.0.1:7002: OK
      Connecting to node 127.0.0.1:7003: OK
      Connecting to node 127.0.0.1:7004: OK
      Connecting to node 127.0.0.1:7005: OK
      >>> Performing hash slots allocation on 6 nodes...
      Using 3 masters:
      127.0.0.1:7000
      127.0.0.1:7001
      127.0.0.1:7002
      Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
      Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
      Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
      M: d450eaf8b29ccc57c5ab851868a0e23b41d0f50c 127.0.0.1:7000
      slots:0-5460 (5461 slots) master
      M: b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b 127.0.0.1:7001
      slots:5461-10922 (5462 slots) master
      M: e81eea0243d2976daca5b349ec0bc2d109ac81d0 127.0.0.1:7002
      slots:10923-16383 (5461 slots) master
      S: 52a634c534ca5db005dbc31494676e08454ebfa4 127.0.0.1:7003
      replicates d450eaf8b29ccc57c5ab851868a0e23b41d0f50c
      S: 270c10d1f3b85438b74b8fd5c9d91a3e0ce8a0da 127.0.0.1:7004
      replicates b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b
      S: e6eae15e4883cd408fe889e85565a38f6e030de7 127.0.0.1:7005
      replicates e81eea0243d2976daca5b349ec0bc2d109ac81d0
      Can I set the above configuration? (type 'yes' to accept): yes
      >>> Nodes configuration updated
      >>> Assign a different config epoch to each node
      >>> Sending CLUSTER MEET messages to join the cluster
      Waiting for the cluster to join...
      >>> Performing Cluster Check (using node 127.0.0.1:7000)
      M: d450eaf8b29ccc57c5ab851868a0e23b41d0f50c 127.0.0.1:7000
      slots:0-5460 (5461 slots) master
      M: b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b 127.0.0.1:7001
      slots:5461-10922 (5462 slots) master
      M: e81eea0243d2976daca5b349ec0bc2d109ac81d0 127.0.0.1:7002
      slots:10923-16383 (5461 slots) master
      M: 52a634c534ca5db005dbc31494676e08454ebfa4 127.0.0.1:7003
      slots: (0 slots) master
      replicates d450eaf8b29ccc57c5ab851868a0e23b41d0f50c
      M: 270c10d1f3b85438b74b8fd5c9d91a3e0ce8a0da 127.0.0.1:7004
      slots: (0 slots) master
      replicates b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b
      M: e6eae15e4883cd408fe889e85565a38f6e030de7 127.0.0.1:7005
      slots: (0 slots) master
      replicates e81eea0243d2976daca5b349ec0bc2d109ac81d0
      [OK] All nodes agree about slots configuration.
      >>> Check for open slots...
      >>> Check slots coverage...
      [OK] All 16384 slots covered.

    当出现:Can I set the above configuration? (type 'yes' to accept):的时候,输入yes.然后他就会自动的通知各个节点,自发组成集群.

    到此,redis集群的官方方案就部署好了.
    如果安装过程中出现:/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in require': cannot load such file -- redis (LoadError).那是ruby缺少redis的依赖.
    在控制台输入gem install redis即可.

    codis集群方案的部署

    Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别.上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.

    Codis 由四部分组成:

    • Codis Proxy (codis-proxy)
    • Codis Manager (codis-config)
    • Codis Redis (codis-server)
    • ZooKeeper

    codis-proxy 是客户端连接的 Redis 代理服务, codis-proxy 本身实现了 Redis 协议, 表现得和一个原生的 Redis 没什么区别 (就像 Twemproxy), 对于一个业务来说, 可以部署多个 codis-proxy, codis-proxy 本身是无状态的.

    codis-config 是 Codis 的管理工具, 支持包括, 添加/删除 Redis 节点, 添加/删除 Proxy 节点, 发起数据迁移等操作. codis-config 本身还自带了一个 http server, 会启动一个 dashboard, 用户可以直接在浏览器上观察 Codis 集群的运行状态.

    codis-server 是 Codis 项目维护的一个 Redis 分支, 基于 2.8.21 开发, 加入了 slot 的支持和原子的数据迁移指令. Codis 上层的 codis-proxy 和 codis-config 只能和这个版本的 Redis 交互才能正常运行.

    Codis 依赖 ZooKeeper 来存放数据路由表和 codis-proxy 节点的元信息, codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy.

    需要注意的是,codis的proxy是无状态的,当一个分片的master挂掉的时候,codis不会自动的将某个slave升级成master.不过他提供了一个解决方案:codis-ha.这是一个通过codis开放的api实现自动切换主从的工具。该工具会在检测到master挂掉的时候将其下线并选择其中一个slave提升为master继续提供服务。但是只是在每一个分片是一主一从两台的情况下才有效.否则,该分片内其他slave实例是不会自动改变状态的,这些slave仍将试图从旧的master上同步数据,因而会导致分片内新的master和其他slave之间的数据不一致。因为redis的slave of命令切换master时会丢弃slave上的全部数据,从新master完整同步,会消耗master资源。因此建议在知情的情况下手动操作。使用 codis-config server add <group_id> <redis_addr> slave 命令刷新这些节点的状态即可。codis-ha不会自动刷新其他slave的状态。


    1. 由于codis是由GO语言写的,因此,要运行codis首先需要的就是安装go语言环境.

      在类unix机器上都有现成的安装包可以安装.
      比如Macos 在终端中输入brew install go 即可. (安装过程中需要访问https://go.googlesource.com/tools.git,方法你懂的)

    2. 设置GO的workspace路径.在~/.bash_profiler下增加export GOPATH="/Volumes/WORKSPACE/openSourceWorkspace/GoWorkspace" 注意$GOPATH是本机所有go项目(包括项目依赖的第三方库)的所在目录,而非单纯codis的所在目录。

    3. 执行下面的命令下载codis源码并编译.它会自动的下载源码以及依赖包.
    1
    2
    3
    4
    go get -u -d github.com/wandoulabs/codis
    cd $GOPATH/src/github.com/wandoulabs/codis
    ./bootstrap.sh
    make gotest
    1. 执行完命令后,会在codis/bin下生成三个文件codis-config codis-proxy codis-serverassets文件夹里面存放的是dashboard服务所需要的静态文件.

    2. 默认情况下 这些命令都会读取config.ini里面的配置.配置很简单,按照里面的注释改就可以了.

    3. 启动ZK.
    4. 启动dashboard,执行 ./bin/codis-config dashboard,就会启动dashboard
    5. 初始化 slots , 执行 ./bin/codis-config slot init,该命令会在zookeeper上创建slot相关信息.
    6. 开始启动Codis Redis.执行./bin/codis-server,就启动的.这个就和官网的一样. 配置文件也可以跟在后面.比如:./bin/codis-server redis.config
    7. 添加 Redis Server Group , 每一个 Server Group 作为一个 Redis 服务器组存在, 只允许有一个 master, 可以有多个 slave, group id 仅支持大于等于1的整数.这个步骤可以通过dashboard来增加,也可以使用命令行.比如:

      1
      2
      3
      4
      bin/codis-config server add 1 localhost:6379 master
      bin/codis-config server add 1 localhost:6380 slave
      bin/codis-config server add 2 localhost:6479 master
      bin/codis-config server add 2 localhost:6480 slave

      这样就增加了4个节点,并且分成两片,每片一主一从.

    8. 设置 server group 服务的 slot 范围 Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024 每一个 slot 都会有一个且必须有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供.

      1
      2
      $ bin/codis-config slot range-set 0 511 1 online
      $ bin/codis-config slot range-set 512 1023 2 online

      同样,可以在界面上进行操作

    9. 启动 codis-proxy (注意,如果zk的session时间设置太短的话,proxy可能启动不起来.)

      1
      bin/codis-proxy -c config.ini -L ./log/proxy.log --cpu=8 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000
    到此就集群完毕.
    
    1. 但是为了能在master当机的时候自动的升级slave,这就需要codis-ha了.这个同样是go语言写的.所以直接在终端中输入:

      1
      2
      3
      4
      go get github.com/ngaut/codis-ha
      cd codis-ha
      go build
      codis-ha --codis-config=localhost:18087 --productName=test

      就搞定了,他会自动的监控dashboard,然后发现节点不正确后,调用restful的接口,提升slave为master


    接下来就是客户端的调用了.
    由于codis依赖了zk作为服务的发现方.因此,整个集群的节点状态都是在zk中有的.

    它自身也提供了一个JAVA的实现,叫jodis.通过这个,就可以关联jedis Driver.并且获取当前可用的codis-server.
    不过目前这个jodis还没有提供与spring的集成.这个需要我们自己来开发.

  • 相关阅读:
    高级架构进阶之HashMap源码就该这么学
    MySQL底层索引剖析
    一篇文章把本该属于你的源码天赋还给你
    不懂RPC实现原理怎能实现架构梦
    观《亿级流量网站架构核心技术》一书有感
    高效程序员如何优雅落地需求
    职场软技能:开启程序员的“破冰之旅”
    获取ScrollView的onScrollListener
    Android自定义控件之圆形进度条ImageView
    Android之內置、外置SDCard
  • 原文地址:https://www.cnblogs.com/jack87224088/p/8528998.html
Copyright © 2020-2023  润新知