设为首页 收藏本站
查看: 1728|回复: 0

[经验分享] 高性能网站架构设计之缓存---redis集群搭建

[复制链接]

尚未签到

发表于 2018-11-6 07:43:22 | 显示全部楼层 |阅读模式
  一、关于redis  cluster
  集群技术是构建高性能网站架构的重要手段,在网站承受高并发访问压力的同时,还需要从海量数据中查询出满足条件的数据,并快速响应,我们必然想到的是将数据进行切片,把数据根据某种规则放入多个不同的服务器节点,来降低单节点服务器的压力。
  我部署的redis集群主要是利用切片技术来组建的集群。
  集群要实现的目的是要将不同的 key 分散放置到不同的 redis 节点,这里我们需要一个规则或者算法,通常的做法是获取 key 的哈希值,然后根据节点数来求模,但这种做法有其明显的弊端,当我们需要增加或减少一个节点时,会造成大量的 key 无法命中,这种比例是相当高的,所以就有人提出了一致性哈希的概念。
  Redis 引入另一种哈希槽(hash slot)的概念。
  Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
  使用哈希槽的好处就在于可以方便的添加或移除节点。
  当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;
  当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;
  1,redis cluster的现状
  目前redis支持的cluster特性:
  1):节点自动发现
  2):slave->master 选举,集群容错
  3):Hot resharding:在线分片
  4):进群管理:cluster xxx
  5):基于配置(nodes-port.conf)的集群管理
  6):ASK 转向/MOVED 转向机制.
  2,redis cluster 架构
  架构细节:
  (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
  (2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
  (3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  (4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护nodeslotvalue
  3,redis-cluster选举:容错
  (1)领着选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
  (2):什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
  a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
  b:如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
  二、redis  cluster搭建
  1,安装redis-cluster依赖
  (1)确保系统安装zlib,否则gem install会报(no such file to load -- zlib)
  (2)安装ruby
  yum install  –y ruby ruby-rdoc ruby-rvm
  yum erase ruby ruby-libs ruby-mode ruby-rdoc ruby-irb ruby-ri ruby-docs
  (3)安装rubygem
  yum install rubygems 或

  •   # rubygems-1.8.16.tgz
  •   cd /path/gem
  •   sudo ruby setup.rb
  •   sudo cp bin/gem /usr/local/bin
  (4)安装gem-redis
  gem install redis --version 3.0.0
  #由于源的原因,可能下载失败,就手动下载下来安装
  #download地址:http://rubygems.org/gems/redis/versions/3.0.0
  gem install -l /data/soft/redis-3.0.0.gem
  2,安装redis-cluster

  •   cd /path/redis
  •   make
  •   sudo cp redis-server /usr/local/bin
  •   sudo cp redis-cli /usr/local/bin
  •   sudo cp redis-trib.rb /usr/local/bin
  3,配置redis-cluster
  (1) 配置redis文件结构
DSC0000.jpg

  使用包含(include)把通用配置和特殊配置分离,方便维护.
  (2)redis通用配置
  ============================================================================
  #GENERAL
  daemonize yes
  tcp-backlog 511
  timeout 0
  tcp-keepalive 0
  loglevel notice
  databases 16
  dir /data/webserver/redis/data
  slave-serve-stale-data yes
  #slave只读
  slave-read-only yes
  #not use default
  repl-disable-tcp-nodelay yes
  slave-priority 100
  #打开aof持久化
  appendonly yes
  #每秒一次aof写
  appendfsync everysec
  #关闭在aof rewrite的时候对新的写操作进行fsync
  no-appendfsync-on-rewrite yes
  auto-aof-rewrite-min-size 64mb
  lua-time-limit 5000
  #打开redis集群
  cluster-enabled yes
  #节点互连超时的阀值
  cluster-node-timeout 15000
  cluster-migration-barrier 1
  slowlog-log-slower-than 10000
  slowlog-max-len 128
  notify-keyspace-events ""
  hash-max-ziplist-entries 512
  hash-max-ziplist-value 64
  list-max-ziplist-entries 512
  list-max-ziplist-value 64
  set-max-intset-entries 512
  zset-max-ziplist-entries 128
  zset-max-ziplist-value 64
  activerehashing yes
  client-output-buffer-limit normal 0 0 0
  client-output-buffer-limit slave 256mb 64mb 60
  client-output-buffer-limit pubsub 32mb 8mb 60
  hz 10
  aof-rewrite-incremental-fsync yes
  ================================================================
  (3)redis特殊配置
  ================================================================
  #包含通用配置
  include /data/webserver/redis/conf/redis-common.conf
  #日志PID
  logfile /data/webserver/redis/logs/redis_6380.log
  pidfile /data/webserver/redis/pids/redis_6380.pid
  #监听tcp端口
  port 6380
  bind 10.161.180.111
  #最大可用内存
  maxmemory 2G
  #内存耗尽时采用的淘汰策略:
  # volatile-lru -> remove the key with an expire set using an LRU algorithm
  # allkeys-lru -> remove any key accordingly to the LRU algorithm
  # volatile-random -> remove a random key with an expire set
  # allkeys-random -> remove a random key, any key
  # volatile-ttl -> remove the key with the nearest expire time (minor TTL)
  # noeviction -> don't expire at all, just return an error on write operations
  maxmemory-policy allkeys-lru
  #aof存储文件
  appendfilename "appendonly-6380.aof"
  #rdb文件,只用于动态添加slave过程
  dbfilename dump-6380.rdb
  #cluster配置文件(启动自动生成)
  cluster-config-file nodes-6380.conf
  #部署在同一机器的redis实例,把auto-aof-rewrite搓开,防止瞬间fork所有redis进程做rewrite,占用大量内存
  auto-aof-rewrite-percentage 80-100
  ================================================================,
  因为我们要启动多个 redis 实例,虽然可以直接通过命令行来启动,但始终是不怎么方便的,所以我们按端口号分别建立实例目录,在实例目录里面创建redis特殊配置文件
  (4)初始化并构建集群
  分别启动实例,./redis-server ./6380/redis-6380.conf
  使用自带的ruby工具(redis-trib.rb)构建集群   redis-trib.rb create --replicas 0 10.161.180.111:6380 10.161.180.111:6381 10.161.180.111:6382
  需要注意的是执行 redis-trib.rb 命令需要 ruby 的支持,如果你没有安装可以先到 https://rubygems.org/gems/redis 下载,然后离线安装。
  sudo gem install redis-3.0.7.gem --local
  检查集群状态

  •   #redis-trib.rb的check子命令构建
  •   #ip:port可以是集群的任意节点
  •   redis-trib.rb check 10.161.180.111 :6380
  最后输出如下信息,没有任何警告或错误,表示集群启动成功并处于ok状态

  •   [OK] All nodes agree about slots configuration.
  •   >>> Check for open slots...
  •   >>> Check slots coverage...
  •   [OK] All 16384 slots covered.
  下面我们用 redis 自带的客户端测试一下:
DSC0001.jpg

  可以看到,虽然我们第一次连接的是6380端口,当我们去获取 testkey001 的时候,redis cluster 自动帮我们重定向到 6382 。
  当我们在 6382设置 testkey002 时,redis cluster 又重定向到 6380 。总的来说, redis 集群部署起来还是非常方便的.
  (5)添加新master节点
  redis-trib.rb add-node 10.168.228.78:6383 10.161.180.111:6380
  add-node  将一个节点添加到集群里面, 第一个是新节点ip:port, 第二个是任意一个已存在节点ip:port
  检查一下新节点是否已经加入: DSC0002.jpg
  node:新节点没有包含任何数据, 因为它没有包含任何slot。新加入的节点是一个主节点, 当集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。
  因此需要为新节点分配slot

  •   redis-trib.rb reshard 10.161.180.111:6383
  •   #根据提示选择要迁移的slot数量(ps:这里选择500)
  •   How many slots do you want to move (from 1 to 16384)? 500
  •   #选择要接受这些slot的node-id
  •   What is the receiving node ID? f51e26b5d5ff74f85341f06f28f125b7254e61bf
  •   #选择slot来源:
  •   #all表示从所有的master重新分配,
  •   #或者数据要提取slot的master节点id,最后用done结束
  •   Please enter all the source node IDs.
  •   Type 'all' to use all the nodes as source nodes for the hash slots.
  •   Type 'done' once you entered all the source nodes IDs.
  •   Source node #1:all
  •   #打印被移动的slot后,输入yes开始移动slot以及对应的数据.
  •   #Do you want to proceed with the proposed reshard plan (yes/no)? yes
  •   #结束
  (6)添加新的slave节点
  redis-cli连接上新节点shell,输入命令:cluster replicate 对应master的node-id
  或者执行redis-trib.rb命令,如下:
  redis-trib.rb add-node --slave 10.168.228.78:7382 10.161.180.111:6382
  (7)在线reshard 数据
  对于负载/数据均匀的情况,可以在线reshard slot来解决,方法与添加新master的reshard一样,只是需要reshard的master节点是老节点.
  redis-trib.rb reshard 10.161.180.111:6380
  (8)删除节点
  删除一个slave节点:

  •   #redis-trib del-node ip:port ''
  •   redis-trib.rb del-node 10.168.228.78:7386 'c7ee2fca17cb79fe3c9822ced1d4f6c5e169e378'
  删除一个master节点:
  删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点(目前只能把被删除master的slot迁移到一个节点上)

  •   #把10.161.180.111:6383当前master迁移到10.161.180.111:6380上
  •   redis-trib.rb reshard 10.161.180.111:6383
  •   #根据提示选择要迁移的slot数量(ps:这里选择500)
  •   How many slots do you want to move (from 1 to 16384)? 500(被删除master的所有slot数量)
  •   #选择要接受这些slot的node-id(10.161.180.111:6380)
  •   What is the receiving node ID? c4a31c852f81686f6ed8bcd6d1b13accdc947fd2 (ps:10.161.180.111:6380的node-id)
  •   Please enter all the source node IDs.
  •   Type 'all' to use all the nodes as source nodes for the hash slots.
  •   Type 'done' once you entered all the source nodes IDs.
  •   Source node #1:f51e26b5d5ff74f85341f06f28f125b7254e61bf(被删除master的node-id)
  •   Source node #2:done
  •   #打印被移动的slot后,输入yes开始移动slot以及对应的数据.
  •   #Do you want to proceed with the proposed reshard plan (yes/no)? yes
  删除空master节点:
  redis-trib.rb del-node 10.161.180.111:6383 'f51e26b5d5ff74f85341f06f28f125b7254e61bf'
  目前c#客户端还不能很好的支持 redis 集群,下一篇将介绍如何使用代理来实现 redis 集群。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-631261-1-1.html 上篇帖子: redis的一次持久化*** 下篇帖子: Redis主从同步
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表