顾黄亮
作者顾黄亮课题专家组·2019-05-06 12:09
技术总监·畅销书作者

Redis选型、调优、监控、数据一致性等四大难点探讨总结

字数 8932阅读 7178评论 3赞 12

Redis是一个作用于内存的数据结构存储系统,它可以作为数据库、缓存或者消息中间件,支持多种类型的数据结构。与传统金融系统相比,互联网金融系统更多的侧重系统的高并发访问、海量数据的处理,又有传统金融对数据处理的可靠性和连续性。账务核心系统是互联网金融系统中非常重要的一个系统,它承载金融业务的开展,批量处理业务流水,进行账务的核对,客户贷款的期次、利息、罚息的计算,还款计划的生成等重要功能。随着金融业务越来越广泛、客户数越来越多、账务数据趋于庞大,给账务处理工作带来极大的压力,造成严重问题而致不能正常开展业务。这次我们就重点围绕Redis内存数据库集群的特性和在互联网金融账务核心系统中的应用进行交流探讨:包括集群的选型、业务场景的应用和使用中遇到的一些问题。同时,我们也在尝试将redis技术应用到更多的场景中,也在进行redis cluster在多机房架构下进行大二层的组网,以探索更多的实践领域。
为有效帮助各运维同仁们在redis使用及建设过程中,有的放矢,消除疑虑,切合自身运维工作实际现状,结合大家的关注问题和交流内容进行了4大分类总结,希望给大家有帮助。

**(1)、redis该怎么选择版本;如何进行redis集群的选型;
(2)、redis的调优该怎么做;
(3)、redis该如何监控;
(4)、redis使用过程中使用哪些场景,如何更好更合理的使用redis**

一、redis该怎么选择版本;如何进行redis集群的选型

1.1想要咨询下,现在redis都已经出来5.0版本了,那现在是哪个版本比较稳定哪?一般现在生产上采用哪个版本?生产上部署redis cluster的架构多吗?这个在银行业务中有采用这种架构的吗?
答:目前用的比较多的是3.0,3.2和4.0三个版本。 也会把一些新出的功能合并到现有版本上。

1.2 redis集群如何实现?有哪些好处?如何搭建redis集群,集群有哪些好处?
答:twemproxy、codis、redis-cluster、哨兵。集群的好处:横向扩展、便于管理、提高业务连续性

1.3 Redis生产部署中集群方案简化部署?目前,在实际生产部署中,已经在使用Redis主备方案的部署,但还仅是依靠硬件负载均衡设备进行应用分发后,由2台Redis服务器实现主备。基于Redis在系统仅是做为数据写入缓存的单一功能,想了解一下除了Redis多机集群,是否有简单的Redis双机部署方案,性能如何?
答:没理解题主现在的架构是什么样的?2台redis服务器是指两台物理机还是两个redis实例?题主说的主备指的什么?以及要采用双机方案的目的是什么?20万的数据量不大,可以采用redis主从方式,搭配sentinel进行自动主从切换。如果团队开发能力较强,可以研究一下twemproxy开源架构。另外,redis是单线程模式运行的,为了充分使用机器的CPU资源,可以搭建多个redis实例,部署多套主从架构,或者使用twemproxy开源架构对数据进行分片,适应将来的业务量上涨。

1.4 redis数据库的优缺点及适用场景?
答:redis持久服务的特点,key-value键值类型存储系统,支持数据可靠存储,单进程单线程高性能服务器,恢复比较慢单机qps(秒并发)可以达到10W,适合小数据高速读写访问,redis存储系统优、缺点:,可以持久化存储数据,支持每秒10W的读写频率,支持丰富的数据类型,所有操作都是原子性的,支持异机主从复制,内存管理开销大(低于物理内存的3/5),不同命令延迟差别大,官方网站:http://www.redis.io
主要使用场景分为两大块:01 缓存:热点数据放到缓存里,大部分情况命中缓存,不命中时,访问磁盘存储并更新缓存02 键值存储,独立使用缓存作为数据提供方。依赖于缓存服务的可靠性不高,业务对事务和数据的一致性要求不高。具体的,一般由架构师和开发人员,根据业务的特性,设计出具体的使用方法。

二、redis的调优该怎么做

2.1 redis的调优参数有哪些?如何配置?
答:一:第一个问题,redis的参数调优问题,根据场景不同,有不同的调优方法,以下列举踩过的一些坑的参数调优。我们的场景的海量数据,高并发。
(1)timeout参数,非常需要关注,官方对timeout的解释如下:该参数表示当某一个客户端连接上来并闲置timeout(单位秒)的时间后,Redis服务端就主动关闭这个客户端连接。我们发现如果客户端对连接处理比较差的时候,存在连接不释放的问题,导致连接池耗尽,单个redis默认的连接数是1000.所以需要在timeout参数做文章,强制释放无效连接,我们的参数调整为timeout 30000
(2)持久化参数,RDB和AOF究竟开哪个,很多人很纠结。其实选择很简单,两者的区别是持久化的颗粒度不一样,如果你关注数据的强一致性,选择AOF,如果你选择更好的性能,选型RDB。如果你选择极致的性能,又能容忍数据的丢失,那你可以完全不用开启持久化,当然了,集群是一定要开持久化的。
(3)tcp-backlog和maxclient,这两个参数可能大家也比较迷糊,maxclient模式10000,一般情况下是够了,但是在高并发海量访问的时候,还是会出现客户端缓慢的情况,那就是系统的限制,就是backlog参数,你可以理解为在三次握手时进入accept queue队列的最大值,也就是send_Q,所以这个值设大点是没有坏处的,我们的设置是1024
(4)重点提一下安全的参数,requirepass foobared 个人认为,如果你们觉得你们hold住,那就不用开,如果在DMZ区,数据又比较重要,那就开。个人认为,密码的作用不是你想象中的带给你安全,第一redis一分钟可以访问你想象不到的次数,如果弱密码,分分钟破解,第二auth命令是明文的,破解也很容易。
(5)maxmemory,这个参数比较常见,但是也非常的坑。如果你选择用,有个原则,你是当数据库用还是当缓存用,如果当数据库用,就不要开,如果当缓存用,可以开。曾经有个BUG,多个salve的情况下,会导致擦除主节点的数据。如果你开启这个参数,记得预留一些空间给系统的buffer。
二:遵循哪些原则,其实很简单,遵循你的使用场景和你对参数的了解。宁愿逐步踩坑逐步解决问题逐步深入了解,也不要盲从的调整参数。

2.2 redis与oracle中存有同一份数据,当数据发生变化时,应用程序是先写redis然后再同步到oracle,还是先写oracle然后再同步到redis呢,使用何种同步机制可以有效的解决这个时间差中两份数据的不一致性呢?
答:如果你是当数据库用,那就类似于电商抢购场景。抢购的场景中有个需要解决的问题是超买和超卖,意思就是说,我要控制库存数量,而且要保证可用库存的数量为0,不能出现负数。一般是把数据从oracle刷到redis,贴合题主的问题,那就是同样有一份数据,当数据变化的时候,是先写redis还是先写oracle?是先写redis,再写oracle,因为代码层面保证数据的一致性,在高并发情况下,悲观锁机制并不会很友好,而且影响性能。而redis天然的原子性事务,是可以保证数据的一致性。
如果你当缓存用,又要确保数据的强一致性,是可以先写redis,也可以先写oracle,如果先写redis,参考前一段话,采取redis的强一致性;如果先写oracle,那就采取悲观锁来实现。

三、redis该如何监控

3.1目前的监控系统是python到oracle取配置信息,经过运算之后再写回oracle,然后根据阀值来触发告警,在这样的模式之下redis是否有可以应用的空间呢?
答:当你的监控的需求具备秒级监控的能力后,你的web-db的架构就不再满足了
比如说以下场景
1:基于日志的流式计算
2:监控指标的基线
3:数据的统计分析
4:通用的计算周期
5:多维度的告警规则:如无数据告警、基于同环比的告警、基于基线的告警、
越来越多的监控场景、监控指标、触发器,redis的作用就是提供你更快、更优质的服务

3.2 redis的监控指标有哪些,如何做好监控?
答:内存使用。如果 Redis 使用的内存超出了可用的物理内存大小,那么 Redis 很可能系统会被杀掉。针对这一点,你可以通过 info 命令对 used_memory 和 used_memory_peak 进行监控,为使用内存量设定阀值,并设定相应的报警机制。当然,报警只是手段,重要的是你得预先计划好,当内存使用量过大后,你应该做些什么,是清除一些没用的冷数据,还是把 Redis 迁移到更强大的机器上去。
持久化。如果因为你的机器或 Redis 本身的问题导致 Redis 崩溃了,那么你唯一的救命稻草可能就是 dump 出来的rdb文件了,所以,对 Redis dump 文件进行监控也是很重要的。可以通过对rdb_last_save_time 进行监控,了解最近一次 dump 数据操作的时间,还可以通过对rdb_changes_since_last_save进行监控来获得如果这时候出现故障,会丢失(即已改变)多少数据。
Keys。通过获取Keyspace中的结果得到各个数据库中key的数量
QPS。即每分钟执行的命令个数,即:(total_commands_processed2-total_commands_processed1)/span,为了实时得到QPS,可以设定脚本在后台运行,记录过去几分钟的total_commands_processed。在计算QPS时,利用过去的信息和当前的信息得出QPS的估计值。

四.redis使用过程中使用哪些场景,如何更好更合理的使用redis

4.1我们的系统现在使用了两套redis;分别用作热点数据缓存、会话保持保存全局ID。热点数据缓存采用的是一主一从三哨兵(分别独立,共五个节点);会话保持采用的是一主三从四个哨兵(共四个节点,每个节点上启动了一个哨兵进程);这个是乙方给的方案,请教各位大神,这个方案可靠吗?能否使用cluster方案来替代呢?有必要吗?
答:你有两套redis,A作为热数据缓存,B作为回话保持。
缺点:A有5个节点,B有4个节点,9个节点中只有2个节点是主节点,提供服务,备节点只是冗余,存在比较大的资源浪费。优点:sentinel集群,客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息,做到代理层的可用性。切换至cluster后在资源使用率方面,按照9节点的规模,实际组网只能有8台,4主4从,资源使用率得到很大的提升,而且代理层分别由8个节点负担,因此,也能保证了可用性.

4.2如何将redis加入私有云paas功能,其多租户能力是否满足云平台需求?
答:需要二次开发。云上的redis实例或者集群都是用户独享的,redis本身不会使用多租户的能力。都是通过二次开发,为不同的用户搭建不同的redis实例或者集群。

4.3有哪些工具支持redis在线数据备份和还原?
答:这款treeNMS软件,就可以轻松实现redis在线数据备份和还原

4.4主机房部署了redis集群,并数据持久化。问题:要求容灾机房能在主机房发生灾难并不可修复的情况下,容灾机房能在一定时间内承担起主机房的业务能力。如何保障容灾机房的redis集群数据跟主机房一致??如何操作??谢谢
答:主要看你采用集群的方式,如果是cluster,请参考,关于双活机房中cluster模式的组网,根据你的业务场景来决定。如果redis的使用中并不处在核心链路上,完全当做cache来使用,且在击穿情况下有后续的数据库来支撑,可以放在同一机房内。如果redis的使用在核心链路上,当做数据库来使用,在单侧机房部署,不能保证多机房环境下的多活。以双活机房为例,集群有A、a、B、b、C、c节点,A、B、C三个节点部署在甲机房,a、b、c三个节点部署在乙机房,甲乙两个机房使用波分线路进行大二层透传,能够使某一业务同时在某一都使用同一网段地址。基于redis本身,能够实现双数据副本模式,当甲机房单侧异常时,乙机房单侧接管,重新完成组网,提供服务。
如果是其他集群,请描述,我再补充。我大概明白你的意思了,我猜测1:你应该没有使用集群模式,而且采取了无状态的三个节点,进行组网。2:你采取的cluster,三主三从都是部署在单侧机房。目前你的做法是AB两个机房,你集群部署在A单侧机房,另外在B机房又复制了A机房的集群镜像,当单侧机房故障时,B机的redis进行启动进行加载数据提供服务。目前我有个问题,你们有没有演练过?且应用要不要改redis的IP? 如果你们对redis的场景没有横向扩展的要求,建议在redis集群上加一层代理,比如sentinel、twemproxy通过代理去路由redis,同时redis的主备分别部署两侧机房,当主节点异常,备节点进行选举接管。

4.5多个系统共用redis集群,如何防止某个系统独占大量资源,导致其他系统不可用?
答:多个系统共用一套redis的前提,那就是不能对其他业务有影响。1:key-value的命名规范、2:定义使用场景、3:完善的监控、4:定期巡检慢查询日志

4.6 redis分布式锁与同类产品对比的优缺点?
答:其实,如果单纯为了分布式锁,其实redis并不是一个特别好的选择,如果配合你的场景,你对技术的掌握的程度,可以选择redis或者其他一些组件。下面我大概说一下我选择redis作分布式锁的一些理由1:redis官方有支持的分布式锁算法,且redis具备天然的原子性事务的特征、2:redis并发高,响应快需要、3:支持互斥,容错率高
但是redis也有一些不太好的地方,比如、1:因为原子性事务原则,客户端不可达的情况下,必须到了超时的阈值才能释放锁、2:需要不停的发送锁请求获取锁信息,增加开销

4.7 Redis 有什么Windows客户管理工具吗?
答:可以研究试用下RedisStudio。开源地址:https://github.com/cinience/RedisStudio/releases使用方法:https://blog.csdn.net/knight0513/article/details/64921632

4.8 redis cluster在多活机房中采取怎样的架构?
答:关于双活机房中cluster模式的组网,根据你的业务场景来决定。
如果redis的使用中并不处在核心链路上,完全当做cache来使用,且在击穿情况下有后续的数据库来支撑,可以放在同一机房内。如果redis的使用在核心链路上,当做数据库来使用,在单侧机房部署,不能保证多机房环境下的多活。以双活机房为例,集群有A、a、B、b、C、c节点,A、B、C三个节点部署在甲机房,a、b、c三个节点部署在乙机房,甲乙两个机房使用波分线路进行大二层透传,能够使某一业务同时在某一都使用同一网段地址。基于redis本身,能够实现双数据副本模式,当甲机房单侧异常时,乙机房单侧接管,重新完成组网,提供服务。

4.9 Redis Cluster什么情况下会导致数据丢失,应该怎么避免?
答:cluster模式下数据丢失,有两种可能1:请求击穿,写入失败,这个要从代码层面来解决;2:主从切换,从节点的数据跟主节点数据有差异。这个解决方式可以采取配置always参数,保持数据的大概率的一致性。

4.10 Jedis与Redisson应该怎么选择,实际使用中有什么不一样的地方?
答:Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
在伸缩性方面:Jedis使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。Redisson使用非阻塞的I/O和基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。在数据结构支持方面:Jedis仅支持基本的数据类型如:String、Hash、List、Set、Sorted Set。Redisson不仅提供了一系列的分布式Java常用对象,基本可以与Java的基本数据结构通用,还提供了许多分布式服务,其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service)。在分布式开发中,Redisson可提供更便捷的方法。综述:1:根据场景来选择;2:根据对两者的掌握程度来选择。

4.11 Redis主从间是异步复制,这里提到强一致是如何做到的?应用层的工作吗?
答:不得不说,redis的数据同步,强一致性是有前置条件的,强一致性的根据有两个前提,1:持久化文件的生成的一致性;2:持久化文件的写入的一致性针对1,目前有两种持久化方式,RDB和AOF,针对两者而言,其实都是异步的,两个都有优缺点,但针对落地数据而言,都是异步的,所以能做到准实时,不能做到真正意义上的实时。很多人有疑问了,appendfsync always这个参数明明是同步的,是能牺牲性能保证数据的一致性的。仔细看官网的介绍,AOF持久化中的文件写入操作其实是将aof_buf缓冲区的内容存放到了内存缓冲区中,这时还没有真正写入到磁盘中,这个缓冲区达到同步条件时,才会执行fsync将这个缓冲区的内容写入到硬盘中,完成文件同步。所以持久化和REDIS事务的原子性是解耦的。针对2,取决于持久化文件的大小,曾遇到一种情况,当持久化文件非常大的时候,同步也是需要时间的。综上所述,不能做到绝对的强一致性,只能做到可接受的范围的强一致性。

4.12在金融行业,为了保证数据的强一致性,应该选择哪种持久化方式?换句话说,在主从切换中,通过哪些途径保持数据的强一致性?
答:持久化并且要保证数据不丢失:可以开启aof备份,并且把appendfsync参数设置为 always ,保证收到写命令后就立即写入磁盘,但是效率最差,一般的sata盘只能支持几百的QPS。 可以使用高效的SSD磁盘提升性能。但是这也违背了redis高速缓存的初衷。主从切换:目前原生redis不支持同步复制,它的主从只能是异步复制,也就是无法保证数据强一致性。有些公司通过修改复制内核支持主从完全同步的复制。这也牺牲了性能和QPS。redis出现的目的是为了作为缓存提升访问性能,对数据一致性的支持相对比较弱。

4.13 redis目前好像3.0版本以上了,目前技术上分布式水平扩展成熟的方案有吗?希望推荐一个开源的解决方案。谢谢。
答:常用的有三种,rediscluster、twemproxy、codis。第一种是redis原生的集群,平滑水平扩容比较容易,后两种缓存服务代理。twemproxy特点:1.通过代理的方式减少缓存服务器的连接数。2.自动在多台缓存服务器间共享数据。3.通过不同的策略与散列函数支持一致性散列。4.通过配置的方式禁用失败的结点。5.运行在多个实例上,客户端可以连接到首个可用的代理服务器。6.支持请求的流式与批处理,因而能够降低来回的消耗。codis特点:1.Codis是一整套缓存解决方案,包含高可用、数据分片、监控、动态扩态 etc.。走的是 Apps->代理->redis cluster,一定规模后基本都采用这种方式。
2.Codis引入了Group的概念,每个Group包括1个Redis Master及至少1个Redis Slave,这是和Twemproxy的区别之一。这样做的好处是,如果当前Master有问题,则运维人员可通过Dashboard“自助式”切换到Slave,而不需要小心翼翼地修改程序配置文件。3.为支持数据热迁移(Auto Rebalance),出品方修改了Redis Server源码,并称之为Codis Server。4.Codis采用预先分片(Pre-Sharding)机制,事先规定好了,分成1024个slots(也就是说,最多能支持后端1024个Codis Server),这些路由信息保存在ZooKeeper中。5.Codis仅负责维护当前Redis Server列表,由运维人员自己去保证主从数据的一致性。rediscluster特点:1.无中心架构。2.数据按照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布。3.可扩展性,可线性扩展到1000个节点,节点可动态添加或删除。4.高可用性,部分节点不可用时,集群仍可用。通过增加Slave做standby数据副本,能够实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升。5.降低运维成本,提高系统的扩展性和可用性。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

12

添加新评论3 条评论

powxpowx技术经理ZWT
2019-05-13 17:51
学习一下!!!!
鲁花花生油鲁花花生油系统运维工程师联众
2019-05-08 20:49
学习学习,谢谢
jasonvonjasonvon系统架构师中广
2019-05-06 13:40
学习,感谢整理。

jemmy_fan@jasonvon 学习了,谢谢整理…

2019-12-13 08:09

jemmy_fan@jasonvon 学习了,谢谢整理…

2019-12-13 08:09
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广