软件重构经验总结

结合小旺项目的重构经历来分析

小旺项目:5月份重构方案

转店/找店 拆表

参考:转店需求:transfer_requirement,字段requirement_id。转化为Service表的id。

地理位置相关业务重构

读 >> 写

涉及到以下业务字段的,需要重构。

  • 经纬度
  • 区域
  • 详细地址

Table:geographical_location

Fileds:

主键业务模块编号业务模块类型纬度经度区域编号详细地址
idsource_idtypelatitudelongitudeaeraIdaddress

source_id:关联的业务模块的主键

type:标识到业务模块的类型,枚举。

type字段主要是考虑这张表数据会膨胀的很快,以后可以以这个字段为依据做:mysql表分区、redis分库

问题

冗余:不是所有的业务都有这些字段,特别是经纬度

数据的记录与状态分离

(业务与图片的关联性,也可以参照)

读 ~= 写

数据状态

Table:status

Fileds:

主键业务模块编号业务模块分类状态状态值(tinyint)
idsource_idcategoryvalue

source_id:关联的业务模块的主键

category:区分单条数据记录内的多个状态属性值。一条数据记录可能同时存在很多状态属性,例如:订单,订单状态、支付状态。

数据状态依赖

Table:status_dependence

Fileds:

主键状态编号状态依赖编号状态值(tinyint)
ids_iddependence_idvalue

s_id与dependence_id都来源于status表的id字段

问题边界

状态依赖的边界

  • 数据状态的依赖,需要区分于:数据记录的存在性或不存在性。对数据记录的计算,需要在应用层解决。

问题

如何解决集中化的读写?

数据记录删除的处理

数据在主表进行物理删除或逻辑删除(isDeleted=1)时,如何处理关联的状态?

状态依赖树形结构过深

这会带来递归更新、删除的问题,需要在应用层避免

Solr异步写入 [低优先级]

提高吞吐量:去除JOOQ Listener模式,减少在Solr进行非关键性操作时,对主流程的阻塞。

可控性:独立出数据同步组件,负责在mysql数据有变化后,按规则将数据同步到Solr、Redis等

支付与合同独立出来

与Notify系统的通讯方式

ActiveMQ

引入MQ。
将上层应用与Notify交互时依赖于Socket,转变为MQ代理。

优势

消息传递可靠
消息的优先级
消息重试机制
Notify的伸缩性

Notify节点的上下线,MQ是感知到的。

Notify的吞吐量

P端的写入是长连接机制,省去大多数Socket链接创建、断开的开销。

Notify与APP通讯时,依靠JPUSH提供的HTTP接口,该接口存在调用频率限制

MQ的可控性

支持自我监控

MQ的可靠性
MQ的伸缩性
MQ的HA方案

小旺项目重构方案

串行化的幂等性操作

钱包业务:WalletModelImpl.java getWalletSummary(int uid)

实现“callable”接口,提高性能。

可以合并的请求

典型 1:for循环访问redis获取多个图片信息

改为:批量获取,访问一次redis

典型 2: 转店插件保存图片信息到mysql,循环访问mysql,插入数据

改为:batchInsert接口

不必要的字段查询

典型:ScopedContext.java getUserRecord()

基础接口,查询user表中,单条记录的所有字段

但是后续使用中,绝大多数只使用了其中的1个字段:id

读 >> 写

钱包业务:WalletModelImpl.java getWalletSummary(int uid)

请将读操作的结果保存下来,或者在写入时,后台线程计算出来并存储

多表join

简单业务需要多表join

1.适度冗余,修改业务逻辑,重建数据库模型
2.利用好缓存:数据库级别的查询缓存、redis缓存行记录

接口业务过于复杂

去除jooq listener同步调用

异步方式重构
优点:
1.主流程可以尽快结束,提高TPS,降低RT
2.出错可以有重试机制

缺点:
1.业务需要容忍最终一致性
2.新系统的加入,加大了研发成本、运维成本、监控成本

1.调用notif

ActiveMQ、Redis

2.调用solr

另做系统,实时解析mysql binlog。参考阿里方案:otter

系统监控

1.日志流分析
2.系统业务指标
3.报警系统

外键的大量使用

对没有强一致性要求的业务,去除外键。

HA、Scalable out

系统容错性

先了解

了解中发现问题症结

了解中思考解决方案

选取合适的解决方案

保留可扩展性

保留可维护性

再动手

重构方案的评审

理清方案的优势与不足

资源预先到位

包括重构的时间争取,参与人员配比,对其他软硬件资源、中间件的预研。

重构前后的效果量化

充分的测试

基础方面的重构,需要充分的测试

方案上线

Talk is cheap,show me the code.