业务场景:
最近几个月都在做项目接口优化,压测等工作。
目前项目缓存主要用的redis和spring的cache以及Ibatis的cache。但绝大部分还是用的redis.
基本步骤:先去缓存查,有就直接返回,没有就去查数据库,然后加失效时间,存缓存,然后返回,但是这中间有个问题,像那种业务逻辑比较多的,虽说缓存的那几秒速度快了,TPS上不去,缓存的失效时间到了,还是会把压力透传到db上。之前用户量少,随随便便就可以撑住,随着用户增长,手机小屏用户变多,机顶盒用户变多,现在用户在700万+,而且为了做推广,做了开户抽奖活动,并发,性能问题越来越严重。
起初优化
起初想到的就是优化代码及业务逻辑,我们三个人,便开始撸代码之旅
代码包括
- 使用多线程,线程池去做处理
- 梳理逻辑去掉冗余代码
- 使用jmap,jstack去查看耗时的堆栈信息
- JProfiler 优化接口
- Jmeter压测接口
- 其他
其中db包括
- 加索引
- 改sql查询逻辑
- 分库用的mycat
- 分表用的简单的%32,算hash
- 尽量不在for内查询
- 小米的soar(https://www.jianshu.com/p/2c3bd3a7714e)
- 其他
等这些都做完,出包放到线上,效果还是不好,并不能满足领导性能的要求及想要的TPS
继续优化
然后又是开会讨论讨论研究研究...,最后定了做一个CacheManager(缓存系统),最终达到领导想要的TPS及指标。
这里简单说一下cm一条线路,还有几条线路就不说了,Metadata和API通过MQ做消息传输,消息队列之前用的ActiveMQ,然后改为RabbitMQ,好处网上有一堆,在Metadata侧发数据给API侧时,将数据同时传到cm侧做处理,主要是缓存.以此来减少接口对数据库的压力。
此方案的缺点
觉得MongDB,属于鸡肋
理由,redis已经有持久化了,如果只做展示,运维,加入mongo在这个场景下,会占用很多的空间,各有利弊吧
数据一致性的问题
因为以后基本不过db,直接去缓存取,虽然redis有持久化,但是我们还是引进了MongDB,存redis时顺带存mongo,使用vue写了个简单页面,然后cm提供一组供运维页面使用的接口,在页面做简单请求实现,以此来解决数据一致性的问题(其中包括查问题数据重新刷到redis)
redis相关的问题
压力全部转移到redis,如果redis出现问题,将是致命的,细的我也没怎么看,说几个我知道的
- 网络延时导致阻塞
- 阻塞通过查看慢查询日志,找病因
- redis模式的合理选择
- 最主要的加机器,机器,机器,重要事说三遍
总结
此方案或许有很多漏洞,不恰当之处请包涵,但整体效果是达到了领导的要求,中间我们就讨论过数据一致性问题,为啥不用binlog去做数据恢复,为啥非得加mongo,画页面等,我当时提的建议是,对于数据一致性修复,咱们得弄可视化让运维去做处理,总不能每次都提供脚本吧。
对于redis模式的选择,推荐使用集群,理由如下
单实例
对于单实例,学习使用就行,在项目中基本不会使用此模式.单实例除小系统外,撑不起整个服务。
主从模式
数据会通过主同步到从,但是受限于单台机器的性能。
哨兵模式
项目之前用的哨兵模式
优点:虽说哨兵有主写从读、主从复制,故障自动转移,通过选举做的.。
缺点:还是受限于单台机器性能,而且数据上去后,每台机器都保存着全量的缓存数据,如果还做持久化了(RDB,AOF),那占用的资源会更大。
集群模式
项目现在用的模式
优点:主从复制,高可用,通过16384个槽,均匀分配到不同的主节点,key通过crc16算槽,压力分配到每台机器上,支持动态加减节点,扩容及收缩,故障自动转移等
缺点:耗机器,需要多台机器
相关资料
链接: https://pan.baidu.com/s/1PedVDbb2NjODoHWuGbiQmw 提取码: 5ii4