希望长大对我而言,是可以做更多想做的事,而不是被迫做更多不想做的事...... 首页 Redis+Twemproxy+HAProxy+Keepalived 丁D 学无止境 2019-07-12 17:20 573963已阅读 Redis Twemproxy HAProxy Keepalived Redis Cluster 摘要本文将介绍Redis Cluster集群和Twemproxy的对比,并搭建使用代理Twemproxy搭建Redis集群。 https://blog.csdn.net/shmilychan/article/details/73433804 https://my.oschina.net/dchuang/blog/666827 ###为什么Redis+Twemproxy不是Redis Cluster? (1)Redis Cluster不好做读写分离,如果需要扩展读写qps,都是直接扩展主节点。从节点只是做热备+高可用 (2)不好跟nginx+lua直接整合,lua->redis的client api,但是不太支持redis cluster,中间就要走一个中转的java服务 (3)不好做树形结构,redis cluster不太好做成那种树状结构 (4)方便,相当于是上下线节点,集群扩容,运维工作,高可用自动切换,比较方便 Twemproxy (1)Twemproxy是一个代理,可以很好的支持读写分离 (2)nginx+lua直接整合 (3)不好做树形结构 (4)扩容/缩容 需要一些成本 Twemproxy和codis对比? ###环境准备 3个哨兵 4个redis实例 2主2从 1个Twemproxy ip| sentinel服务| redis|Twemproxy| ------- | ------- | ------- | -------| 192.168.144.3| 192.168.144.3:5000| -| 192.168.144.3:1111 192.168.144.4 | 192.168.144.4:5000| 192.168.144.4:8000 192.168.144.4:8001| 192.168.144.8 | 192.168.144.8:5000| 192.168.144.4:8002 192.168.144.4:8003| **Twemproxy的服务器上面要有哨兵** **Twemproxy的服务器上面要有哨兵** **Twemproxy的服务器上面要有哨兵** ###redis读写分离 见以前博客 ###sentinel 见以前博客 ```js //由于两个集群所以配置2个 sentinel monitor tw_8000 192.168.144.4 8000 2 sentinel down-after-milliseconds tw_8000 30000 sentinel failover-timeout tw_8000 60000 sentinel parallel-syncs tw_8000 1 sentinel monitor tw_8003 192.168.144.8 8003 2 sentinel down-after-milliseconds tw_8003 30000 sentinel failover-timeout tw_8003 60000 sentinel parallel-syncs tw_8003 1 ``` ###安装Twemproxy ```js //安装twemproxy 前,需要安装autoconf,automake,libtool 软件包 //判断存不存在 autoconf --version automake --version libtool --version ``` **autoconf** ```js ## 下载 && 解压并安装 wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz tar zxf autoconf-2.69.tar.gz ./configure make && make install //报错 checking for GNU M4 that supports accurate traces... configure: error: no acceptable m4 could be found in $PATH. //处理 wget http://ftp.gnu.org/gnu/m4/m4-1.4.16.tar.gz tar -zxvf m4-1.4.16.tar.gz ./configure make && make install //报错 ./stdio.h:477:1: error: 'gets' undeclared here (not in a function) _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); //处理 https://www.cnblogs.com/zll123/p/6865900.html //报错 Can't locate Data/Dumper.pm in @INC (@INC contains: ../lib /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at ../lib/Autom4te/C4che.pm line 33. //处理 yum install 'perl(Data::Dumper)' ``` **automake** ```js wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz tar zxf automake-1.15.tar.gz ./bootstrap.sh ./configure make && make install //报错 Can't locate Thread/Queue.pm in @INC (@INC contains: ./automake-1.14 /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/ 处理 yum install perl-Thread-Queue ``` **libtool** ```js wget https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz tar zxf libtool-2.4.6.tar.gz cd libtool-2.4.6 ./configure make && make install ``` **twemproxy** ```js ## 下载 && 解压并安装 wget https://github.com/twitter/twemproxy/archive/master.zip unzip master.zip cd twemproxy-master ## 在twemproxy源码目录执行autoreconf 生成 configure文件等 autoreconf -fvi ## 然后编译安装 ./configure --prefix=/usr/local/twemproxy/ make && make install ``` 配置 ```js //vim redis_twemproxy.yml redis_twemproxy: listen: 0.0.0.0:11111 hash: fnv1a_64 distribution: ketama redis: true auto_eject_hosts: true #redis_auth: mldnjava server_retry_timeout: 30000 server_failure_limit: 2 servers: - 192.168.144.4:8000:1 redis1 - 192.168.144.8:8003:1 redis2 //解释 redis_twemproxy: redis集群的逻辑名称,跟文件名一样 listen:twemproxy监听的端口号 hash:hash散列算法 distribution:分片算法,一致性hash,取模,等等 timeout:跟redis连接的超时时长 redis:是否是redis,false的话是memcached servers:redis实例列表,一定要加别名,否则默认使用ip:port:weight来计算分片,如果宕机后更换机器,那么分片就不一样了,因此加了别名后,可以确保分片一定是准确的 auto_eject_hosts: true,自动摘除故障节点 server_retry_timeout: 30000,每隔30秒判断故障节点是否正常,如果正常则放回一致性hash环 server_failure_limit: 2,多少次无响应,就从一致性hash环中摘除 redis_auth:redis密码 //创建存放pid文件和log文件的目录 mkdir -p /var/twemproxy/{pid,logs} //启动 /root/twemproxy-master/src/nutcracker -d -c /root/twemproxy-master/conf/redis_twemproxy.yml -p /var/twemproxy/pid/redis_twemproxy.pid -o /var/twemproxy/logs/redis_twemproxy.log -d:后台启动 -c:指定配置文件 -p:指定pid文件 -o:执行日志文件 ``` ###twemproxy和哨兵结合 如上面的配置 servers 中我们配置的是主节点的列表,但是当我们redis的master宕机,sentinel将slave节点提拔为master,但是我们的twemproxy配置是独立了,并没有切换。 所以我们这里要利用sentinel的通知功能(client-reconfig-script) ```js //client-reconfig-script 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。以下参数将会在调用脚本时传给脚本: 目前总是“failover”, 是“leader”或者“observer”中的一个。 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的。这个脚本应该是通用的,能被多次调用,不是针对性的。 ``` 通知脚本 ```js //vim twemproxy-reconfig.sh #!/bin/sh ### sentinel 触发执行此脚本时,会默认传递几个参数过来 ### # monitor_name="$1" ##monitor master-group-name master_old_ip="$4" master_old_port="$5" master_new_ip="$6" master_new_port="$7" twemproxy_name="redis_twemproxy" ##这里我直接写死了,twemproxy的配置文件名 不包括.yml twemproxy_bin="/root/twemproxy-master/src/nutcracker" twemproxy_conf="/root/twemproxy-master/conf/${twemproxy_name}.yml" twemproxy_pid="/var/twemproxy/pid/${twemproxy_name}.pid" twemproxy_log="/var/twemproxy/logs/${twemproxy_name}.log" twemproxy_cmd="${twemproxy_bin} -d -c ${twemproxy_conf} -p ${twemproxy_pid} -o ${twemproxy_log}" ## 将新的master 端口和ip 替换掉 twemproxy 配置文件中旧的master 信息 sed -i "s/${master_old_ip}:${master_old_port}/${master_new_ip}:${master_new_port}/" ${twemproxy_conf} ## kill 并启动的nutcracker 进程 ,并重新启动 #echo "kill start" >> ./log.txt #ps -ef |grep "${twemproxy_cmd}" | grep -v grep >> ./log.txt ps -ef |grep "${twemproxy_cmd}" |grep -v grep |awk '{print $2}'|xargs kill #echo "kill ing" >> ./log.txt #ps -ef |grep "${twemproxy_cmd}" | grep -v grep >> ./log.txt #echo "kill end" >> ./log.txt #echo "start twemproxy" >> ./log.txt ${twemproxy_cmd} #echo "start end" >> ./log.txt sleep 1 ps -ef |grep "${twemproxy_cmd}" |grep -v grep ps -ef |grep "redis" ``` ```js chmod 777 twemproxy-reconfig.sh //让脚本生效 //-h 127.0.0.1 -p 5000是哨兵的ip和端口 tw_8000,tw_8003 是哨兵监听的集群在哨兵配置文件配置的,这里是2主2从 所以两个 redis-cli -h 127.0.0.1 -p 5000 sentinel set tw_8000 client-reconfig-script /etc/sentinal/twemproxy-reconfig.sh redis-cli -h 127.0.0.1 -p 5000 sentinel set tw_8003 client-reconfig-script /etc/sentinal/twemproxy-reconfig.sh ``` ###测试 目前: 主节点 8001 -> 从节点 8004 主节点 8003 -> 从节点 8002 我们直接kill 8003master会发现,哨兵日志已经打印 主从切换的日志 我们直接看 twemproxy的配置文件 发现 master列表被替换了 ```js servers: - 192.168.144.4:8000:1 redis1 - 192.168.144.4:8002:1 redis2 ``` 之后我们可以直接连接twemproxy测试 ```js //这里是twemproxy redis-cli -h 127.0.0.1 -p 11111 就可以set get 了 问题 设redis8000原本有k1这个key 但是 twemproxy计算k1的hash值是在8003这个集群中,这里是获取不到的 。 ``` ###HAProxy+Keepalived 我们知道redis是基于内存操作的,快得一逼,所以会发现单台twemproxy成了系统的性能的瓶颈。所以我们可以部署多台twemproxy来提高twemproxy的性能,并使用Keepalived一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障 ####安装HAProxy #####环境准备 ip| sentinel服务| redis|Twemproxy| ------- | ------- | ------- | -------| 192.168.144.3| 192.168.144.3:5000| -| 192.168.144.3:11111 192.168.144.4 | 192.168.144.4:5000| 192.168.144.4:8000 192.168.144.4:8001|192.168.144.3:11111 192.168.144.8 | 192.168.144.8:5000| 192.168.144.4:8002 192.168.144.4:8003| 在192.168.144.3安装Haproxy [下载haproxy](http://download.openpkg.org/components/cache/haproxy/) 这里选择下载版本:**haproxy-1.8.10.tar.gz** ```js wget http://download.openpkg.org/components/cache/haproxy/haproxy-1.8.10.tar.gz tar -xvf haproxy-1.8.10.tar.gz //查询系统内核 我是3.10.0-957.el7.x86_64 uname -r //可能依赖 yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel //这些应该不用--为了排除内核写成310就全装了 yum net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget ntpdate cd haproxy-1.8.10 //TARGET 内核大于26.28的统一指定linux2628(我写成linux310会出错) make TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 make install //haproxy要自己创建配置文件 mkdir /etc/haproxy cd /etc/haproxy touch haproxy.cfg ``` 配置文件haproxy.cfg **redis要是用tcp** **redis要是用tcp** **redis要是用tcp** **frontend redis 中的mode** **backend redis_tw 中的mode** ```js //不弄成tcp 报错 Error: Protocol error, got "H" as reply type byte ``` ```js mkdir /var/haproxy 放日志和pid ``` ```js //haproxy.cfg ###########全局配置######### global log 127.0.0.1 local2 info #定义haproxy 日志级别[error warringinfo debug] local1 /etc/rsyslog.conf local2.* /var/log/haproxy/haproxy.log daemon #以后台形式运行harpoxy nbproc 1 #设置进程数量 maxconn 4096 #默认最大连接数,需考虑ulimit-n限制 #user haproxy #运行haproxy的用户 #group haproxy #运行haproxy的用户所在的组 pidfile /var/haproxy/haproxy.pid #haproxy 进程PID文件 #ulimit-n 819200 #ulimit 的数量限制 #chroot /usr/share/haproxy #chroot运行路径 #debug #haproxy 调试级别,建议只在开启单进程的时候调试 #quiet ########默认配置############ defaults log global mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK option httplog #日志类别,采用httplog option dontlognull #不记录健康检查日志信息 retries 2 #两次连接失败就认为是服务器不可用,也可以通过后面设置 #option forwardfor #如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip option httpclose #每次请求完毕后主动关闭http通道,haproxy不支持keep-alive,只能模拟这种模式的实现 #option redispatch #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器,以后将不支持 option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 maxconn 4096 #默认的最大连接数 timeout connect 5000ms #连接超时 默认单位是毫秒,可以自己加后缀 timeout client 30s #客户端超时 timeout server 30s #服务器超时 timeout check 5000 #心跳检测超时 单位是ms #timeout http-keep-alive10s #默认持久连接超时时间 #timeout http-request 10s #默认http请求超时时间 #timeout queue 1m #默认队列超时时间 balance roundrobin #设置默认负载均衡方式,轮询方式 ########统计页面配置######## listen stats bind 0.0.0.0:10000 #设置Frontend和Backend的组合体,监控组的名称,按需要自定义名称 mode http #http的7层模式 option httplog #采用http日志格式 #log 127.0.0.1 local0 err #错误日志记录 maxconn 10 #默认的最大连接数 stats refresh 30s #统计页面自动刷新时间 stats uri /stats #统计页面url stats realm jinding\ Haproxy #统计页面密码框上提示文本 stats auth admin:admin #设置监控页面的用户和密码:admin,可以设置多个用户名 stats auth root:root #设置监控页面的用户和密码:root stats hide-version #隐藏统计页面上HAProxy的版本信息 stats admin if TRUE #设置手工启动/禁用,后端服务器(haproxy-1.4.9以后版本) ########frontend前端配置############## frontend redis bind *:6666 #这里建议使用bind *:80的方式,要不然做集群高可用的时候有问题,vip切换到其他机器就不能访问了。 option tcplog mode tcp #option forwardfor#真实ip redis不需要 log global default_backend redis_tw #不满足则响应backend的默认页面 ########frontend前端配置############## #frontend main # bind *:80 #这里建议使用bind *:80的方式,要不然做集群高可用的时候有问题,vip切换到其他机器就不能访问了。 # acl web hdr(host) -i www.abc.com #acl后面是规则名称,-i为忽略大小写,后面跟的是要访问的域名,如果访问www.abc.com这个域名,就触发web规则,。 # acl img hdr(host) -i img.abc.com #如果访问img.abc.com这个域名,就触发img规则。 # use_backend webserver if web #如果上面定义的web规则被触发,即访问www.abc.com,就将请求分发到webserver这个作用域。 # use_backend imgserver if img #如果上面定义的img规则被触发,即访问img.abc.com,就将请求分发到imgserver这个作用域。 # default_backend dynamic #不满足则响应backend的默认页面 ##############redis后端配置####################### backend redis_tw balance roundrobin mode tcp #option redispatch server twemproxy1 192.168.144.3:11111 weight 1 check inter 2000 rise 2 fall 3 #server 名字(随意写) ip:port 权重...见下面注释 #server 名字(随意写) ip:port 权重...见下面注释 server twemproxy3 192.168.144.4:11111 weight 1 check inter 2000 rise 2 fall 3 #check:表示启用对此后端服务器执行健康状态检查。 #inter:设置健康状态检查的时间间隔,单位为毫秒。 #rise:设置从故障状态转换至正常状态需要成功检查的次数,例如。“rise 2”表示 2 次检查正确就认为此服务器可用。 #fall:设置后端服务器从正常状态转换为不可用状态需要检查的次数,例如,“fall 3”表示 3 次检查失败就认为此服务器不可用。 ``` //启动 ```js /usr/local/sbin/haproxy -f /etc//haproxy/haproxy.cfg ``` 控制台 http://192.168.144.3:10000/stats ![alt](/upload/微信图片_20190724180738.png ) 从上图可以看到后端twemproxy都是启动的 之前出现一个问题:就是我的twemproxy配置文件中写如下代码,导致连接拒绝,后面改成0.0.0.0所有的就可以了 ```js redis_twemproxy: listen: 127.0.0.1:11111 ``` ```js //连接操作 //注意端口是 haproxy监听的 redis-cli -h 192.168.144.3 -p 6666 ``` ![alt](/upload/微信图片_20190724181147.png ) 未完待续。。。 很赞哦! (8) 上一篇:使用静态内部类来创建单例 下一篇:redis哨兵 目录 点击排行 Elasticsearch6.3.2之x-pack redis哨兵 2019-07-09 22:05 Redis+Twemproxy+HAProxy+Keepalived 2019-07-12 17:20 GC优化策略和相关实践案例 2019-10-10 10:54 JVM垃圾回收器 2019-10-10 10:23 标签云 Java Spring MVC Mybatis Ansible Elasticsearch Redis Hive Docker Kubernetes RocketMQ Jenkins Nginx 友情链接 郑晓博客 佛布朗斯基 凉风有信 南实博客 Rui | 丁D Java研发工程师 生活可以用「没办法」三个字概括。但别人的没办法是「腿长,没办法」、「长得好看,没办法」、「有才华,没办法」。而你的没办法,是真的没办法。 请作者喝咖啡