------------恢复内容开始------------
一. 主从架构
原因: 单机版redis存在读写瓶颈, 单机版redis只能承受11万/s的读和8w/s的写.
主从架构: 多台tomcat对应3台以及以上redis,其中一台可读写, 其他的节点只读.
1.1配置文件准备:
(1)docker-compose.yml文件(以 3个redis库, 一个主库,两个从库为例)
-
- 三个redis他们的containner_name和ports都不一样
- 从库需要设置links,指向主库名,
- 从库之间不能通信, 主从库之间可以
# redis主从架构的docker-compose.yml version: '3.1' services: redis1: image: daocloud.io/library/redis:5.0.7 container_name: redis1 restart: always environment: - TZ=Asia/Shanghai ports: - 7000:6379 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis2: image: daocloud.io/library/redis:5.0.7 container_name: redis2 restart: always environment: - TZ=Asia/Shanghai ports: - 7001:6379 volumes: - ./conf/redis2.conf:/usr/local/redis/redis.conf links: - redis1:master command: ["redis-server","/usr/local/redis/redis.conf"] redis3: image: daocloud.io/library/redis:5.0.7 container_name: redis3 restart: always environment: - TZ=Asia/Shanghai ports: - 7002:6379 volumes: - ./conf/redis3.conf:/usr/local/redis/redis.conf links: - redis1:master command: ["redis-server","/usr/local/redis/redis.conf"]
(2) redis2.conf和redis3.conf的设置:从节点指定master节点 通过master可以找到容器, 通过6379可以找到容器内部端口号
replicaof master 6379
1.2 创建步骤:
- 在/opt下创建docker_redis_master_slave目录
- 在docker_redis_master_slave目录下vi docker-compose.yml文件, 即上面准备的文件
- 在指示的数据卷映射中创建conf目录, 并创建 redis2.conf, redis1.conf redis3.conf作为三个库的配置文件
- 在 redis2.conf, redis3.conf两文件中指明master
- 命令docker-compose up -d启动,
volumes:
- ./conf/redis2.conf:/usr/local/redis/redis.conf
主从通信的实验: 进入redis库后, 可以通过info命令查看库信息, 其中有role属性,
第一张图的主节点可以存取数据, 而第二张图片的从节点只能取数据, 不能存.
二. 哨兵架构
原因: 主从架构存在缺陷: (单点故障问题)当master节点宕机后, 主从架构就瘫痪了, 从节点无法跟master通信
哨兵结构:
-
- 每个redis容器里都有一个哨兵,
- 各容器内的redis服务和各自的哨兵可以互相通信
- 所有哨兵之间可以互相通信
- 当master宕机后, 看守它的哨兵会向其他哨兵发出信号,
- 所有哨兵通过投票, 在剩余正常运行的slave中选出一个作为master继续运行
哨兵的配置文件
# 哨兵需要后台启动 daemonize yes # 主节点指定Master节点的ip和端口号 sentinel monitor master localhost 6379 2 # 从节点指定Master节点的ip和端口号 sentinel monitor master master 6379 2 # 哨兵每隔多少秒监听一次redis架构 sentinel down-after-milliseconds master 1000
设置哨兵的conf:
(1)在conf目录下, vi 3个sentinel文件, 并写上述配置文件(主从节点需要各自去注释别人的)
(2) 在redis-config.yml里添加数据卷, 可以在容器中使用哨兵的配置:
- ./conf/sentinel1.conf:/data/sentinel.conf
(3)在每个容器内部(注意是容器内部)启用哨兵: redis-sentinel sentinel.conf(因为data里有sentinel.conf,做过映射)
在master节点上 , 可以写操作
然后停掉master: docker stop 容器id
分别进入两个slave容器, 发现其中一个变成了master.
三.redis集群
redis主从架构解决了效率问题, 哨兵架构解决了单点故障问题.
但当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中。cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。能动态扩充
集群特点:
- redis集群是无中心的, 不像主从和哨兵那样, 有个master.
- 乒乓机制: 每个节点都相互发消息
- 投票机制: 当乒乓机制回应异常, 就采取投票, 谁的票多就表明谁宕机,集群节点的数量必须是 2n+1个节点.
- redis的集群采用hash槽来存数据, 所以可以动态扩充. 默认有16384个哈希槽, 存数据时, 通过hash算法, 将key存到相应的hash槽中.
- 每个redis节点, 都维护着一定数量的hash槽.
- 每一个节点后面, 都跟着一个从节点, 和该节点的数据同步. 防止节点宕机
redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉
现在我们是三个主节点分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:
-
节点A覆盖0-5460;
-
节点B覆盖5461-10922;
-
节点C覆盖10923-16383.
获取数据:
如果存入一个值,按照redis cluster哈希槽的算法: CRC16('key')384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据新增一个主节点:
新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样: -
节点A覆盖1365-5460
-
节点B覆盖6827-10922
-
节点C覆盖12288-16383
-
节点D覆盖0-1364,5461-6826,10923-12287
同样删除一个节点也是类似,移动完成后就可以删除这个节点了。
上面那个例子里, 集群有ABC三个主节点, 如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。
所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A、B、C, 以及从节点A1、B1、C1, 那么即使B挂掉系统也可以继续正确工作。
B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。 当B重新开启后,它就会变成B1的从节点。
不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了。
3.2搭建redis集群
如果搭建3个主节点, 并且每个节点都有一个从节点, 那么总共需要搭建6个节点
(1) 准备docker-compose.yml文件和6个redisx.conf配置文件
# redis集群 version: '3.1' services: redis1: image: daocloud.io/library/redis:5.0.7 container_name: redis1 restart: always environment: - TZ=Asia/Shanghai ports: - 7001:7001 - 17001:17001 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis2: image: daocloud.io/library/redis:5.0.7 container_name: redis2 restart: always environment: - TZ=Asia/Shanghai ports: - 7002:7002 - 17002:17002 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis3: image: daocloud.io/library/redis:5.0.7 container_name: redis3 restart: always environment: - TZ=Asia/Shanghai ports: - 7003:7003 - 17003:17003 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis4: image: daocloud.io/library/redis:5.0.7 container_name: redis4 restart: always environment: - TZ=Asia/Shanghai ports: - 7004:7004 - 17004:17004 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis5: image: daocloud.io/library/redis:5.0.7 container_name: redis5 restart: always environment: - TZ=Asia/Shanghai ports: - 7005:7005 - 17005:17005 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"] redis6: image: daocloud.io/library/redis:5.0.7 container_name: redis6 restart: always environment: - TZ=Asia/Shanghai ports: - 7006:7006 - 17006:17006 volumes: - ./conf/redis1.conf:/usr/local/redis/redis.conf command: ["redis-server","/usr/local/redis/redis.conf"]
6个redis.conf文件(每个文件都以redis1.conf redis2.conf....并改下端口为7001, 7002...)
# redis.conf # 指定redis端口 port 7001 # 开启redis集群 cluster-enabled yes # 集群信息的文件 cluster-config-file nodes-7001.conf # 集群的对外ip地址 cluster-announce-ip 192.168.43.173 # 集群的对外端口 cluster-announce-port 7001 # 集群的对外总线 cluster-announce-bus-port 17001
(3)启动6个redis容器
(4) 进入任意一个容器内, 通过命令来创建集群
redis-cli --cluster create ip:端口号 ... --cluster-replicas 从节点数量
注意: 该才做就会显示master和slave, 并且分配slots; 下图0-5460 被分配到7001....
(5)通过redis-cli -h -p -c操作redis; -c表示可以切换redis节点.
(5)java连接redis集群,
new JedisCluster(参数是一个hostandpot的集合)