挑战空中加油——1号店B2C电商系统演进之路
一、 面临的挑战\u0026#xD;发展速度快:每年近十倍的业务增长。既要及时响应业务发展的新需求,又要对系统平滑地进行技术升级重构,其难度堪比飞机空中加油。\u0026#xD;系统越来越复杂:\u0026#xD;多渠道: 1号店、掌上商城、第三方商城、多个分站\u0026#xD;产品多样: 既有各类百货,也有各种虚拟票劵,还有机票充值等\u0026#xD;...
·
一、 面临的挑战
\u0026#xD;- 发展速度快:每年近十倍的业务增长。既要及时响应业务发展的新需求,又要对系统平滑地进行技术升级重构,其难度堪比飞机空中加油。\u0026#xD;
- 系统越来越复杂:\u0026#xD;
- 多渠道: 1号店、掌上商城、第三方商城、多个分站\u0026#xD;
- 产品多样: 既有各类百货,也有各种虚拟票劵,还有机票充值等\u0026#xD;
- 多种经营模式: 有自营也有代售,有自配送也有第三方配送\u0026#xD;
- 多部门协同:采购、市场、销售、仓储、配送、客服等多部门需高效协同。\u0026#xD;
- 更智能化:随着业务和系统的复杂,各部门完全人工的运营决策变得十分低效,需要系统更加智能化。\u0026#xD;
- 流量越来越大:流量每年增长10倍。\u0026#xD;
二、演进的策略
\u0026#xD;- 新旧兼容,平滑升级:我们在实施任何技术升级时,首要强调的就是新系统要尽量兼容旧系统,以支持平滑升级。完全新的架构看似很吸引人,比较容易开发,但是不兼容原来的系统可能使得新系统风险非常大。所以1号店采用兼容的方式,滚动开发,把架构从原来的合成一团的小系统方式逐步改变为子系统独立,多数据库的模式。这好比一边高速飞行,一边加油。\u0026#xD;
- 系统拆分:解决系统复杂性的唯一方法是分解。同时拆分后系统也使各自进行新的技术改造变得相对平滑。我们从终端渠道、业务逻辑、使用部门等多个维度进行了系统拆分。 例如:\u0026#xD;
三、 经典案例:数据访问层YhdDAL 1.0设计与实施
\u0026#xD;1) 实施前旧系统状态与结构:
\u0026#xD;- 整体已拆分有多个子系统和多个数据库。\u0026#xD;
- 每个应用系统与多个数据库直连,使用iBatis进行O/R Mapping。\u0026#xD;
- 各应用系统代码中,使用MemCached服务器进行数据缓存。\u0026#xD;
2) 旧系统面临的问题:
\u0026#xD;- 数据库连接数大,数据库服务器负担重。\u0026#xD;
- Cache代码繁琐: 本来一行代码的事需要写四五行。下面是典型的示例伪代码:\u0026#xD;
\u0026#xD;result = getFromMemCached(key);\u0026#xD;if (result != null) return result;\u0026#xD;result = getFromDatabase(...);\u0026#xD;writeMemCached(key, timeout);\u0026#xD;return result;\u0026#xD;\u0026#xD; Cache 管理困难: 失效时间代码分散,不便管理。不同系统还容易key冲突。\u0026#xD; 数据分库和读写分离代码繁琐,某库故障时无法自动切换到可用库上。\u0026#xD; 系统Service化改造困难: 原Web层与Dao层代码耦合度高,不易实现Service化。拆分粒度太细连接数上升和故障概率增加,粒度太粗又效果不佳。\u0026#xD; 无法充分发挥Cache潜能:某个Cache项失效时,因前端的并发性会导致多次数据库请求。到期Cache无法延期使用,数据库故障时应用系统就立即故障。\u0026#xD;\u0026#xD;
3) 备选方案的优缺点:
\u0026#xD;- 基于iBatis本地扩展: 优点是工作量小。缺点是连接数和Service化等问题无法很好解决。\u0026#xD;
- 基于jdbc驱动的DAL:优点是客户端代码兼容性好,原代码改动工作量小。缺点是实现一个完整的jdbc驱动本身代价很高。\u0026#xD;
- DAL服务化,接口自定义: 优点是代码可控性高,各项需求特性易实现。缺点是有一定的迁移成本。\u0026#xD;
4) YhdDAL 1.0设计方案:
\u0026#xD;- 引入DAL服务器。应用系统仅访问DAL服务器,DAL才连接数据库。\u0026#xD;
- 客户端与DAL采用成熟的远程调用协议,接口简化为一个:\u0026#xD;
- Object execute(functionName, parameters...)\u0026#xD;
- 参数和返回值一律采用Map或基本类型,必要时可在客户端转换为Java Bean\u0026#xD;
- 支持iBatis格式的sql脚本定义和字段映射,以降低iBatis代码迁移成本。\u0026#xD;
- DAL层支持JavaScript脚本语言编写的类似存储过程的计算代码,简化业务层数据处理代码实现。\u0026#xD;
- 因DAL服务器数量明显小于应用服务器数量,可有效减少数据库连接总数。\u0026#xD;
- DAL层封装Cache处理机制,一方面简化应用层代码。另一方面可采取缓存主动更新,失效延期等机制,充分发挥Cache潜能。\u0026#xD;
- DAL层封装分库和读写分离处理机制,简化应用层代码。\u0026#xD;
- 参考数据库存储过程的设计思想,客户端仅传入过程名称和参数,DAL层计算完成后返回结果。有利于实现Service化。\u0026#xD;
- 大量简化应用层代码,很多简单的Sevice/Dao类可以完全省略。\u0026#xD;
- 1.0的缓存和负载均衡采用相对成熟简单方案,以降低风险。结构图如下:\u0026#xD;
5) 实施与升级过渡步骤:
\u0026#xD;- 实现DAL核心功能。进行压力测试,评估系统性能。\u0026#xD;
- 先对一个风险相对较小的应用系统进行改造,评估系统稳定性和改造成本。\u0026#xD;
- 采用iBatis兼容模式,直接转换迁移旧代码。以快速将原有系统升级至新平台。\u0026#xD;
- 采用新平台的设计理念,如读写分离、Service化,进行旧代码改造。\u0026#xD;
- 扩展DAL附加功能,如日志记录、权限控制、缓存优化、连接分组等。\u0026#xD;
通过一系列的方法与手段,1号店基本实现了从小系统向大系统演变,使得1号店的系统能够支撑大量高并发的访问,同时满足了业务的需要。
\u0026#xD;关于作者
\u0026#xD;韩军,1967年出生。1989年毕业于上海交通大学计算机系, Monash MBA
\u0026#xD;- 1号店的第一个员工,CTO, 设计并开发了1号店所有的系统\u0026#xD;
- 2004年,设计了 美国著名的比较购物系统 smarter.com\u0026#xD;
- 1999年加入51job,设计并开发了中国最为成功的工作网站与系统\u0026#xD;
感谢晁晓娟对本文的审校。
\u0026#xD;给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家加入到InfoQ中文站用户讨论组中与我们的编辑和其他读者朋友交流。
更多推荐
已为社区贡献54条内容
所有评论(0)