上篇说了,我们整个系统的复杂度在于高性能高可用的读和写。读达到了八万多,写达到了两万多,这个要求在一般的软件系统里面还是比较高的。先说一下我们的技术栈是Java,后端存储使用关系型数据库Mysql,前后端分离,有PC端,APP都是原生开发,15个人的研发力量。所谓详细设计其实就是需要确定细节,架构层面将诸多架构细节确定下来,按照确定好的细节在进行逐步推进。

我们从三个层面进行讨论。

  • 单体应用层面

对于单机服务来说,单应用内部需要结合缓存、数据库连接池、代码优化等方式来提高单体应用的性能,同时服务器硬件性能能提高的就提高。

  • 缓存使用Redis,保证缓存数据可以落地,并且支持缓存集群
  • 数据库连接池使用HikariCP,不再使用Druid
  • 统一编码规范,如字符串拼接不能使用String直接进行,多用Threadlocal,禁用For循环查询数据库
  • JVM的优化
  • SQL的优化,查看执行过程耗时,特别是多表的级联查询问题

  • 架构层面

宏观上保证系统高性能和高可用,从成熟的解决方案中进行筛选,适用系统场景。

  • 单个服务都是无状态服务,保证服务可以水平扩展,同时满足了高性能和高可用
  • 集中管理session数据,Redis集群存储
  • 搭建负载均衡服务,分配请求到各个无状态服务,算法使用负载最低优选原则,通过zookeeper来获取服务的负载状态
  • 单个数据库连接有限,数据库采用一主两备方式提供服务,主数据库提供写操作,2个备份服务器提供读操作
  • 主备同步机制使用Mysql主从同步机制即可,读取不是强时效性,所以可以存在延迟
  • 主数据库暂时不进行分库,根据目前资源,需要从业务层面在降低大量写库的压力
  • 不做微服务架构,由于系统目前业务比较简单,服务治理和服务边界划分等会增加大量的工作量

  • 业务层面

从高性能和高可用为出发点,有些性能问题可以通过业务逻辑进行规避。

先分析一下写的场景,上篇文章中提到的写主要是发生在你每次跑步完成之后上传一条跑步记录,同时会生成一条动态。那么跑步记录上传这个逻辑和发动态这两个逻辑,是不是要在一个事务中完成?

跑步记录上传这个动作是不是要实时的?当你的网络环境不好的时候,跑步记录不一定说跑完了就马上就上传,其实可以在APP的后台保存记录后,选择适当网络通讯好的时候再上传。这样就避免了高峰期时大批量的跑步记录上传给系统带来的压力。

另外一个场景是动态的发布。想想看动态发布是谁在读,那肯定是他的关注的好友在读取这个动态,那么这个信息其实并不是需要即时性的,它可以多刷几次也能读到。这里就可以完全用异步方式去

生成动态,扩展一下,异步方式也可以解决跑步记录生成消息通知,总里程计算等其他业务逻辑。因为写消息队列肯定是比写数据库快多了。

以上,我们从架构宏观到单体应用层面,再到业务场景设计了整个架构的规范细节,当然不能面面俱到,但是大的原则是不会变的。

results matching ""

    No results matching ""