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

[经验分享] redis的一些坑

[复制链接]

尚未签到

发表于 2018-11-4 09:14:43 | 显示全部楼层 |阅读模式
  from:http://my.oschina.NET/u/875730/blog/378086
  0 Redis跨机房使用问题
  一般地,redis的每个实例都是一个master加上一个slave,这一主一备一般要放在同一个机房idc,否则会出现各种莫名其妙的问题。为了防止一个idc出问题,可以用scp或者rsync命令把redis数据定时(譬如每隔10分钟或者半小时)地备份到另一个机房。
  1 redisContext尽量在一个线程内使用
  《从hiredis使用出core谈谈redis多线程的使用》一文中提到:redis是单线程异步模型,hiredis这个客户端看来也只支持单线程。
  2 发送二进制数据
  《Redis C语言客户端库hiredis文档翻译》一文提到:
  当你需要发送二进制安全的命令可以采用%b的格式化方式,同时需要一个字符串指针和size_t类型的字符串长度参数,如下
  reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);
  在API内部,Hiredis根据不同的参数分割命令转化为操作redis数据库的标准命令,你可以格式化多个参数来构造redis的命令,如下
  reply = redisCommand(context, "SET key:%s %s", myid, value);
  《C++ Redis mset 二进制数据接口封装方案》一文作者貌似不知道这个用法,他通过redisCommandArgv这个函数绕了一圈来发送二进制数据。
  3 两级hash
  http://www.cnblogs.com/restran/p/4295184.html
  每个key-vaulue结构,Redis本身的维护开销就要80几字节,即便value存储的是纯数字(会使用long类型,占用4个字节),也依然很大,1000万的数据,就要占用快1G内存。
  依据官方文档的内存优化方法,以及这篇文章 节约内存:Instagram的Redis实践,建议对ID分段作为key,并使用 hash 来存储第一级 key 的 value,第二级存储较少的数据量(推荐1000),因此第二级的key使用ID的后3位。
  4 redis-cli 在非交互模式下直接执行命令时附带模糊参数
  redis-cli -h 127.0.0.1 -p 6379 keys '*'
  or redis-cli  -h 127.0.0.1 -p 6379 keys "*"
  5 老版本的sentinel问题注意
  最近使用v2.8.19的sentinel,监控一个服务器的配置为:
  sentinel monitor server1 127.0.0.1 36379 1
  sentinel down-after-milliseconds server1 3000
  sentinel parallel-syncs server1 1
  sentinel failover-timeout server1 15000
  sentinel auth-pass server1 r23456
  测试时候一切正常,但是在线上服务器部署后,发生主fail的情况的时候,主从切换并没有发生,检查了线上版本的sentinel版本,为v2.6.11。
  讲过一番检查,添加了can-failover,就正常了,修改后的配置项为:
  sentinel monitor server1 127.0.0.1 36379 1
  sentinel can-failover server1 yes
  sentinel down-after-milliseconds server1 3000
  sentinel parallel-syncs server1 1
  sentinel failover-timeout server1 15000
  sentinel auth-pass server1 r123456
  另外,使用这个版本的sentinel的时候请把conf文件中原有的mymaster相关配置注释掉,否则就坑爹了,你会发现你的监控项多了一项mymaster。
  6 在一个脚本中批量执行多个写入操作
  先把插入操作放入操作文本insert.bat:
  ?
1234set a bset 1 2set h wset f u  如果是在unix上写的insert.bat,请用命令"unix2dos  insert.bat"转换其格式。
  然后执行命令:cat insert.bat | ./redis-cli --pipe,或者如下脚本:
  ?
12345#!/bin/shhost=$1port=$;password=$3cat insert.bat | ./redis-cli -h $host -p $port -a $password --pipe  7 twemproxy及时感知死掉的redis server
  from:http://www.oschina.net/translate/twemproxy-a-twitter-redis-proxy 评论
  我在虚拟机上安装了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:
  lpha:
  listen: 127.0.0.1:22121
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
  - 127.0.0.1:6379:1
  - 127.0.0.1:6380:1
  - 127.0.0.1:6381:1
  三个redis都启动时,服务正常。当我把 127.0.0.1:6379停掉时,该服务节点不自动摘除,执行set命令时一直有服务拒绝的命令。
  [root@localhost redis]# ./redis-cli -p 22121 set 1 1
  (error) ERR Connection refused
  当我把故障的redis恢复后,发现服务正常了。结果全部是OK
  以上测试可以看出,故障节点没有自动摘除。
  请问专家,这是为何?我没有配置好?
  server_retry_timeout: 2000->60000
  server_failure_limit: 1->0
  试试修改以上两个配置,第一个retry的间隔时间要拉长,不然你的nutcracker一直在重试连接,自然一直摘不掉机器;第二个容忍的错误数可以设置成0容忍,就是说有错误立马摘掉这个机器。
  我把server_retry_timeout: 20000000这个重连时间改的更长了
  这次真的摘除了~谢谢啊!
  原来这个参数代表的是发现故障后,恢复连接间隔时间,我还一直以为重试是内部机制呢,原来不是。。这个有点坑爹
  8 persistence
  redis的数目备份有rdb和aof两种格式,rdb可以认为是一个时刻的redis内存数据的二进制镜像,而aof则是redis数据的MySQL的binlog式的写请求日志文件。
  rdb文件保存方式特点在于:1 在数据非常多的情况下,使用rdb会占用比aof文件更少的磁盘,也更适合远程数据备份,一旦创建完毕就不会再被修改;2 redis启动后能够很快加载rdb文件,如果要重放aof的命令则会很耗费时间;3 rdb文件是某个时间点redis所有数据的image,redis会fork一个进程来进行工作,短则数毫秒长则一秒多内外部客户端的请求不会被及时处理,不能及时保持所有时刻的数据,一旦发生事故,最近一段时间内的写请求的数据就会丢失;4redis执行rdb文件保存的时候,会fork一个子进程创建一个临时文件进行数据保存任务,数据保存完毕后它会删除老的文件并把新的文件rename为老文件的名字;
  aof文件保存方式的特点在于:1 aof保存有三种策略:无fsync(即不保存数据把redis作为一个cache)、每秒钟进行一次fsync和每次写请求都执行fsync,默认是fsync每秒,这种策略被执行的时候redis会创建一个线程进行fsync任务,所以不会影响主线程的工作,就算发生事故也仅仅丢掉了一秒钟内的请求数据;2aof保存的是文本格式的请求log,如果出现用户不小心执行了flushall这种命令,用户可以手工修改aof文件后重启redis即可;3 aof文件的缺点就在于size太大,而且执行数据恢复的时间太长;4redis执行aof任务的时候与rdb流程比较相似,redis先fork一个子进程创建一个新的aof文件,然后把当前进程中的数据以客户端与服务端的通讯方式的写请求形式保存下来,保存过程中如果有新的写请求,主进程会把这些写请求写进老的aof文件的同时也创建一个内存buffer,以保存这批新的请求命令,子进程完成任务后会发送signal给父进程,父进程会deleteold aof file并且rename new aof file,然后把buffer中的写请求追加到new aof file中。
  所以一般安全点的方法就是两种文件保存方法并用。如果redis正在执行rdb保存任务,而用户发送了BGREWRITEAOF 命令给redis,则redis会把任务排队,返回ok给client,当redis执行完毕rdb任务的时候才会执行aof任务。当redis启动执行recovery的时候,它会优先采用aof文件,因为aof文件的数据总比rdb新。
  redis执行aof任务主要由rewriteAppendOnlyFileBackground->rewriteAppendOnlyFile完成,查看这个函数的源码,可以看到所有的db都存在server.db(容量为server.dbnum)之中,每个db类型的redisDb,其主要成员为dict*dict,即所有key都是按照hashtable罗列的,这个hashtable的优点是可以按照iterator那样去遍历。
DSC0000.png

  9 codis
  我们线上的 redis 集群最大单服务的是 800G 左右, 分成32个分片, 对应 codis 的32个 Server group, 总的 qps 大概 10w 左右, 我们用了 2个 codis-proxy 抗着,基本没压力 。rocksdb 的存储引擎:https://github.com/reborndb/qdb,其实启动后就是个 redis-server,支持了 PSYNC 协议,所以可以直接当成redis从来用。
  codis改进了一下redis缺点:
  1 redis数据量太大的话(22G以上),他的处理性能就开始下降;
  2 无法区分冷热数据,内存浪费严重;
  3 RDB Block住整个服务;
  4 写操作太频繁,AOF刷盘太多,很容易rewrite


运维网声明 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-630482-1-1.html 上篇帖子: 玩转Redis集群(上) 下篇帖子: Codis作者黄东旭细说分布式Redis架构设计和踩过的那些坑
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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