Challenges of multitenancy
Cost savings vs. scale
The cost savings can be eclipsed by the difficulty of scaling the single instance as demand grows - increasing the performance of the instance on a single server can only be done by buying faster hardware, such as fast CPUs, more memory, and faster disk systems, and typically these costs grow faster than if the load was split between multiple servers with roughly the same aggregate capacity.
Security Challenges
Development of multitenant systems[7] is more complex, and security testing is more stringent owing to the fact that multiple customers' data is being co-mingled.
Data aggregation performance
It is common to separate the operational database from the mining database (usually because of different workload characteristics).
Meta data overhead
Because of the additional customization complexity and the need to maintain per-tenant metadata, multitenant applications require a larger development effort.
IzyCloud solution and recommendations
Typical work flow is:
Session Token -> Identity IDs (IID) -> Resources
The most typical IID is a userID. Also note that the session to identity key (accountId) should be 1 to many. i.e. 1 session should be able to control and access more than 1 identity key.
An interesting question arises is how to organize the DB schema for the system considering:
- Configurable Access Control Business Rules: some example are
* data is siloed across some IIDs (i.e. two different IIDs cannot see each others data)
* some IIDs have super user accesss
Options
separate dbs so that each account gets its own DB
Pros:
- No accountID column needed and therefore the schema is not contaminated with the ownership info
- Queries are simpler to write since no joining with access control table or ANDing with access control column
- Extra security since the chances of accidental cross account leakage is low
- Reduces the occurance of read/write collisions since the data gets partitioned. This might lead to a performance advantage for database engines that implement MVCC (Multiversion concurrency control) to achieve transactional memory and point in time consistent views.
Cons:
- Sharing data across accounts and shared resourcing (i.e. web presense app where each account can configure the server independently) is much harder and not scalable since seperate sockets and database connections would be needed for each account and joining the the data would be extremly difficult across different dbs.
- Schema updates (such as when it is needed by apps) is more painful as it would need to be applied to all instances
- Still hard to do granular access control scenarios because this approach implicitly relies on on a single data element (database name in this case) for defining access control
single db, which each table having an IID column
single db with an extra access control table
In this example we are going to have an access control table with the following schema:
CREATE TABLE accesscontrol
(
accesscontrolrowid
int(20) unsigned NOT NULL AUTO_INCREMENT,
utcdt
datetime DEFAULT NULL,
ownerid
int(20) unsigned NOT NULL,
ownertype
int(20) unsigned NOT NULL,
itemid
int(20) unsigned NOT NULL,
itemtype
int(20) unsigned NOT NULL,
UNIQUE KEY
id_2
(
accesscontrolrowid
),
UNIQUE KEY uniqequadruplet
(ownerid
,ownertype
,itemid
,itemtype
),
KEY
id
(
accesscontrolrowid
) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
The ownership relationship between each object can be determined by inserting a record into this table. Also access control can be done by doing:
modtask.getSessionJoinClause = function(tableName, session) {
return ' ' + 'INNER JOIN izyware.accesscontrol ON accesscontrol.itemid = ' + tableName + '.id AND accesscontrol.itemtype = ' + modtask.tableNameToItemType[tableName] + ' AND accesscontrol.ownerid = ' + session.ownerId + ' AND accesscontrol.ownerType = ' + session.ownerType;
}
Scalability Analysis
We will analyze the following performance considerations:
- JOINing
- Inserting
- Deleting
To populate the table with 10 million rows, we will do
INSERT INTO status(id, responseCode, lastUpdate) SELECT @row := @row + 1 as row, 503, NOW() FROM
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t5,
(SELECT @row:=0) t6;
Upon closer examination, it appears that it is really up to the specific app to decide which schema is a better suit. To illustrate this point a few different scenarios are discussed.
Recommendations
- Use 1 access control table per database. do not pollute the table schemas with tenant metadata
- Apps / Users / Host paradigm
- Apps have differnet privilages that defines which DB/host they have access to. Once an app runs on izyware they can access everything in the izyware DB.
Example
I. A resource shared across different IIDs
An example of this would be the Web Presence App
- Users sign-up and install the app
- The app will get the Session IID from the parent context (in this case it is the IzyWare dashboard)
- The app will 'trust' that the Session IID is not tampered with. This is enforced in the backend secure context because the IID
- The app will use the IID to enforce the following business logic
The business logic
- Each IID will only be able to do CRUD on the domains they added
- Admin IIDs will be able to CRUS on all others
In this scenario, having a domain table with an IID columm is not ideal:
- access control change requests will require updates to domain table
- generally speaking bringing a new table in would be difficult
- would not allow access control for multiple iids
Instead and access control table should be used that
- defines all the access control rules for objects inside the entire db
- apps will honor and use the guideline