18个最可能限制系统扩展能力的瓶颈,请程序员注意 [复制链接]

2019-9-9 10:32
XGBS 阅读:90 评论:0 赞:0
Tag:  性能

1. 二阶提交

通常当数据库中的数据有变化时,它会被写入本地服务器的内存和磁盘中。但是,当数据库是集群或者分布式系统的话,一个提交不仅会发生在本地,还会发生在远程。二阶提交意味着必须等待远程服务确认。然后由于网络和其他的延迟问题,这样的提交相比单机数据库的提交要慢很多。

主从的同步复制也有这样的问题,因此,MySQL的解决办法是半同步(semi-synchronous:MySQL5.5才有的特性,半同步只需要等待slave写成功日志响应即可,并不需要等待slave完成真正的提交),这实际上是二阶提交的妥协。

2. 串行处理

当顾客在等待拥有10台收银机的超市结账时,这是并行工作的。如果有9个收银员正在休息午餐,只有1个收银机是开放的,那就变成串行的了。突然,超市就会因为收银机问题而排起长长的队伍,让顾客非常沮丧。

WEB应用一定要不惜一切代价避免串行,典型的串行比如分布式锁。否则,有串行处理的地方就会成为你整个系统的瓶颈。

3. 内存不足

对于每一层来说,内存都是非常重要的。缓存最合适的地方有哪些呢?接下来举几个栗子。

  • 浏览器

浏览器缓存似乎遥不可及,直到您意识到浏览器直接从Web服务器获取它渲染页面需要的数据。因此,如果页面中包含的对象有很长的过期时间,浏览器就能否把它们缓存起来,而不需要多次重复抓取。不仅对用户体验更快更好,而且也减轻了服务端的压力。

  • 页面缓存

页面缓存(不是操作系统层面的pagecache)需要用到比如Varnish(https://www.varnish-cache.org/,淘宝和拼多多都有用过该技术)这样的技术组件。它不能像Apache那样处理复杂的页面,但是它相比Apache能更好的处理简单的页面,因此它一般会被部署在Apache前面用来先处理简单的页面。

  • 对象缓存

一般会用redis(或者memcache)来处理对象缓存,对象先序列化成比如json,然后保存到redis中。我们的应用在访问数据库前,先访问redis看是否有我们需要的对象,如果Redis中有,那么从Redis中获取对象的速度是MySQL数据库的几十倍甚至上百倍。从而能提高服务的响应速度,一眨眼就返回用户请求的所有数据,让用户体验更好。

4. 监控和指标不足

监控应该是如此基础的东西,你无法想象没有它的工作。 然而,有些公司和项目就是没有,或者不足,没有足够的监控,一些服务器或关键组件被遗漏了。

随着时间的推移,收集系统和服务器级数据以及应用程序和业务级可用性的数据同样重要。

5. 日志不足

日志和监控关系非常密切,尤其当你定位问题或者调试的时候,你恨不得需要更多的日志。无论是服务器系统日志,Apache和MySQL日志,缓存日志等。而且需要做好日志滚动,以及历史日志备份或者清理。

6. 数据库单点

你的数据库至少应该有一个slave,它的好处是当master出现问题后,slave顶上来能更快的恢复数据库从而提供服务。哪怕你的slave不承担读的压力,你也应该有一个冷备份的slave。

7. 把数据库当作队列

MySQL数据库很擅长存储关系型的表数据。不幸的是,它不太擅长作为队列服务。尽管如此,很多开发者依然有一些不好的使用习惯,例如:你的应用有一些JOB任务表,也许有一个状态列,这个列的值有这些:INIT,PROCESSING,INQUEUE,FINISHED等。如果是这样,那么你无形之中把数据库表当作队列来使用了。

由于锁争夺以及扫描和轮询以便找到更多可执行任务,这种解决方案最终会遇到可伸缩性问题,而且这种状态列不太适合创建索引。如果有队列方面的需求,更推荐使用RabbitMQ或者kafka。

8. 使用数据库全文检索

对任何一个应用来说,搜索都是非常重要的功能。尽管MySQL有全文检索功能,但是它的前提是表必须是MyISAM引擎。然而MyISAM表没有事务特性,而且它的性能和体验都非常差。

成熟的方案都会借助于专业的搜索服务,比如:Solr和ElasticSearch。而且这些专业的搜索服务客户端支持非常多的语言,访问速度也非常快。而且弹性伸缩能力都做的很好。

9. ORM

ORM有助于快速原型设计,并允许那些不擅长SQL的开发人员读写数据库。它们更快,更干净,并提供更快的功能交付。

然后,当DBA发现一个运行缓存的SQL,并要你的团队修复时,你会发现使用ORM框架的话,排查问题是非常困难的。但是,对于开发人员来说,排查并优化问题SQL是经常要做的事情。如果你的项目使用的是ORM,就会带来巨大的技术债,而且替换的代价也非常大。所以建议项目使用MyBatis这样的框架。

10. 没有仪表盘

汽车如果没有仪表盘,你将没办法开车。同样的,如果你的应用没有仪表盘,也会带来很多阻碍。应用仪表盘能够暴露应用程序内部工作的信息。他们记录时间并提供有关应用程序花费时间的反馈。

一个非常流行的Web服务仪表盘解决方案是New Relic(http://newrelic.com/),它提供了吸引所有人的可视化仪表板 - 项目经理,开发人员,运营团队,甚至业务部门都可以在图表中查看并查看 发生了什么。

11. 没有代码仓库或者版本控制

尽管在今天来说,这样的情况是非常罕见的。总之,你的公司千万不要在这个方面成为“鹤立鸡群”的那一家,一定要把代码放到代码仓库中,强烈推荐Git+Gitlab组合管理。

如果你不用版本控制和代码仓库,那么当你的项目越来越复杂时,欠下的技术债就会越来越多,最终导致整个迭代举步维艰。

12. 单点问题

如果你的数据只存在某一单实例数据库,这就是一个单点问题。如果你的服务全部部署在一台服务器上或者一块磁盘上,这也是单点问题。

这些单点问题必须不惜一切代价彻底消除它们。此外,意识到系统的单点问题也比较困难。比如,依赖单一的云厂商,这实际上也是单点问题。因为假如你的服务全部在AWS上,当AWS出问题时,你的服务是完全不可用的。AirBNB就在AWS出现故障时避免了这个问题。

13. 预览模式缺失

如果你尝试在头条上发表评论,或者在微信上发送一条朋友圈动态。你可能会收到这样的提示信息:“对不起,请稍后再试!”。或者你在淘宝上只能预览商品,但是不能下单。

这种现象就是指,应用允许你,但不允许你。这可能是master库宕机了,但是slave库还健在。我们的系统需要具备这种能力,当master库宕机后,slave能正常的处理读取操作,只是写操作暂时受到影响。

14. 缺少沟通

在这里谈论沟通可能有点奇怪。但是强大的沟通渠道是非常有必要的,团队成员必须知道在遇到麻烦时应该去找哪些人。而良好的沟通需要自信和知识渊博的领导力,以及倾听和改进的开放性。

15. 缺乏文档

文档发生在Web应用程序的许多层中,比如:前端、UI、后端、运维等。开发人员需要设计文档,以便为查看该代码的后来者提供提示和参考。运营团队需要为配置文件添加注释,以便在事情中断时提供更改历史记录和洞察力。并且应该在公司的wiki中记录业务流程和关系,以帮助人们找到自己问题的解决方案。

文档在各个层面都非常有帮助,写文档是每个人都应该具备的习惯。

16. 缺少故障演练

故障演练总是被一推再推。团队可能会说,“我们有备份,我们能cover住这个事情。” 没错,直到他们尝试根据备份恢复时才并发现它们不完整,可能丢失了一些配置文件或关键数据。

故障演练能够帮助团队在他们真正需要之前完成动作。您的公司应该把它当作运营团队的一部分日常工作,每年几次故障恢复整个应用程序。而且使用云服务器会让这个事情变得更容易。在这个过程中,您将了解需要多长时间,困难的步骤在哪里,以及需要注意什么。从而在当故障真正来临时,能够做到从容应对!

17. 鲁莽行为

你骑着快马进入小镇,带着枪走进沙龙,你觉得你会交朋友吗?不,你只会吓唬所有人。信心很好,但最好与团队合作,团队的智慧比任何个人都要强。

团队之间需要传达正在改变的东西,以管理的方式进行沟通,任何意外等等都应该有应对计划。谨慎才能赢得了胜利。并且始终有一个B计划(Plan B),做的事情做好有回退的办法,要知道哪些命令具有破坏性,哪些命令无法撤销。

18. 日益增长的技术债

随着应用程序多年来不断发展,团队可能会花费越来越多的时间来维护历史代码,解决历史问题。因此,他们没有多少时间投入新功能。如果您发现技术债不断增加,可能是时候咬紧牙关来一次重构了。重构需要时间,而且重构不会和开发新功能、满足客户需求一样带来立竿见影的效果,但从长远来看,这是非常值得去做的。


我来说两句
您需要登录后才可以评论 登录 | 立即注册
facelist
所有评论(0)
领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )