数据密集型应用系统程序设计-读书笔记

当下所有的应用系统都是数据密集型,不是计算密集型,系统瓶颈不是因为CPU算力不足,而是因为大数据量带来的数据存储,数据计算,数据同步以及数据更新带来的一系列问题,具体表现形式有以下几种,比如redis和数据库的双写一致性问题,消息积压问题,redis集群或者MySQL集群中主从节点的数据同步问题,以及redis持久化问题。包括对于程序员来讲最大的并发同步问题实际上就是短时间内的大量数据计算,存储以及更新问题。
目前所有的系统结构设计都有如下的功能模块

  • 数据持久化模块,保存我们的数据用于记录但是的系统状态,常用就是数据库,比如MySQL,MongoDB等数据库
  • 缓存模块,记录昂贵的系统消耗的结果,用来降低系统压力加快下一次的读取速度。比如redis,RocksDB等内存数据库。
  • 搜索模块,用户可以通过关键字进行搜索以及对数据按需要进行过滤,常见的就是ES流处理,给其他进行进行发消息进行异步处理,减少系统压力,提高系统响应时间。比如常见的消息中间件MQ
  • 批处理,用于定时进行数据同步,比如我们常用的脚本和定时任务。
    redis,rocketMQ等各种中间件都有自己的独特的使用场景的特点,只能高效实现某种特定功能(比如redis重要就是用做换缓存,MQ基本都是用来异步,解耦,削峰,当时目前MQ都开始支持事务消息以保证对分布式事务进行支持和补偿)我们应用代码就是将各种中间件进行缝合成一个整体,同时保证数据在这些中间件中流转的正确性。
    • 当系统出现问题时如何保证数据的正确性和完整性
    • 当系统面临巨大压力出现降级如何保证用户依然有良好的体验
    • 当系统进行扩容时如何保证数据的正确性和完整性
    当下系统的重要考量点,可靠性,可伸缩性,可维护性
    • 可靠性
    程序正常使用下提供给用户需要的功能
    在超出预期负载和数据量下性能满足要求
    系统能够有效拦截未经授权的访问
    总结就是系统出现故障依然能够继续为用户提供服务。但是故障不等于失效。对于应用层面的代码而言,我们在日常业务实现和代码编写过程中的注意事项就是
    避免死锁消耗CPU,内存等公共资源而降低整体系统性能。
    级联故障,应用服务依赖的基础服务出现异常时导致服务不可用或者基础服务报错直接展现给用户。
  • 可伸缩性
    我们的系统为随着时间的增加,用户量和数据量也会同步增加。在负载增加的同时如何保证系统依然可用就是可伸缩性。
    • 负载考量
    我们每个系统的设计和实现都是针对特定的使用场景和使用人群,所以在描述系统负载时不同的系统就用不同的角度来进行。比如有的是统计每秒向服务器发出的请求数,数据库每秒处理的事务量,缓存命中率,系统在线活跃用户量。有时间我们处理一个请求会请求很多其他服务,就会出现巨大的扇出瞬时的系统负载会非常高,有时候这种请求会消耗很多系统性能。这种扇出有时候可以作为特定场景下的系统负载参数。(扇出就是说当我们为了完成一个请求而发出了很多请求去调用其他服务,虽然我们看似只处理了一个请求,但是听过远程调用也产生了很多请求,比如我们淘宝或者支付宝或每年都会统计你过去一年的消费记录进行汇总展示,这个请求实际上就是一个巨大扇出)
    • 性能描述
    【数据密集型应用系统程序设计-读书笔记】对于在线系统,我们主要考量的就是响应时间(response time),但是同样的请求每次请求服务的响应时间可能不一样,有时候会受到网络丢包,垃圾回收暂停,线程上下文切换,内存页切换等的影响。有时候响应时间最长的用户有可能就是最后价值的客户,在正常情况来看,响应时间越长处理数据多,客户价值就越大。
    有时候还会出现头部阻塞现象,由于服务器CPU数量有限,只能并行处理一定量的事务,只要有少量请求阻塞就能阻碍后面的请求处理导致后面所有客户端的响应时间变长。有时候当一个请求需要多个后端请求时那么这个请求的响应时间就成了最慢的请求响应时间。

    推荐阅读