何海棠,朱曉輝,陳蘇蓉
(南通大學(xué),江蘇 南通 226007)
SaaS(Software-as-a-Service)類軟件應(yīng)用具有基于網(wǎng)絡(luò)完成交付和使用、允許用戶按需付費并在一定環(huán)境下對操作界面、數(shù)據(jù)結(jié)構(gòu)等個性化定制的特點。SaaS應(yīng)用所對應(yīng)的數(shù)據(jù)庫為多租戶數(shù)據(jù)庫,是多租戶數(shù)據(jù)存儲和個性化定義的保障。在設(shè)計時,需結(jié)合SaaS模式的特點,合理地平衡數(shù)據(jù)共享和數(shù)據(jù)隔離[1-2],既使不同租戶的數(shù)據(jù)達到某種形式上的統(tǒng)一,促進數(shù)據(jù)的高效訪問,又保證各租戶數(shù)據(jù)的個性化和存取的獨立性。
本文基于.NET環(huán)境,以SQL Server 2008為數(shù)據(jù)庫管理軟件,以面向中小型企業(yè)信息化管理的SaaS軟件為例,在考慮數(shù)據(jù)共享和數(shù)據(jù)隔離的基礎(chǔ)上,圍繞多租戶數(shù)據(jù)的存儲、子用戶與租戶的對應(yīng)、子用戶權(quán)限的管理、租戶數(shù)據(jù)的擴展等幾個方面對SaaS模式下的多租戶數(shù)據(jù)庫進行研究。
SaaS模式下的多租戶數(shù)據(jù)庫按數(shù)據(jù)的存儲形式可分為獨立數(shù)據(jù)庫和共享數(shù)據(jù)庫。獨立數(shù)據(jù)庫和租戶間為1∶1關(guān)系,每個租戶在自己的獨立數(shù)據(jù)庫中進行數(shù)據(jù)存取。共享數(shù)據(jù)庫和租戶間為1∶n關(guān)系,所有的租戶共用一個數(shù)據(jù)庫,不同租戶在同一個數(shù)據(jù)庫中進行數(shù)據(jù)存取;根據(jù)共享數(shù)據(jù)庫中的租戶是否使用相同的表集,還可分為共享SCHEMA和獨立SCHEMA 兩種架構(gòu)[2-4]。
無論采用哪種數(shù)據(jù)庫存儲方案,均需解決數(shù)據(jù)庫和租戶間的對應(yīng)問題。該問題的解決可通過構(gòu)建存儲租戶基本信息的注冊租戶表解決,在該表中設(shè)置companyID字段和connectionString字段以體現(xiàn)租戶和數(shù)據(jù)庫間的對應(yīng)。companyID用于標識租戶,為保證其惟一性及可管理性,可設(shè)置其為int型且具有IDENTITY屬性,每增加一個租戶,自動按規(guī)則產(chǎn)生新值填充。connectionString字段以字符串形式存儲與companyID對應(yīng)的數(shù)據(jù)庫信息,形如“server=ServerNo1;uid=sa;pwd=123456;database=dbID;”,提供數(shù)據(jù)庫服務(wù)器名、數(shù)據(jù)庫名、登陸方式、登陸名、登陸密碼等;該字符串中server和database的不同取值可體現(xiàn)是共享數(shù)據(jù)庫還是獨立數(shù)據(jù)庫。
SaaS模式下的數(shù)據(jù)庫所有者為不同租戶(本文只考慮租戶為中小型企業(yè)),同一租戶往往又存在多個子用戶,在解決完數(shù)據(jù)庫和租戶間的對應(yīng)問題后,需考慮如何實現(xiàn)子用戶和租戶間的對應(yīng),其本質(zhì)為解決子用戶和租戶數(shù)據(jù)庫間的對應(yīng)。
該問題的解決基礎(chǔ)是構(gòu)建注冊用戶表,存儲employeeID(子用戶 ID)、loginName(子用戶名)、loginPwd(密碼)等信息。子用戶在登陸時需提供companyID、employeeID、loginPwd,系統(tǒng)據(jù)此查看注冊租戶表和注冊用戶表以完成子用戶和租戶數(shù)據(jù)庫間的對應(yīng)。
注冊用戶表可存儲在租戶數(shù)據(jù)庫中。獨立數(shù)據(jù)庫方案下,一個租戶對應(yīng)一張注冊用戶表;共享數(shù)據(jù)庫共享SCHEMA方案下,多個租戶對應(yīng)一張注冊用戶表,且該表中需添加租戶ID字段用以標識該用戶的歸屬;共享數(shù)據(jù)庫獨立 SCHEMA方案下,每個SCHEMA中存儲一張注冊用戶表,無需額外添加租戶ID字段。
不同租戶及其子用戶對多租戶數(shù)據(jù)庫通常存在不同的訪問需求。為保證租戶數(shù)據(jù)的安全,需劃分對數(shù)據(jù)庫的不同操作(細化到對表、字段的存取),并將其對應(yīng)到不同的用戶,即為不同用戶設(shè)置不同的數(shù)據(jù)庫訪問權(quán)限。另外,SaaS模式下,軟件應(yīng)用的一個重要特點是可配置性,租戶可按需選擇功能模塊,在設(shè)計時,與數(shù)據(jù)庫存取相關(guān)的功能模塊可與數(shù)據(jù)庫訪問權(quán)限結(jié)合起來,采用角色管理的方法實現(xiàn)其可配置性??尚械姆椒ú襟E如下:
(1)構(gòu)建功能模塊描述表,設(shè)置functionID(int)字段,用于標識每個功能模塊。
(2)構(gòu)建角色描述表,設(shè)置roleID(int)和functionIDs(char)字段,roleID用于標識每個角色(角色的劃分可結(jié)合企業(yè)的不同業(yè)務(wù)崗位,如會計、銷售員、倉庫管理員等),functionIDs用于存儲每個roleID對應(yīng)的functionID集合。
實際基于.NET環(huán)境進行軟件實現(xiàn)時,可考慮將模塊功能的展現(xiàn)對應(yīng)到網(wǎng)頁、模塊功能的調(diào)用對應(yīng)到多級菜單的菜單項,將構(gòu)建功能模塊描述表改為構(gòu)建菜單信息描述表,在該表中設(shè)置menuID(int)和menuURL(nvarchar)字段,menuID用于標識每個菜單項,menuURL用于存儲與模塊功能展現(xiàn)對應(yīng)的網(wǎng)頁地址;將角色描述表中的functionIDs字段改為menuIDs字段,存儲每個roleID對應(yīng)的menuID集合。
(3)在注冊用戶表中添加roleID字段,將用戶與角色聯(lián)系。
傳統(tǒng)的多租戶數(shù)據(jù)庫在設(shè)計時基于所有租戶數(shù)據(jù)需求的并集進行,所有租戶的數(shù)據(jù)結(jié)構(gòu)完全相同且固定,容易造成數(shù)據(jù)冗余,不符合SaaS模式下允許租戶個性化數(shù)據(jù)的特點。目前,SaaS模式下的多租戶數(shù)據(jù)庫在設(shè)計時較多地采用固定擴展或定制擴展[5-7]的方式。
固定擴展方式是以為表預(yù)留字段的方式提供擴展,其可擴展性受限于預(yù)留字段的數(shù)目和預(yù)留字段的類型,且無法保證預(yù)留字段的最佳利用率。因此,筆者在研究時基于共享數(shù)據(jù)庫共享SCHEMA采用定制擴展的方式為租戶提供擴展,其設(shè)計思路基于單個標準數(shù)據(jù)庫表(Standard)與擴展數(shù)據(jù)表(Extension)之間的通用關(guān)系(如圖1所示),具體實現(xiàn)時考慮將共享數(shù)據(jù)庫中所有擴展數(shù)據(jù)統(tǒng)一存儲管理,涉及到 Tb_Table、Tb_ExBase、Tb_Extension 三張表(如圖2),說明如下:
(1)Tb_Table存儲存在擴展需求的companyID、tableID(表)及 tableName(表名)。
(2)Tb_ExBase存儲所有擴展字段的基本屬性,ID為擴展字段的唯一標識,fieldID為該字段在特定租戶的特定表中的唯一標識。companyID、tableID、fieldID、fieldEN(字段英文名,fieldCH用于顯示,為字段中文名)的組合不允許重復(fù)。
Tb_Table和Tb_ExBase基于companyID+tableID字段存在1∶n聯(lián)系。
(3)Tb_Extension存儲擴展字段的值,recordID為tableID指定表中的具有擴展字段值的實體編號,recordID的存在要求共享數(shù)據(jù)庫中所有存在潛在擴展需求的表均具有recordID字段,若實體有擴展數(shù)據(jù),則用自增且保持唯一的值對其填充,否則為NULL。tableID、recordID、fieldID的組合不允許重復(fù)。
某租戶(已具有companyID)個性化數(shù)據(jù)的操作原理如下:
(1)添加擴展字段:根據(jù)當前需擴展對象(表)名在Tb_Table中檢索tablename,若存在,則獲取tableID,否則自動生成tableID,并向Tb_table中填充companyID和tablename;根據(jù)tableID、按字段擴展順序產(chǎn)生的fieldID,將擴展字段的相關(guān)屬性填充到Tb_ExBase表。
(2)刪除擴展字段:根據(jù)租戶界面操作確定companyID、tableID、fieldID,在 tableID 指定表中獲取companyID對應(yīng)的實體的recordID集,根據(jù)tableID、recordID、fieldID的組合將Tb_Extension中對應(yīng)的記錄全部刪除,并在Tb_ExBase中刪除companyID、tableID、fieldID組合確定的記錄。
(3)添加擴展字段值:根據(jù)用戶界面操作確定tableID、fieldID、value,在 tableID 中為當前實體產(chǎn)生recordID,在Tb_Extension添加記錄。
(4)修改擴展字段值:根據(jù)用戶界面操作確定tableID、fieldID、value,在 tableID 中檢索當前實體的recordID,在Tb_Extension中修改記錄。
(5)顯示擴展字段值:獲取當前實體的tableID、recordID,若recordID值不為NULL,則根據(jù)該值及tableID在Tb_Extension獲取fieldID和value值,利用companyID、tableID、fieldID的組合在Tb_ExBase中獲取fieldCH、dataType,根據(jù)dataType選用合適的界面元素在界面上將value進行顯示。
(6)刪除擴展字段值:部分刪除則參照(4)的操作;若全部刪除,則在刪除Tb_Extension中tableID和recordID對應(yīng)的記錄后,還需將tableID指定表中對關(guān)的recordID的值修改為NULL。
SaaS模式下,軟件服務(wù)商基于網(wǎng)絡(luò)采用一個應(yīng)用實例,或基于同一代碼庫的多個同構(gòu)應(yīng)用實例,為多個中小型企業(yè)同時提供諸如CRM、ERP等企業(yè)信息化服務(wù),其服務(wù)的支持基礎(chǔ)為多租戶數(shù)據(jù)庫。本文對SaaS模式下的多租戶數(shù)據(jù)庫設(shè)計過程中不可避免的數(shù)據(jù)存儲、權(quán)限管理、數(shù)據(jù)擴展等問題進行了討論,并給出了具體的解決思路和實現(xiàn)方法。在今后的研究中,還需基于多租戶特點對加快擴展數(shù)據(jù)的查詢、共享數(shù)據(jù)庫形式下數(shù)據(jù)的備份和恢復(fù)等問題作進一步的研究,以更好地為SaaS模式下的軟件提供支持。
[1]Frederick Chong and Gianpaolo Carraro.Architecture Strategies for Catching the Long Tail[J/OL].http://msdn.microsoft.com/en - us/library/aa479069.2006.
[2]Frederick Chong,Gianpaolo Carraro,and Roger Wolter.Multi- Tenant Data Architecture[J/OL].http://msdn.microsoft.com/en - us/library/aa479086.2006.
[3]Robert Vieira.SQLServer2008高級程序設(shè)計[M].楊華,騰靈靈(譯).北京:清華大學(xué)出版社,2010.
[4]查俊,溫浩宇,楊朝君.SaaS數(shù)據(jù)層方案比較研究[J].情報雜志,2010,(29).
[5]昌中作,徐悅,戴鋼.基于SaaS模式公共服務(wù)平臺多用戶
數(shù)據(jù)結(jié)構(gòu)的研究[J].計算機系統(tǒng)應(yīng)用,2008,(2):7 -11.[6]孔蘭菊,李慶忠,史玉良,等.面向SaaS應(yīng)用基于鍵值對
模式的多租戶索引研究[J].計算機學(xué)報,2010,33(12):2239-2246.
[7]凌永紅,周新.SaaS模式下數(shù)據(jù)擴展性的設(shè)計與實現(xiàn)[J].
計算機與數(shù)字工程,2009,37(12):76 -79,187.