后端资源常见的使用优化
随着服务端流量的不断递增,对底层资源的依赖也越来越重,连接数增多,IO负载高等,很多性能瓶颈由此产生。下面结合自身经验,主要谈谈DB/Redis/Mc的优化。
DB
DB的查询会触发磁盘IO,我们知道IO的代价是很高的,所以DB的优化主要从降低IO次数着手。
a. 优化慢查询
优化慢查询主要考虑从索引入手,众所周知,Innodb索引存储结构为B+树,真正的数据项只存在于叶子节点,所以要考虑降低树的查询长度,例如:有一表的列字段如下
`card` varchar(10) DEFAULT NULL,UNIQUE KEY `idx_card` (`card`),
explain SELECT * FROM `table` WHERE `card` = 187300;
由于SQL的隐式转换(关于隐式转换,推荐阅读Type Conversion in Expression Evaluation),这个查询并没有办法命中索引。需要类型进行对应,正确写法:
explain SELECT * FROM `table` WHERE `card` = '187300';
在比如COUNT,SUM,LIKE,等列运算,应尽量避免,具体结合对应的业务场景。比如:COUNT通过计数器缓存,LIKE使用最左匹配等。
b.分库分表
数据库的划分,可以按具体业务划分成不同的微服务库,这样方便单体资源的监控、扩容。例如:媒资库、用户库等等。
分表逻辑可以从两个维度考虑。一方面是水平分割,例如:常见Feed查询场景,我关注的一批(多个uid)用户的某些行为,数据表可以按照月或者天水平切分,具体的切分粒度要参考业务数据量,保证每张表的数据量都在百万行即可。
垂直切分的话,也分两个方面,一个是表列的切分,可以划分为内容表,索引表,主表,附属表等。表数据的切分要依据查询场景,例如:针对用户内容表的查询(主键查询基本内容),将uid取模hash即可。由于垂直切分写入更新时,要同时处理多张表,所以要考虑数据的一致性(原子性)。
Redis
a. 资源类型划分
我们知道Redis内部是以单进程的模式运行的,即每次只能执行一个redis命令,所以很容出现一种情况是,一个复杂的操作,例如:hash/set等导致用户进程卡住,连接没有及时释放,后续redis操作无法及时响应。这种情况,需要把Redis拆分成KV和复杂操作两个资源类型,KV时间复杂度为O(1),可以用于counter,kv缓存等常见场景,其他操作都放在复杂操作资源里执行。
b. 集群的使用
之所以单独说一下redis集群,是因为redis3.0之前官方并没有支持集群,集群的使用需要通过一致性Hash算法,但是要考虑到节点的容灾与新增节点后相邻节点的数据同步,对业务要求比较高。也有开源的集群方案,例如:codis,twemproxy、redis cluster等。MC
memcache常用于缓存临时数据,因为是内存kv,所以存储场景大多是基本content跟list数据。
对MC的优化主要集中在业务调用上,例如:DB写入后需要同步写入MC,DB更新后直接更新MC缓存,而不是删除。
另一方面,由于MC使用基于过期时间的LRU的方式淘汰内存,应该着重评估过期时间的设置,例如:设置了很多不过期(expire time为0)的数据,当逐步把内存占满后,设置过期时间的数据将很快失效,这样会导致MC命中率非常低。除此之外,资源的配置、key、过期时间等应该统一管理。
最后,业务对资源的操作也应该有统一的出入口,降低资源之间的相互依赖,保证模块化的资源可用性与可扩展性。
推荐阅读:后端资源常见的使用优化
- 点赞
- 收藏
- 关注作者
评论(0)