
并发数上升,究竟是哪一个服务处理能力到了瓶颈,仍是Redis性能到了瓶颈,只有找出是哪里的性能问题,才能对症下药。因此,了解redis的一些运维知识可以帮助咱们快速断定是否Redis集群的性能问题。
css
关于stat选项,官网也是介绍的比较简单。使用redis-cli命令加上stat选项能够实时监视redis实例,好比当前节点内存中缓存的 key总数以及每秒处理请求数等。stat默认每隔一秒会输出一行信息,若是须要改变频率可以使用-i <interval> 指定频率,单位为秒,如--stat -i 100。须要配合-h选项使用。java
关于requests与connections官方也没有介绍,本身结合本地和线上的输出,作了对比得出的结论。nginx
------- data ------ --------------------- load -------------------- - child -keys mem clients blocked requests connections 97146 6.82G 1724 0 60068357585 (+49536) 93936323 97146 6.82G 1724 0 60068403702 (+46117) 93936323 97146 6.82G 1724 0 60068451875 (+48173) 93936323 97146 6.82G 1724 0 60068496037 (+44162) 93936323
keys:当前节点缓存的key总数redis
mem:当前节点缓存总的占用内存swift
clients:当前节点的活跃链接数,或者说未断开链接的总链接数缓存
blocked:当前节点正在等待阻塞命令的数量安全
requests:当前处理的请求数,与上一次请求数相减可知1秒所处理的请求,或者说所执行的命令数。服务器
connections:是历史链接总数,即到目前为止,一共新建了多少个链接。与前一次相减,能够得出一秒内新建的链接数。微信
Requests列括号里的数是每间隔所处理的命令数。好比当前60068496037减去前一次60068451875 等于44162,因为stat默认频率是每秒输出一次,44162就是每秒执行4万多条命令。正好是括号里面的数字,也所以能够知道,括号里面的数字表明每秒(interval)执行的命令数。网络
固然--stat每秒输出一次结果也是一条命令,因此在没有任何请求的状况下,你看到的requests是自增的,能够本地起个redsi服务,而后使用redis-cli --stat观察下输出。
Blocked并非排队等待执行的命令数,而是客户端执行阻塞命令的总数。好比BLPOP。
Connections也是颇有用的参数,若是发现connections与前一次的差值很大,且很频繁,那就要看下代码中链接池配置是否生效了。
在此以前,咱们项目中用的是古老的主从集群模式,使用读写分离的链接池,全部写请求都会访问主节点,全部读请求都会访问从节点,那么读写分离会存在哪些问题?
观察主节点,全部写请求都会发到这个节点。
------- data ------ --------------------- load -------------------- - child -keys mem clients blocked requests connections 382453 1.22G 1305 0 53636611824 (+5112) 70953183 382453 1.22G 1305 0 53636616926 (+5102) 70953183 382453 1.22G 1305 0 53636622056 (+5130) 70953183
观察从节点,全部读请求都会发到这个节点。
------- data ------ --------------------- load -------------------- - child -keys mem clients blocked requests connections 382551 1.22G 1307 0 197046636517 (+34705) 75561440 382551 1.22G 1307 0 197046669775 (+33258) 75561440 382552 1.22G 1307 0 197046701747 (+31972) 75561440 382551 1.22G 1307 0 197046734329 (+32582) 75561440
很明显,主节点每秒处理的写请求数远小于从节点每秒处理的读请求数。在极端状况下,好比写少读多的场景,使用这种主从读写分离方案,会致使一个节点无请求,而另外一个节点忙得不可开交。
主从读写分离还有一个缺点,若是一时间批量写了不少数据,因为主从同步的延时问题,会出现一个空白期,从从节点上读不到数据。若是有实时性要求高的场景,或者大批量数据更新很频繁的场景,仍是不建议使用读写分离。从节点应该只用来提供高可用的保证,在主节点挂的状况下从节点保证这部分槽位可用。固然,这不用也是浪费。
只有两个主节点的Cluster集群,槽位平均分配。使用redis-cli --stat实时监视实例。
节点1输出片断:
------- data ------ --------------------- load -------------------- - child -keys mem clients blocked requests connections 97270 6.82G 1726 0 60242433804 (+26930) 94154236 97270 6.81G 1726 0 60242457927 (+24123) 94154236 97270 6.82G 1725 0 60242485748 (+27821) 94154236 97270 6.82G 1725 0 60242511827 (+26079) 94154236
节点2输出片断:
------- data ------ --------------------- load -------------------- - child -keys mem clients blocked requests connections 96077 4.20G 1725 0 61244385399 (+32594) 94349868 96076 4.20G 1725 0 61244417031 (+31632) 94349868 96075 4.21G 1725 0 61244443142 (+26111) 94350076 96075 4.20G 1725 0 61244466682 (+23540) 94350076
从两个节点的当前链接数能够看出,JedisCluster配置的链接池会为每一个节点建立一个链接池,每一个节点的链接池链接数都是相同的。之因此会每一个节点都维持相同的链接数,由于每一个请求的key都有可能落在其中的一个节点上,你没法预知程序运行过程当中落在哪一个节点的请求数较多,哪一个较少。
当各个服务的集群总节点数不少的状况下,就须要合理分配链接池的最大链接数。官方推荐单个redis节点最大链接数不超过1w,假设有20个服务节点须要用到redis,那么每一个节点的链接池最大链接数最大不能超过10000/20 = 500。建议链接池的最大链接数比业务线程的最大线程数多20个链接,只要确保每一个工做线程都能有一个redis链接,不至于为了等待链接而阻塞就能够,由于不可能一个线程同时会用到2个以上的链接。假设工做线程数为200,那么redis链接池能够配置为200~220。
从两个节点的内存使用和每秒处理的请求数可以看出,数据的倾斜仍是较为严重的,每秒请求数相差在1w左右,这个差距还在可接受范围内。若是请求和内存的倾斜比较严重,就能够从新分配槽位,给请求和存储较少的一方分配更多的槽位以达到平衡状态。
stat对于性能监控仍是颇有帮助的。可以获取到每秒处理的命令数还能够经过info Stats。如
172.31.x.x:6379> info stats# Stats.....instantaneous_ops_per_sec:8589....
instantaneous_ops_per_sec:redis内部较实时的每秒执行的命令数。
若是想要获取更详细的每种命令的平均耗时,可使用info Commandstats查看如:
172.31.x.x:6379> info Commandstatscmdstat_zrangebyscore:calls=1006828954,usec=9633479351,usec_per_call=9.57cmdstat_rpush:calls=49673,usec=278402,usec_per_call=5.60cmdstat_setbit:calls=86267170,usec=2645199883,usec_per_call=30.66......
cmdstat_zrangebyscore: 即zrangebyscore命令
calls:命令调用总次数
usec: 总耗时
usec_per_call: 平均耗时,单位微秒
当命令的执行耗时超过配置的慢查询时间,则会被放入一个慢查询的队列中。可经过config set slowlog-log-slower-than xxx修改慢查询时间,单位微秒,默认状况下,这个值为10000,即全部执行时间超过10ms的都会记录到慢查询队列。使用slowlog get能够查看慢查询信息。
172.31.x.x:6379> slowlog get 1 1) 1) (integer) 6018 2) (integer) 1575108134 3) (integer) 19861 4) 1) "ZRANGEBYSCORE" 2) "ip-country-city-locations-range-3708" 3) "3.72526109E9" 4) "1.7976931348623157E308" 5) "limit" 6) "0" 7) "1" 5)"172.31.x.x:xxx" ......
>src/redis-cli --latency -h 172.31.1.1min: 0, max: 12, avg: 0.25 (1047 samples)
# 是否开启持久化策略# (支持同时开启RDB和AOF,即混合策略)appendonly no
# yes: 在aof重写期间不作fsync刷盘操做,可能丢失整个AOF重写期间的数据,no-appendfsync-on-rewrite yes
# fsync针对单个文件操做(好比AOF文件),作强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证了数据持久化。# always:每次写入都要同步AOF文件。# no:同步硬盘操做由操做系统负责,一般同步周期为30秒,数据安全性没法保证。# everysec:由专门线程每秒同步一次fsync。理论上只有在系统忽然宕机的状况下丢失1秒的数据。appendfsync no
#当前aof文件大小与上次重写后文件大小的比值超过该值时进行重写,200即等于以前的2倍auto-aof-rewrite-percentage 200
#当aof文件大小大于该值时进程重写,以减少aof文件占用的磁盘空间auto-aof-rewrite-min-size 64mb


本文分享自微信公众号 - Java艺术(javaskill)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。