Redis开发规范

一、总体情况介绍:

  • redis实例总共3780个,140个集群(cluster 模式)主要为cluster模式
  • 最大的集群广告集群,双机房部署,lg机房17台服务器,25个分片,共50个实例 600G已用423G
  • 架构 主推 redis-cluster ,辅助m-s架构
  • Redis Cluster简介

    • 是Redis官方3.0版本开始提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能。 整个集群是无中心化结构,把集群的键空间(KeySpace)划分为16384个slots(槽)。集群中每个分片(shard)负责处理部分slots,每个redis节点都会保留集群slots分布的元数据信息。smart clients(如jedis)首次构建线程池会获取cluster slots分布的元数据,client在处理请求命令,通过对被操作的key, 进行CRC16(key)/16384公式计算出key的数据槽号,通过槽号归属于一个节点,这样Redis集群就知道请求最终发向正确的节点。
  • 架构细节:

    • (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
    • (2)节点的fail是通过集群中超过半数的master节点检测失效时才生效. gossip 协议
    • (3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
    • (4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->key
  • 分配图:

    • cluster ---> 16384 个slots (分配到多个分片)---> key
  • 名词解释   分片和节点

    • 一个Redis集群包含固定的16384个数据槽(slot),这些数据槽通常分布到多个分片(sharding),每个分片有且有一个主节点(master node),每个主节点可能有0个或多个副本(replica)。Redis集群理论上最多能支持16384个主节点(每个node负责1个slot),但官方建议目前版本节点不要超1000个。 从最佳实践来看不超过100个。
  • 数据槽(slots)

    • Redis cluster 将存储空间分为16384(0-16383)个slots,当所有slots分配完毕,集群就可以写入数据对外提供服务。一般slots的分配,采用平均分配的原则,假如有10个分片,则每个分片有:16384/10个slots。
  • 复制和副本

    • Redis集群虽是无中心节点,且任意节点间两两互联,通过gossip协议(流言协议)进行通信和配置更新;但并不像Cassandra采用对等结构(P2P)分布式模型。因为集群中的节点分为主节点和从节点两种角色。
    • Redis集群内部支持复制,每个主节点可设置0~多个从节点,通过Redis的原生异步复制同步数据。当某个主节点挂掉或网络无法连接,集群通过投票判定主节点故障(Fail)后,会选择它的一个从节点进行顶替。
  • 故障检测和故障转移

    • 1 选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
    • 2 什么时候整个集群不可用( cluster_state:fail )?
      • a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态. 如果cluster-require-full-coverage参数打开,那么集群兼容部分失败,默认是打开。
      • b:如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态. ps:当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误

三、当前redis使用过程遇到的问题

  • 1、使用的版本?
  • 2、当前的redis架构?
  • 3、缓存还是存储?数据完整性要求?极端情况下是否容许丢数据。

四、运维支持

  • 监控 http://falcon.xae.xiaomi.com/template/view/246
  • 备份还原 http://dba.n.xiaomi.com/redisbackup/log
    • 存储类型的,cluster架构,一般情况下正常切换,不丢数据
      • 极端情况下1 :主机down机,从库也down机并且无法启动,只能恢复到当天凌晨3点
      • 极端情况下2 :主机down机,从库也down机但是可以启动,可恢复到down机前。doing.
  • 扩容:

    • 1、支持横向扩容,通过划分更多的分片,实现扩容。添加机器,reblance slots分布。
    • 2、支持纵向扩容,通过调整单个实例的容量,和failover 机制扩容。
    • 前提:不要使用一些包装的命令,例如pipline。
  • Redis的慢查询分析

    • slowlog只存储在内存中,最老的慢查询淘汰后,就没法找回。现在通过slowlog len命令取得慢查询列表中的个数。
    • 慢查询扩大问题,由于Redis是单线程的,因此出现一个慢查询,比如get操作执行500ms,导致这500ms内的请求都会堵住,但是慢查询日志只会记录一条。

五、 cluster 的使用限制

  • 1、不支持pipline 操作
  • 2、不支持多key操作,例如keys、mget、hmget
  • 3、单个key过大,QPS过高,可能网络会成为瓶颈,需要业务优化

六、常见问题

  • 1、 Java 异常Too many Cluster redirections
  • 2、双机房问题
    • 1、目前双机房,采用业务双写的策略。如果是java ,可以使用 广告组开发的公共包。其他语言,暂时没有。
    • 2、双机房的高可用问题,采用的策略是机房自治策略,单个机房出现问题时,业务降级,将流量从A机房迁移到B机房。

七、开发规范

  • 生产环境严禁使用的危险命令(请误在生产环境尝试)
    • keys * : 导致Redis实例堵死,甚于触发故障切换,导致整个集群出现大面积故障
    • flushall: 导致Redis堵死,同时丢失所有数据
    • flushdb: 丢失当前database的所有数据,出现堵死现象
    • save: 导致Redis堵死
    • bgsave: 导致Redis卡顿,FORK引起COW内存消耗,有导致大面积OOM的风险
    • config set: 严禁开发同学修改生产配置,错误配置会导致数据丢失和OOM的风险
    • shutdown: 导致Redis关闭、数据丢失和故障转移
    • debug : 导致Redis Crash、堵死和集群故障转移等
    • 慎用时间复杂度为O(N)的命令方法, 详细分析见本节后文”程序架构规范"。
  • Keyspace设计
    • 只使用database 0,通过key前缀划分命令空间
      • 多个database用select切换时,更消耗CPU资源
      • 更易自动化运维管理,如scan/dbsize命令只用于当database
  • Key的设计规范:高可读性、区分性和尽量简洁
    • 按业务功能命名key前缀,防止key冲突覆盖,同时方便运维管理。
    • Key的长度小于30个字符,Key内容本身分占用1到多份内存容量。
    • Key名字本身是String对象,最大长度512MB
    • 建议Key使用":"字符进行分层。
    • Redis缓存场景,建议Key都设置TTL值,保证不使用的Key能被及时清理或淘汰,使内存复用。
    • 有业务60%的Key 100天都未访问过一次,或已废弃。
  • 程序架构规范

    • Cluster模式中,热点Key和大容量Key尽量设计"打散”;避免集群不均,导致某个分片QPS“过载“和容量过大。
    • 避免使用时间复杂度为O(N)的访问模式或命令;对元素比较多的集群key使用时间复杂度为O(N)命令,往往。
    • redis是single-threaded server,如果命令耗时过长,命令独占server,其间不能响应其他命令,导致服务超时。如果执行时间比较长,甚于导致判断节点为下线状态,触发集群故障转移。
    • 查看命令时间复杂度,官方文档Commands,每个都对应有Time complexity属性;如HGETALL命令Time complexity: O(N) where N is the size of the hash.时间复杂度为O(N)的常见命令: keys mget mset hgetall
  • 容量规划

    • 可以通过工具计算出需要的容量
--------EOF---------
微信分享/微信扫码阅读