一步一个脚印:解密唯品会中Redis集群架构演进与功能定制

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 在2016杭州云栖大会的“开源数据库之Redis专场”上,来自唯品会的高级数据工程师申政带来了题为《Redis在唯品会的应用实践》的精彩分享。分享中,他主要介绍Redis集群架构演进、Redis使用经验以及唯品会对Redis二次开发实践积累三部分,干货满满,精彩不容错过。

在2016杭州云栖大会的“开源数据库之Redis专场”上,来自唯品会的高级数据工程师申政带来了题为《Redis在唯品会的应用实践》的精彩分享。分享中,他主要介绍Redis集群架构演进、Redis使用经验以及唯品会对Redis二次开发实践积累三部分,干货满满,精彩不容错过。

以下内容根据演讲PPT及现场分享整理。


Redis集群架构演进

目前在唯品会内对Redis的使用属于重量级别,目前在唯品会内大概有8000个Redis实例、1000台物理机、500个应用。

ac5f135676f37a118e26fdb366e39b687e02b8e9

上图是唯品会对Redis使用的演进历史图。在2014年7月左右,采用的是客户端分片(Client Sharding)的架构;2014年7月到2015年12月期间,主要采用的是Twemproxy集群模式;从2015年6月至今,唯品会内主要采用Redis Cluster框架。

下面简单介绍上述三种框架的优缺点。

Client Sharding架构

9130e5cd0b9cb2ec393426c003b39088df42c2ca

Client Shareding的架构如上图所示,从图上可以看出该架构十分简单稳定,但它需要业务方面自定义Key分布,进而增加了业务开发难度和工作量;其次该架构的在线扩容能力非常弱,并且不能在数据库层面提供Failover能力。

Twemproxy架构

1eeba89c40e45d3cad1b0223df02e72574e3c186

唯品会内对Twemproxy的使用超过2000个实例、800台物理机、150个应用,其框架如上图所示,相比于Client Shareding的架构复杂了很多,通过在Twempoxy层上增加了LVS,既增加了Twempoxy的高可用,又可以在LVS下任意增加或删除Twempoxy节点,很好的支持了增量业务。

Twemproxy负责数据分片,下面可以挂载多个Redis节点,此外架构中通过采用Redis官方提供的HA保证主从之间的高可用。Twemproxy具有很多优点:

  1. 支持数据自分片和一致性Hash
  2. 同时支持RedisMC协议
  3. 支持pipelinemgetmset等多Key操作
  4. Twemproxy自身扩容简单,可以做到用户无感知,降低了业务开发复杂度

事有正反面,在使用Twemproxy过程中也发现其存在很多不足:首先该架构十分复杂,导致机器成本高;其次,Redis和MC扩容比较难;此外,该架构分为三层,每一个环节都可能成为集群的性能瓶颈;客户端的请求需要经过三层的请求链路,导致请求相应时间长;最后尤其值得注意的一点是:它的运维成本很高。

Redis Cluster

adabc412cf3cc1e54c7df768fefa7f91a58302e0

Redis Cluster框架如上图所示,从图中可以看出:它是一个无中心框架,集群中每个节点完全对等,任一节点都与其他节点保持一个长连接,通过高速协议维护整个集群的状态信息;并且该架构还提供了自动Failover和在线扩缩容能力;同时采用单层框架,相应时间短;此外,由于该架构中客户端与Redis直接相连,相比于Twemproxy架构,节省了一半的机器开销。

但该架构对客户端依赖非常重,需要智能客户端支持;对Mget、Mset、Pipeline支持不友好。

一些经验

下面分享一下在使用Redis过程中踩过的坑,供大家借鉴。

f01cd70dd9f0e516d586027c86673a131e6036a3

在使用Twemproxy时,常发现线上同目录实例的内存特别大,达到几G、几十G,甚至比Redis占据的内存还要大。这是因为在业务开发时,一次使用Pipeline过大,命令数量特别多,这是由于Twemproxy是一次性接受完客户端发来的所有数据再转发导致;同时Twemproxy申请的内存申请后不释放,进而导致了内存只增不减。

因此,建议在使用Twemproxy时,一次Pipeline包含的命令量适中,最好不要超过1000个。

ac90c8d9040c8479e5f99a4c0e6a05d37bf90744

按照Twemproxy执行Hash规则,当后端server出现问题时,理论上只会影响当前Server内的Key。但我们遇到的问题是:当其中的一个Server出现问题时,其他Server返回请求都出现问题。这是由Twemproxy代码结构所决定的,它对每一个客户端的链接都有一个队列,当队列头部的请求恰好是出现问题Server的请求(不能响应到Twemproxy),则该请求会将队列中后续的其他Server请求全部卡死,此时这些请求都缓存在Twemproxy,不能相应到客户端,进而导致Twemproxy的内存飙升。

还有一点需要注意:Twemproxy中Timeout参数,默认是永远等待,即便Server没用相应,但其仍认为该Server是正常的,一直等待下去。因此在使用Twemproxy时,务必要注意Timeout参数的设置。

b0966ed7566afdcbaf3b4647de3bdf63aa0d8029

Twemproxy中设计了剔除策略。有时Twemproxy下面挂载的Redis/MC并没有挂掉,网络也没出现问题,但Twemproxy会剔除某些Server。这是由Twemprox自身的设计缺陷导致,在Twemproxy中存在server_connections和server_failure_limit两个参数,前者表示Twemproxy与后端Server建立长连接的数量;后者是Twemproxy与后端server出现问题的连接数,如果连接连续出现问题,则触发剔除策略。

在实际使用时,建议设置server_connections数目小于server_failure_limit,以规避剔除现象的发生。

416ca2d5df964361d451af1f7c64646bf899a469

在使用Twemproxy时,曾出现过这种情况:业务监控客户端连接只有几十个,而Twemproxy端连接却有几千个、甚至上万个。

这是由LVS机制导致的:LVS内有一个专门维护客户端向后端发起连接数量的表,其内置了exprie机制,当连接在15min没有活跃的请求时,会将该连接从表内剔除,而不通知双方。此时,Twemproxy认为该连接是正常的,而客户端发现连接不通时,会新建连接继续发送请求,长此以往,两者的连接数差距越来越大;并且Twemproxy的文件描述符会消耗很快,直到不能再正常建立连接。

为了解决该问题,在Twemproxy中增加了TCPKeepalive功能,完美地规避了该情况的发生。

 

37416899a9f477866a9d30a70ccaab1e991a303c

如果在使用Twemproxy时,发现线上Twemproxy内存监控曲线如上图所示,并且在业务中还用到了Mset命令,基本上可以确定是由Mset引起的内存泄露。

在Mset命令进行拆分时,由于特殊情景导致内存不被释放,进而导致Twemproxy内存越来越大。应对该问题,可以采用重启Twemproxy进行解决。

在使用Redis Cluster的过程中,唯品会积累了一些实践技巧,先总结如下:

  •  Cluster-require-full-coverage建议为no(官方默认为yes)
  •  Cluster-node-timeout建议适当增大
  •  jedisCluster注意捕获异常MaxRedirectionsException(该异常表示命令执行不成功)
  •  不建议使用mget、mset等multi-key命令
  •  尽量使用官方redis-trib脚本管理集群,不要轻易使用Cluster命令

二次开发

在使用Redis过程中,为了更加满足业务需求,唯品会对其进行了二次开发。

de641c00e05d1c9c27218ac63f24aa43a051aecb

对于Twemproxy,为了保障其高可用性,增加了replace_server命令,当Redis Master挂掉之后,Sentinel调用脚本通过replace_server命令把Twemproxy中的Master替换成Slave。

 

d41ae42b8e8819e3467426d13b867095d318c57a

目前唯品会线上最大的Twemproxy集群用到的实例超过100个,如果想更改Twemproxy配置时,工作量是比较大的。因此,唯品会在Twemproxy集群中集成zookeeper,Twemproxy集群的配置信息统一由Zookeeper管理、分发,用户无感知。

7b00f3dbdd75ed4dc66eb1c2c1b9e3d68045bb72

唯品会对MC也进行可二次开发,由于MC中不存在主从概念,但MV集群中其中一个节点挂掉之后会对后端的数据库造成很大的压力。为了解决该问题,在Twemproxy层面增加了复制池(Replication pool)功能,在Master pool和Slave pool之间建立主从关系,客户端同时写入两个pool内;读取时,首先读取Master pool中内容,当Master pool中无数据时,并不会回传到数据库,而是从Slave pool中获取数据,有效减轻由于MC挂掉带给后端数据库的压力。

5ca14f3eeba46123bc54f4936b91a64204afd701

借鉴Redis,在Twemproxy中增加了Slowlog功能,停留时间;此外,还增加简单统计信息功能,将一天分为几个时间段,每个时间段记录Slowlog次数,便于定位Slowlog和解决Slowlog。

5989cc4624654a74592b33027b19acb6e76b2382

增加多线程功能是对Twemproxy一次大的改动。Twemproxy提供的QPS在几万左右,由于线上每个物理机上只能部署一个Twemproxy,导致了物理机极大地浪费。借鉴MC多线程模型,建立了master线程+N个worker线程多线程模型:master线程负责监听端口,接受新的客户端连接;worker线程负责处理客户端请求。Twemproxy多线程开6个线程时,QPS可以达到35万/s,同时也节约了千万服务器成本。

24c6e2cb35f47e6255af217b3364285d26ad5e5f

很多用户在使用Redis Cluster是都会遇到这样问题:flushall删不掉数据;明明Master是存活的,网络也正常,但Cluster却执行了failover。这是因为Redis是单线程的,在执行时间复杂度为O(n)命令时,线程被阻塞,无法响应其他节点的ping命令,造成假死现象,进而导致主从切换。

针对该问题的处理方式是:增加了额外进程监听额外端口(extra-port),当超过cluster-node-timeout/2s时间,ping请求没有收到回复,主动向extra-port发送ping请求。

4de373083adff8a7b9db3fc9760ed44b6428c9d2

最初上线Redis cluster时,很多客户端并不是友善支持,因此增加了Redis Cluster客户端功能,在Hiredis上进行功能改造使其支持集群模式,用于:

  •  解析并更新路由表
  •  处理moved/ask错误
  •  内含Max redirect机制
  •  支持mget、mset、pipeline、异步API

8020c304170a7b009eab361a302367e726e0cb6a

为了应对Redis集群之间的数据迁移,唯品会开发了Redis Migrate迁移工具,它是基于Redis复制功能的,在迁移过程中,老集群正常对外提供服务;并且支持多线程异构迁移,支持Twemproxy、Redis Cluster、RDB文件和AOF文件恢复;同时迁移过程也可以实时查看;此外,该迁移工具还具有比较完善的数据抽样校验机制,保障迁移数据的一致性。

da2a33785b5631e0b8b19b0aab6b7870d735ed89

Redis Migrate具体迁移步骤如上所示,这其中关键点是左侧的配置文件,这里不不再一一叙述。

300f6c5c8d2863d3b4d85d4e5cf38be5f180c631

Reids多线程是目前唯品会正在改造,借鉴于上文提到的Twemproxy多线程改造,将Redis改造成Master+N个worker多线程模型:客户端有worker线程管理;多线程中不可能避免有锁的存在,Redis中存在DB级别读写锁,通过单独后台线程处理过期key和dict维护。

目前Redis多线程实现支持五大数据结构(String/list/hash/set/zset);支持100个Redis命令(包括管理命令)。

398fdd57fcd40c0314e1a88f15ef067169523599

Redis多线程中,为了降低DB锁竞争,引入了逻辑DB。一个逻辑DB包含N个真实物理DB,用户使用的是逻辑DB。一个逻辑DB的所有Key分散在各个物理DB上吗,每个物理DB拥有一把读写锁——pthread_rwlock_t。

7797f7ac18a774ed376d836a16bb654796a67b88

上图是Redis处理客户端请求的命令过程,这里不再一一叙述。每个Worker线程都会进行上图六个步骤,DB锁的竞争主要是在第四步和第五步上,其他步骤Worker之间完全并行。

Redis多线程-性能测试

abc7b2d2cf9e6a9203b335cdc826978a946d20e5

上图是用于Redis多线程性能测试的测试环境配置。

701aae11ee987a1785bc3e85d0e15162b523e802

测试用例图上图所示,从图上可以看出SET的效率为34万左右;GET效率为40万左右。

ce87b1f542640e0d5eeb0f800f21ea02c854373b

热Key问题是使用Redis中不可避免的问题。在Redis多线程中,遇到热Key首先将其拆分,将其分散到不同的Redis实例中。上图是多线程中针对热Key的性能测试:只写一个key时,四个线程的QPS可以达到30万/s;只读一个Key时,四个线程的QPS可以达到43万/s,一定程度上有效改善了热Key问题。

附录:

文章中提到的唯品会对Redis二次开发的源代码开源地址:http://github.com/vipshop

 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
打赏
0
0
0
0
79430
分享
相关文章
Redis 逻辑数据库与集群模式详解
Redis 是高性能内存键值数据库,广泛用于缓存与实时数据处理。本文深入解析 Redis 逻辑数据库与集群模式:逻辑数据库提供16个独立存储空间,适合小规模隔离;集群模式通过分布式架构支持高并发和大数据量,但仅支持 database 0。文章对比两者特性,讲解配置与实践注意事项,并探讨持久化及性能优化策略,助你根据需求选择最佳方案。
50 5
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL集群架构负载均衡故障排除与解决方案
本文深入探讨 MySQL 集群架构负载均衡的常见故障及排除方法。涵盖请求分配不均、节点无法响应、负载均衡器故障等现象,介绍多种负载均衡算法及故障排除步骤,包括检查负载均衡器状态、调整算法、诊断修复节点故障等。还阐述了预防措施与确保系统稳定性的方法,如定期监控维护、备份恢复策略、团队协作与知识管理等。为确保 MySQL 数据库系统高可用性提供全面指导。
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 +  无锁架构 +  EDA架构  + 异步日志 + 集群架构
融合AMD与NVIDIA GPU集群的MLOps:异构计算环境中的分布式训练架构实践
本文探讨了如何通过技术手段混合使用AMD与NVIDIA GPU集群以支持PyTorch分布式训练。面对CUDA与ROCm框架互操作性不足的问题,文章提出利用UCC和UCX等统一通信框架实现高效数据传输,并在异构Kubernetes集群中部署任务。通过解决轻度与强度异构环境下的挑战,如计算能力不平衡、内存容量差异及通信性能优化,文章展示了如何无需重构代码即可充分利用异构硬件资源。尽管存在RDMA验证不足、通信性能次优等局限性,但该方案为最大化GPU资源利用率、降低供应商锁定提供了可行路径。源代码已公开,供读者参考实践。
100 3
融合AMD与NVIDIA GPU集群的MLOps:异构计算环境中的分布式训练架构实践
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用的算法是哈希槽分区算法。Redis集群中有16384个哈希槽(槽的范围是 0 -16383,哈希槽),将不同的哈希槽分布在不同的Redis节点上面进行管理,也就是说每个Redis节点只负责一部分的哈希槽。在对数据进行操作的时候,集群会对使用CRC16算法对key进行计算并对16384取模(slot = CRC16(key)%16383),得到的结果就是 Key-Value 所放入的槽,通过这个值,去找到对应的槽所对应的Redis节点,然后直接到这个对应的节点上进行存取操作
【赵渝强老师】达梦数据库MPP集群的架构
达梦数据库提供大规模并行处理(MPP)架构,以低成本实现高性能并行计算,满足海量数据存储和复杂查询需求。DM MPP采用完全对等无共享体系,消除主节点瓶颈,通过多节点并行执行提升性能。其执行流程包括主EP生成计划、分发任务、各EP并行处理及结果汇总返回。为确保高可用性,建议结合数据守护部署。
Redis原理—3.复制、哨兵和集群
详细介绍了Redis的复制原理、哨兵原理和集群原理。
|
5月前
|
redis主从集群与分片集群的区别
主从集群通过主节点处理写操作并向从节点广播读操作,从节点处理读操作并复制主节点数据,优点在于提高读取性能、数据冗余及故障转移。分片集群则将数据分散存储于多节点,根据规则路由请求,优势在于横向扩展能力强,提升读写性能与存储容量,增强系统可用性和容错性。主从适用于简单场景,分片适合大规模高性能需求。
134 5
揭秘 Elasticsearch 集群架构,解锁大数据处理神器
Elasticsearch 是一个强大的分布式搜索和分析引擎,广泛应用于大数据处理、实时搜索和分析。本文深入探讨了 Elasticsearch 集群的架构和特性,包括高可用性和负载均衡,以及主节点、数据节点、协调节点和 Ingest 节点的角色和功能。
162 0
Redis--缓存击穿、缓存穿透、缓存雪崩
缓存击穿、缓存穿透和缓存雪崩是Redis使用过程中可能遇到的常见问题。理解这些问题的成因并采取相应的解决措施,可以有效提升系统的稳定性和性能。在实际应用中,应根据具体场景,选择合适的解决方案,并持续监控和优化缓存策略,以应对不断变化的业务需求。
111 29
下一篇
oss创建bucket
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等