Redis数据库与传统数据库属于并行关系,也就是说传统的关系型数据库保存的是结构化数据,而Redis保存的是一些所谓的 临时
数据,由于Redis具有一项很强的功能 持久化数据
,发现Redis好像也能够作一些传统数据库的开发。可是如今Redis除了能够进行数据的存储以外,实际上也能够在一些系统的架构设计之中做为数据的缓冲点:
若是要想实现主从模式的配置,首先必定要准备出三台Redis实例,本次为了方便将在一台主机上进行模拟,也就是说在这一台主机上将准备出三个Redis实例,分别对应的端口为:637九、6380、6381,其中6379运行的Redis服务为主服务,而其它两个端口运行的服务为从服务。css
1.若是要想进行主从的模式匹配,主服务器上不须要作出任何的变化,也就是说主服务器根本就不关心是否有从服务器;java
2.全部的从服务的配置文件redis-6380.conf、redis-6381.conf必需要求明确的设置出它对应的主服务器。linux
vim /usr/local/redis/conf/redis-6380.conf
; slaveof 192.168.125.161 6379
masterauth mldnjava
3.启动全部的Redis数据服务:nginx
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
4.登陆6379端口的Redis服务主服务查看全部的副本信息:git
/usr/local/redis/bin/redis-cli -h 192.168.125.161 -p 6379 -a mldnjava info replication
connected_slaves:2 slave0:ip=192.168.125.161,port=6380,state=online,offset=99,lag=0 slave1:ip=192.168.125.161,port=6381,state=online,offset=99,lag=0
若是能够发现以上的信息就表示如今6379下有两个从节点。github
5.操做主节点6379的数据:set mldn java
redis
get mldn
; (error) READONLY You can't write against a read only slave.
。备注:
主从设计的最大好处在于:能够自动对数据作备份; 主从设计模式的最大缺点在于:只可以作备份,而出现灾难以后没法当即恢复。算法
只要是进行高可用的架构部署,那么就必须保证多节点,在Redis里面使用了主从模式能够实现多节点配置,可是传统的主从模式的设计有一个缺陷:一旦Master主机出现了问题以后,两台Slave主机将没法提供正常的工做支持,例如:slave主机为只读主机,并且若是要想继续提供支持,那么你至少应该经过剩余的几台slave里面去推选出一个新的master,而且最为重要的是,这个新的master还必须可以被用户的程序找到。
哨兵机制(Sentinel)
Redis哨兵是redis官方推荐的redis高可用(HA)解决方案之一;spring
sentinel的功能:
监控(Monitoring),sentinel时刻监控着redis master-slave 是否正常运行;
通知(Notification),sentinel 能够经过api来通知管理员,被监控的 redis master-slave 出现了问题;
自动故障转移(Automatic failover),当redis master出现故障不可用状态,sentinel 会开始一次故障转移,将其中一个slave 提高为新的 master ,将其余的 slave 将从新配置使用新的 master 同步,并使用redis 的服务器应用程序在链接时受到使用新的地址链接;
配置提供者(Configuration provider),sentinel 做为在集群中的权威来源,客户端链接到 sentinel 来获取某个服务的当前 redis 主服务器的地址和其余信息。当前故障转移发生时,sentinel 会报告新地址。sql
1.若是要想进行哨兵配置及使用,请确保你的主机上已经准备好了Redis服务,本次将在一台主机上模拟哨兵机制,如今的实现原则:一台主机运行三个哨兵,而且该哨兵运行端口不一样,可是这三个哨兵都要去监控同一个master的地址。
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
2.经过redis源代码拷贝出哨兵运行程序: cp /usr/local/src/redis-3.2.9/src/redis-sentinel /usr/local/redis/bin/
3.全部的哨兵若是要想运行必定要准备出一个配置文件:sentinel.conf;
/usr/local/src/redis-3.2.9/sentinel.conf
;4.创建sentinel-26379.conf配置文件:vim /usr/local/redis/conf/sentinel-26379.conf
;
mkdir -p /usr/data/redis/{sentinel-26379,sentinel-26380,sentinel-26381}
;配置哨兵监听端口:port 26379
配置哨兵的工做目录:dir /usr/data/redis/sentinel-26379
设置监控的master:sentinel monitor mymaster 192.168.125.161 6379 2
备注:
设置的mymaster只是一个表明名称,若是你一个哨兵监控多个master,则这个名称必定要有所不一样,然后2
表示若是有两个哨兵认为你出现了问题,则你应该下线选举出新的master
设置master的认证信息:sentinel auth-pass mymaster mldnjava
设置master不活跃的时间:sentinel down-after-milliseconds mymaster 30000
选举新的master失败时间:sentinel failover-timeout mymaster 180000
只有一个master同步:sentinel parallel-syncs mymaster 1
撤销Redis保护模式:protected-mode no
随后按照这样的配置分别创建sentinel-26380.conf、sentinel-26381.conf两个配置文件。
cp /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/conf/sentinel-26380.conf cp /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/conf/sentinel-26381.conf
建议将此时的配置作一个副本保留一下:cp /usr/local/redis/conf/* /usr/data/redis/back/
5.启动三个哨兵进程:
/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26380.conf /usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26381.conf
经过哨兵的信息输出能够发现以下特色:
+slave
:当一个哨兵启动以后若是已经肯定能够链接到了master节点,则自动追加全部的slave节点;+sentinel
:每当启动一个新的哨兵进程后会自动进行哨兵增长的信息提示;6.直接kill掉当前监控的master主机,随后会发现有以下提示信息:
+sdown master mymaster 192.168.125.161 6379
:当前的master主机已经下线了;+vote-for-leader
:进行从新的投票选举;+slave-reconf-sent slave 192.168.125.161:6381
:从主机会自动修改redis.conf配置文件;+switch-master mymaster 192.168.125.161 6379 192.168.125.161 6380
:6380为新的master;7.若是此时的6379的进程又从新启动成功了,那么这个时候能够考虑经过命令作一个从的设置,必定要求设置好redis-6379.conf配置文件中的masterauth属性,若是不进行此项配置则没法链接到master主机。
如今为止已经成功的实现了哨兵处理机制,可是对于程序的编写依然须要注意一点,若是要进行哨兵的处理操做,那么必定要求经过哨兵来取得可用的master地址。
package cn.mldn.jedis; import java.util.HashSet; import java.util.Set; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisSentinelPool; public class JedisSentinel { public static final String MASTER_NAME = "mymaster" ; // 定义哨兵的Master配置名称 public static final int TIMEOUT = 2000 ; // 链接超时时间 public static final String REDIS_AUTH = "mldnjava" ; // 认证密码 public static final int MAX_TOTAL = 1000 ; // 设置最大链接数 public static final int MAX_IDLE = 200 ; // 设置最小维持链接数 public static final int MAX_WAIT_MILLIS = 1000 ; // 设置最大等待时间 public static void main(String[] args) { // 若是要经过哨兵机制进行Redis访问,那么必需要明确的设置出全部可使用的哨兵的地址与端口 Set<String> sentinels = new HashSet<String>() ; // 设置全部的哨兵的处理地址信息 sentinels.add("192.168.125.161:26379") ; // 哨兵的地址 sentinels.add("192.168.125.161:26380") ; // 哨兵的地址 sentinels.add("192.168.125.161:26381") ; // 哨兵的地址 // 首先若是要想使用Jedis链接池,则必须有一个类能够保存全部链接池相关属性的配置项 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 设置最大链接数 poolConfig.setMaxIdle(MAX_IDLE); // 设置空闲的链接数 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待时间 // 此时全部的链接应该经过哨兵机制取得,因此这个时候应该使用JedisSentinelPool对象 JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, poolConfig); // 创建一个哨兵的链接池 Jedis jedis = pool.getResource() ; // 经过链接池获取链接对象 jedis.auth(REDIS_AUTH) ; System.out.println(jedis); jedis.set("mldn", "www.mldn.cn") ; jedis.close(); pool.close(); // 关闭链接池 } }
在以前使用的SpringData进行Redis访问的时候采用的是一个Spring内部支持的链接池,而且只有一个链接地址,可是若是要进行哨兵的配置,则须要将全部的哨兵地址都进行配置。
1.修改redis.properties配置文件,追加全部的哨兵配置地址:
# 追加全部的哨兵的访问处理地址以及对应的端口号 redis.sentinel-1.host=192.168.68.165 redis.sentinel-2.host=192.168.68.165 redis.sentinel-3.host=192.168.68.165 redis.sentinel-1.port=26379 redis.sentinel-2.port=26380 redis.sentinel-3.port=26381 # 定义哨兵的master的名称 redis.sentinel.master.name=mymaster # Redis的认证信息,认证信息密码 redis.password=mldnjava # Redis链接的超时时间 redis.timeout=2000 # 设置最大的可用链接数 redis.pool.maxTotal=100 # 最小维持的可用链接数 redis.pool.maxIdle=20 # 最大等待时间 redis.pool.maxWaitMillis=2000
2.修改spring-redis.xml配置文件,在这个配置文件里面须要将以前的链接池作一些更改:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <!-- 若是要进行Redis处理用户应该不去关注具体的序列化或反序列化操做,这一切都应该交给SpringData处理 --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 定义Redis链接工厂 --> <property name="keySerializer"> <!-- 定义序列化Key的程序处理类 --> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <!-- 处理value数据的操做 --> <!-- 明确表示若是要进行value数据保存的时候,保存的对象必定要使用JDK提供的序列化处理类 --> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <!-- 处理hash数据的保存 --> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!-- 进行全部的哨兵地址的配置项 --> <bean id="sentinelsConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"><!-- 配置master的节点名称 --> <bean class="org.springframework.data.redis.connection.RedisNode"> <!-- 经过资源文件读取出master的名称进行配置 --> <property name="name" value="${redis.sentinel.master.name}"/> </bean> </property> <!-- 配置全部哨兵的链接地址信息 --> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-1.host}"/> <constructor-arg name="port" value="${redis.sentinel-1.port}"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-2.host}"/> <constructor-arg name="port" value="${redis.sentinel-2.port}"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-3.host}"/> <constructor-arg name="port" value="${redis.sentinel-3.port}"/> </bean> </set> </property> </bean> <!-- 首先进行Jedis链接池的相关配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.pool.maxTotal}"/> <!-- 最大可用链接数 --> <property name="maxIdle" value="${redis.pool.maxIdle}"/> <!-- 最小维持链接数 --> <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/> <!-- 最大等待时间 --> </bean> <!-- 进行ConnectionFactory的配置 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg name="sentinelConfig" ref="sentinelsConfiguration"/> <property name="poolConfig" ref="jedisPoolConfig"/> <!-- 引用进行链接池的配置项 --> <property name="password" value="${redis.password}"/> <!-- 定义的是链接密码,认证密码 --> </bean> </beans>
无论你如今电脑性能有多好,只要你运行了Redis,那么就有可能形成一种很是可怕局面:你电脑的内存将马上被占满,并且一台Redis数据库的性能终归是有限制的,那么如今若是要求保证用户的执行速度快,就须要使用集群的设计。而对于集群的设计主要的问题就是解决单实例Redis的性能瓶颈。
Twemproxy是一个专门为了这种nosql数据库设计的一款代理工具软件,这个工具软件最大的特征是能够实现数据的分片处理。所谓的分片指的是根据必定的算法将要保存的数据保存到不一样的节点之中。
有了分片以后数据的保存节点就可能有无限多个,可是理论上若是要真进行集群的搭建,每每要求三台节点起步。
Twemproxy
Twemproxy 的特性
最主要功能:用户再也不直接操做真正的Redis,并且支持高性能的数据访问,并且支持分片处理,能够操做Redis集群。
本次预计使用三台Redis服务器,而且考虑到实际的应用环境,这三台的Master分别有各自的两个slave主机。因而如今给出本次使用的主机列表:
主机名称 | IP地址 | 描述 |
---|---|---|
tw-redis-server-a | 192.168.125.162 | Reids master数据服务:6379 Reids slave数据服务:6380 Reids slave 数据服务:6381 |
tw-redis-server-b | 192.168.125.163 | Reids master 数据服务:6379 Reids slave 数据服务:6380 Reids slave 数据服务:6381 |
tw-redis-server-c | 192.168.125.164 | Reids master 数据服务:6379 Reids slave 数据服务:6380 Reids slave 数据服务:6381 |
1.tw-redis-server-*考虑到主机的通用性,全部的主机都建议修改主机名称以及对应的hosts文件:
vim /etc/hostname
,修改完成以后从新启动;vim /etc/hosts
,作好ip地址与主机名称的映射;2.tw-redis-server-a本次主机经过以前的配置得来里面已经实现了基本的配置环境,可是依然须要由用户本身来配置主从关系:
vim /usr/local/redis/conf/redis-6380.conf
slaveof 192.168.125.162 6379 masterauth mldnjava
vim /usr/local/redis/conf/redis-6381.conf
slaveof 192.168.125.162 6379 masterauth mldnjava
3.tw-redis-server-*启动全部Redis数据库的实例
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
此时就至关于有就台Redis数据库,然后有三台是Master节点,六台为Slave节点。
4.tw-redis-server-*查看从节点状态:
/usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 6379 -a mldnjava info replication
一台主机的redis客户端,只要你链接的ip、端口、密码正确,那么均可以链接到任意的主机上。
如今关键的问题就在于如何进行Redis分片处理,而分片处理的关键工具就是twemproxy工具,可是此工具给出的是一个源代码,因此使用以前必定要先进行编译处理。
1.tw-proxy-server-a将twemproxy-0.4.1.tar.gz源代码开发包上传到Linux系统之中,随后将其解压缩到源代码目录:
tar xzvf /srv/ftp/twemproxy-0.4.1.tar.gz -C /usr/local/src/
2.tw-proxy-server-a进入到源代码所在的目录:cd /usr/local/src/twemproxy-0.4.1/
autoreconf -fvi
;mkdir -p /usr/local/twemproxy
;./configure --prefix=/usr/local/twemproxy
;make && make install
;3.tw-proxy-server-a随后须要配置一个twemproxy的配置文件,这个配置文件考虑到随后与其它机制的整合,名称必定要设置为 redis_master.conf
:
mkdir -p /usr/local/twemproxy/conf
;cp /usr/local/src/twemproxy-0.4.1/conf/nutcracker.yml /usr/local/twemproxy/conf/redis_master.conf
4.tw-proxy-server-a编辑redis_master.conf文件:vim /usr/local/twemproxy/conf/redis_master.conf
redis_master: listen: 0.0.0.0:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true redis: true redis_auth: mldnjava server_retry_timeout: 2000 server_failure_limit: 1 servers: - 192.168.125.162:6379:1 - 192.168.125.163:6379:1 - 192.168.125.164:6379:1
以上配置的 redis_master
的名称与配置文件是同样的,并且必须同样,同时在本文件里面配置了redis访问密码,以及twemproxy全部可能代理到的redis服务器master节点。
5.tw-proxy-server-a{坑}twemproxy自己自带有一个配置文件的检测工具:
/usr/local/twemproxy/sbin/nutcracker -t /usr/local/twemproxy/conf/redis_master.conf
6.tw-proxy-server-a启动twemproxy的服务:
mkdir -p /usr/local/twemproxy/{pid,logs}
/usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_master.conf -p /usr/local/twemproxy/pid/redis_master.pid -o /usr/local/twemproxy/logs/redis_master.log -d
7.tw-proxy-server-a这个时候一旦twemproxy
启动以后就表示该进程是一个redis
的代理进程, 全部的服务能够经过twemproxy
访问,而它的地址是:22121
,随意找到一个redis
客户端便可。 /usr/local/redis/bin/redis-cli -h 192.168.68.170 -p 22121 -a mldnjava
如今链接的直接为代理,随后找到各自的redis数据库的服务。 /usr/local/redis/bin/redis-cli -h 192.168.68.167 -p 6379 -a mldnjava
8.编写java程序经过jedis访问:
package cn.mldn.jedis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class TwemproxyDemo { public static final String REDIS_HOST = "192.168.68.170" ; // 主机地址 public static final int REDIS_PORT = 22121 ; // 端口号 public static final int TIMEOUT = 2000 ; // 链接超时时间 public static final String REDIS_AUTH = "mldnjava" ; // 认证密码 public static final int MAX_TOTAL = 1000 ; // 设置最大链接数 public static final int MAX_IDLE = 200 ; // 设置最小维持链接数 public static final int MAX_WAIT_MILLIS = 1000 ; // 设置最大等待时间 public static final boolean TEST_ON_BORROW = true ; // 是否进行可用测试 public static void main(String[] args) { // 首先若是要想使用Jedis链接池,则必须有一个类能够保存全部链接池相关属性的配置项 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 设置最大链接数 poolConfig.setMaxIdle(MAX_IDLE); // 设置空闲的链接数 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待时间 poolConfig.setTestOnBorrow(TEST_ON_BORROW); // 是否要进行链接测试,以保证返回的链接为可用链接 JedisPool pool = new JedisPool(poolConfig,REDIS_HOST,REDIS_PORT,TIMEOUT,REDIS_AUTH) ; Jedis jedis = pool.getResource() ; // 经过链接池获取链接对象 for (int x = 0 ; x < 1000 ; x ++) { jedis.set("mldn-" + x, "www.mldn.cn") ; } jedis.close(); pool.close(); // 关闭链接池 } }
Twemproxy
若是要与Redis
集成使用的是Redis
的Master
节点,由于只有Master
节点才具有有写功能,而全部的Slave节点只具有有只读的数据功能,如今的思考点暂时不放在twemproxy
上,而如今的问题集中在后端的全部Redis
节点之中,由于Redis
存在有主从关系,那么一旦某一个Redis
的Master
被干掉了,则必定要从新选举出一个新的Master
节点,可是这个时候会出现有一个问题:twemproxy
所使用的配置文件是单独存在的:
redis_master: listen: 0.0.0.0:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true redis: true redis_auth: mldnjava server_retry_timeout: 2000 server_failure_limit: 1 servers: - 192.168.125.162:6379:1 - 192.168.125.163:6379:1 - 192.168.125.164:6379:1
若是要进行哨兵机制运行至少须要有三台或以上的主机,本次已经有了三台Redis集群,因此为了方便,在以前的三台主机上进行Sentinel配置,如今主机所运行的进程关系以下:
主机名称 | IP地址 | 描述 |
---|---|---|
tw-redis-server-a | 192.168.125.162 | Redis服务637九、6380、6381 Sentinel服务 26379 |
tw-redis-server-b | 192.168.125.163 | Redis服务637九、6380、6381 Sentinel服务 26379 |
tw-redis-server-c | 192.168.125.164 | Redis服务637九、6380、6381 Sentinel服务 26379 |
tw-proxy-server-a | 192.168.125.165 | Twemproxy代理服务 Sentinel服务26379 |
1.tw-redis-server-*在全部的主机上创建哨兵机制的保存数据目录:mkdir -p /usr/data/redis/sentinel
2.tw-redis-server-a进行哨兵配置文件的编写:vim /usr/local/redis/conf/sentinel.conf
port 26379 dir /usr/data/redis/sentinel protected-mode no sentinel monitor redis_master_group1 192.168.125.162 6379 2 sentinel auth-pass redis_master_group1 mldnjava sentinel down-after-milliseconds redis_master_group1 10000 sentinel failover-timeout redis_master_group1 10000 sentinel parallel-syncs redis_master_group1 1 sentinel monitor redis_master_group2 192.168.125.163 6379 2 sentinel auth-pass redis_master_group2 mldnjava sentinel down-after-milliseconds redis_master_group2 10000 sentinel failover-timeout redis_master_group2 10000 sentinel parallel-syncs redis_master_group2 1 sentinel monitor redis_master_group3 192.168.125.164 6379 2 sentinel auth-pass redis_master_group3 mldnjava sentinel down-after-milliseconds redis_master_group3 10000 sentinel failover-timeout redis_master_group3 10000 sentinel parallel-syncs redis_master_group3 1
3.tw-redis-server-a将哨兵的配置文件发送到其它主机上:
拷贝到 tw-redis-server-b
主机:scp /usr/local/redis/conf/sentinel.conf 192.168.125.163:/usr/local/redis/conf/
拷贝到 tw-redis-server-c
主机:scp /usr/local/redis/conf/sentinel.conf 192.168.125.164:/usr/local/redis/conf/
4.tw-redis-server-*考虑到哨兵机制运行以后会进行配置文件的变动,那么最好的作法是将这些配置文件作一个副本,这样测试起来会比较方便:cp /usr/local/redis/conf/* /usr/data/redis/back/
5.tw-redis-server-*启动哨兵进程:/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
若是要想在twemproxy
之中与哨兵整合,而且实现twemproxy
进程的从新启动,那么有一个前提必须有保证:你的twemproxy
运行的主机必定要提供有哨兵机制,目的是为了与其它的哨兵进行整合处理。
1.tw-redis-server-a将哨兵的配置文件拷贝到tw-proxy-server-a主机上;
scp /usr/data/redis/back/sentinel.conf 192.168.68.170:/usr/local/redis/conf;
2.tw-proxy-server-a经过源代码文件拷贝出哨兵进程的启动项:cp /usr/local/src/redis-3.2.9/src/redis-sentinel /usr/local/redis/bin/
3.tw-proxy-server-a启动哨兵机制,这个哨兵机制是为了让Shell脚本能够整合到全部的哨兵机制里;
/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
4.tw-proxy-server-a为了方便进行shell脚本的保存在twemproxy程序目录中建立有一个sh的目录:mkdir -p /usr/local/twemproxy/sh
5.tw-proxy-server-a创建一个能够进行哨兵重启twemproxy进程的shell脚本:
编辑命令:vim /usr/local/twemproxy/sh/client-reconfig.sh
#!/bin/sh # monitor_name="$1" master_old_ip="$4" master_old_port="$5" master_new_ip="$6" master_new_port="$7" twemproxy_name=$(echo $monitor_name |awk -F'_' '{print $1"_"$2}') twemproxy_bin="/usr/local/twemproxy/sbin/nutcracker" twemproxy_conf="/usr/local/twemproxy/conf/${twemproxy_name}.conf" twemproxy_pid="/usr/local/twemproxy/pid/${twemproxy_name}.pid" twemproxy_log="/usr/local/twemproxy/logs/${twemproxy_name}.log" twemproxy_cmd="${twemproxy_bin} -c ${twemproxy_conf} -p ${twemproxy_pid} -o ${twemproxy_log} -d" sed -i "s/${master_old_ip}:${master_old_port}/${master_new_ip}:${master_new_port}/" ${twemproxy_conf} ps -ef |grep "${twemproxy_cmd}" |grep -v grep |awk '{print $2}'|xargs kill ${twemproxy_cmd} sleep 1 ps -ef |grep "${twemproxy_cmd}" |grep -v grep
6.tw-proxy-server-a为脚本授予所有执行权限:chmod 777 /usr/local/twemproxy/sh/client-reconfig.sh
7.tw-proxy-server-a如今要链接本机的哨兵进程,这样才能够与此脚本文件有关联:
/usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group1 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh /usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group2 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh /usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group3 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh
那么此时哨兵机制一旦发生了从新的选举以后,那么会马上从新启动twemproxy的相关进程。
8.tw-redis-server-a杀死掉redis-6379服务进程,这样master就消失了,消失以后应该会触发脚本,会从新配置redis_master.conf文件,这个时候对应在twemproxy主机上的哨兵会自动进行twemproxy的进程从新启动,以此保证twemproxy中Redis主机的高可用状态。
Twemproxy主要功能在于数据的分片处理,并且会发如今整个的Redis集群里面,若是用户要想访问Redis集群必须经过Twemproxy,因而这个时候就有可能形成一种问题:
HAProxy:haproxy是一个开源的,高性能的,基于TCP第四层和http第七层应用的千万级高并发负载均衡软件;
HAProxy优势:
如今为了观察问题准备出来了三台twemproxy主机,然后如今再须要准备出一台haproxy主机tw-haproxy-server-a。然后经过这个haproxy主机先进行haproxy运行的处理。
1.tw-haproxy-server-a将haproxy
的开发包上传到系统之中,随后为其进行解压缩控制:tar xzvf /srv/ftp/haproxy-1.5.18.tar.gz -C /usr/local/src/
2.tw-haproxy-server-a进入到haproxy源代码目录:cd /usr/local/src/haproxy-1.5.18/
Haproxy
编译后的保存目录:mkdir -p /usr/local/haproxy
HAProxy
的处理必定要选择好你当前的系统架构的信息:make TARGET=linux26 PREFIX=/usr/local/haproxy ARCH=x86_64
make install PREFIX=/usr/local/haproxy
;安装完成以后会在 /usr/local/haproxy
目录下存在有:doc、sbin、share三个目录;
3.tw-haproxy-server-a创建一个haproxy的数据保存工做目录:mkdir -p /usr/data/haprox
4.tw-haproxy-server-a经过源代码拷贝出一个配置文件到指定的目录之中;
cp /usr/local/src/haproxy-1.5.18/examples/haproxy.cfg /usr/local/haproxy/
5.tw-haproxy-server-a编辑 haproxy.cfg
配置文件:vim /usr/local/haproxy/haproxy.cfg
global
log 127.0.0.1 local0 log 127.0.0.1 local1 notice #log loghost local0 info maxconn 4096 chroot /usr/local/haproxy pidfile /usr/data/haproxy/haproxy.pid uid 99 gid 99 daemon #debug #quiet defaults log global mode tcp option httplog option dontlognull retries 3 redispatch maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000 listen appli1-rewrite 0.0.0.0:10001 cookie SERVERID rewrite balance roundrobin option abortonclose option redispatch retries 3 maxconn 2000 timeout connect 5000 timeout client 50000 timeout server 50000 listen proxy_status bind :16001 mode tcp balance roundrobin server tw_proxy_1 192.168.125.165:22121 check inter 10s server tw_proxy_2 192.168.125.166:22121 check inter 10s server tw_proxy_3 192.168.125.167:22121 check inter 10s frontend admin_stats bind :7777 mode http stats enable option httplog maxconn 10 stats refresh 30s stats uri /admin stats auth mldn:java stats hide-version stats admin if TRUE
6.tw-haproxy-server-a须要进行haproxy的进程启动:
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg
7.若是如今要想确认当前已经正常启动,则能够经过管理控制台查看:http://192.168.125.165:7777/admin
1.若是要想正常完成测试,必定要先保证Redis、sentinel、twemproxy的服务进程所有正常启动;
ps -ef | grep redis
cp /usr/data/redis/back/sentinel.conf /usr/local/redis/conf/
/usr/local/redis/bin/redis-server /usr/local/redis/conf/sentinel.conf
2.tw-proxy-server-*启动twemproxy的进程:
/usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_master.conf -p /usr/local/twemproxy/pid/redis_master.pid -o /usr/local/twemproxy/logs/redis_master.log -d
3.先保证各个 twemproxy
的节点能够正常使用。
4.使用haproxy进行代理操,使用redis客户端登陆:/usr/local/redis/bin/redis-cli -h 192.168.125.167 -p 16001 -a mldnjava
5.经过jedis的java客户端进行数据访问:
package cn.mldn.jedis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class TwemproxyDemo { public static final String REDIS_HOST = "192.168.125.167" ; // 主机地址 public static final int REDIS_PORT = 16001 ; // 端口号 public static final int TIMEOUT = 2000 ; // 链接超时时间 public static final String REDIS_AUTH = "mldnjava" ; // 认证密码 public static final int MAX_TOTAL = 1000 ; // 设置最大链接数 public static final int MAX_IDLE = 200 ; // 设置最小维持链接数 public static final int MAX_WAIT_MILLIS = 1000 ; // 设置最大等待时间 public static void main(String[] args) { // 首先若是要想使用Jedis链接池,则必须有一个类能够保存全部链接池相关属性的配置项 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 设置最大链接数 poolConfig.setMaxIdle(MAX_IDLE); // 设置空闲的链接数 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待时间 JedisPool pool = new JedisPool(poolConfig,REDIS_HOST,REDIS_PORT,TIMEOUT,REDIS_AUTH) ; Jedis jedis = pool.getResource() ; // 经过链接池获取链接对象 for (int x = 0 ; x < 10000 ; x ++) { jedis.set("mldn-" + x, "www.mldn.cn") ; } jedis.close(); pool.close(); // 关闭链接池 } }
若是此时的程序出现有以下的错误信息:
Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: READONLY You can't write against a read only slave.
若是面对Redis
集群,只是依靠twemproxy
的分片是不够的,还须要有一系列的代理设计,例如:HAProxy能够实现负载均衡设计。
Keepalived
是一个基于VRRP协议来实现的服务高可用方案,能够利用其来避免IP单点故障,相似的工具还有heartbeat、corosync、pacemaker
。可是它通常不会单独出现,而是与其余负载均衡技术如lvs、haproxy、nginx一块儿工做来达到集群的高可用。
下载地址:http://wwww.keepalived.org/
keepalived组件给出的是一个源代码的开发包,因此你依然须要在你的系统之中进行编译与配置处理。
1.tw-haproxy-server-a主机将keepalived开发包上传到Linux系统之中,随后将其进行解压缩。
tar xzvf /srv/ftp/keepalived-1.2.24.tar.gz -C /usr/local/
2.tw-haproxy-server-a主机为了配置方便进行一下改名处理:
mv /usr/local/keepalived-1.2.24/ /usr/local/keepalived
3.tw-haproxy-server-a主机进入到keepalived组件包的目录:cd /usr/local/keepalived/
4.tw-haproxy-server-a主机进行编译处理:
./configure --prefix=/usr
make && make install
5.tw-haproxy-server-a主机将keepalived的配置文件拷贝到 /etc/keepalived
目录之中;
mkdir -p /etc/keepalived
cp /usr/etc/keepalived/keepalived.conf /etc/keepalived/
6.tw-haproxy-server-a主机编辑keepalived.conf配置文件:vim /etc/keepalived/keepalived.conf
cat /proc/net/dev、ifconfig
,如今的名称为 ens33
;! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.68.250 } } virtual_server 192.168.125.250 16001 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.125.168 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } real_server 192.168.125.169 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } }
7.tw-haproxy-server-b主机关闭 tw-haproxy-server-a
这台虚拟机,然后将其克隆为 tw-haproxy-server-b
主机。
8.tw-haproxy-server-b主机修改 keepalived.conf
配置文件,必定要设置为BACKUP,同时优先级别必定要下降。
- 修改配置文件:vim /etc/keepalived/keepalived.conf
;
vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.68.250 } } virtual_server 192.168.125.250 16001 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.125.168 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } real_server 192.168.125.169 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } }
9.tw-haproxy-server-*启动HAProxy:
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg
10.tw-haproxy-server-*启动keepalived服务:service keepalived start
keepalived
相关进程:ps -ef | grep keepalived
keepalived
状态:service keepalived status
keepalived
服务:service keepalived stop
11.此时若是在进行访问,必定要使用VIP进行访问。
haproxy
:http://192.168.125.250:7777/admin
;