- 发布时间
服装零售决策管理系统技术方案
- 作者

- 作者名字
- Kavin Wang
概述与分析
本系统在进行设计时,必须考虑到品牌公司的数据管理以及数据安全问题,在当前系统资源有限的情况下,还必须考虑服务的效率,以在有限资源下达到最好的服务。
考虑到我们面对的是无数的对数据安全要求比较苛刻的品牌公司,因此可以得出,我们的系统是非常明显的多租户SAAS系统。
基于以往的经验,结合对零售行业的深度学习分析与了解,实施一个服装零售系统的决策系统将是一个复杂沉重的工作,是一个挑战性异常高昂的决定。我们必须慎重选择客户当前最关心最头疼的部分,还要考虑客户对未来数据管理的需要。
因此我们的系统既要保障客户数据的安全,还要考虑系统的可靠扩展性,连续服务的技术一致性等也都变得至关重要。
技术方案与选型
数据库
关于服饰行业的模型复杂性,我们考虑在系统业务处理模型上,尽量使用mongodb数据库来实现,通用数据考虑使用postgre来完成。希望既能保障业务建模的便利完整性,也能在系统管理上尽量简单。
软件技术
涉及到用户信息安全管理方面,尽量使用商业公司提供的安全服务。
关于业务的实现,考虑到初创企业成本限制,需尽量使用已经验证成熟灵活的开源系统和框架,必要之处,再考虑商业公司提供的技术和设施服务。
租户系统
由于我们系统的多租户特性,经过思考和分析,当前可以选择的技术方案有以下几种:
大数据模式
我们把所有的数据保存在一个数据库中,数据之间不做严格的隔离,但会对不同租户赋予不同的安全的uid,并在所有租户相关的数据上赋予这个uid进行区分。
这种模式对系统要求相对比较大,系统租户量不多时,系统实现和执行效果比较满意,担当租户量增大时,考虑到数据量的极度增加,对于数据库系统的挑战将会非常大,并且可能需要投入非常大的硬件设施投入。
轻量租户模式
我们将为每一个租户建立一个独立的数据库,系统使用统一的管理系统来管理租户数据,所有租户共享同一个数据库连接池,系统根据租户的不同来调整连接池中的租用的连接,使之根据不同租户去访问租户的私有数据库。
考虑到共享连接池,因此这种系统租户量可能不会很大,并且对租户的访问要求也比较苛刻,比如要求租户访问时的压力要小于每秒一个请求,任务处理速度也要求应在10ms内完成。原因是某一个租户的慢速访问,会直接影响其它的租户的访问效率。
const express = require('express');
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/main');
mongoose.set('debug', true);
mongoose.model('User', mongoose.Schema({ name: String }));
const app = express();
app.get('/users/:tenantId', function(req, res) {
const db = mongoose.connection.useDb(`tenant_${req.params.tenantId}`, {
// `useCache` tells Mongoose to cache connections by database name, so
// `mongoose.connection.useDb('foo', { useCache: true })` returns the
// same reference each time.
useCache: true
});
// Need to register models every time a new connection is created
if (!db.models['User']) {
db.model('User', mongoose.Schema({ name: String }));
}
console.log('Find users from', db.name);
db.model('User').find().
then(users => res.json({ users })).
catch(err => res.status(500).json({ message: err.message }));
});
app.listen(3000);
重度租户模式
这种模式,应该比上一个模式更加灵活,服务质量应该更高,比如可以服务10K个以上的租户,可以要求请求的速度大于每秒一个请求。
因此我们需要要求每一个不同的租户,都需要有自己独立的连接池。单个租户的对系统性能要求比较严格的业务请求,能够较小的影响到其它的租户的使用。
很明显,这种系统实现起来更加困难,也更加复杂。特别是mongodb对最大连接能力的限制,即使使用mongd atlas,也有会对每个连接池中活跃连接数进行限制
const express = require('express');
const mongoose = require('mongoose');
const tenantIdToConnection = {};
const app = express();
app.get('/users/:tenantId', function(req, res) {
let initialConnection = Promise.resolve();
const { tenantId } = req.params;
if (!tenantIdToConnection[tenantId]) {
tenantIdToConnection[tenantId] = mongoose.createConnection(`mongodb://127.0.0.1:27017/tenant_${tenantId}`);
tenantIdToConnection[tenantId].model('User', mongoose.Schema({ name: String }));
initialConnection = tenantIdToConnection[tenantId].asPromise();
}
const db = tenantIdToConnection[tenantId];
initialConnection.
then(() => db.model('User').find()).
then(users => res.json({ users })).
catch(err => res.status(500).json({ message: err.message }));
});
app.listen(3000);