摘 要: Redis+MySQL+MongoDB技術架構實現了本項目中大數據存儲和實時云計算的需求。使用MongoDB切片的水平動態添加,可在不中斷平臺業務系統的同時保障擴容后的查詢速度和云計算效能;依據切片鍵索引分片,位于各切片獨立進行計算,使大數據下的實時分析成為現實。對于高頻訪問的數據放在了Redis中,有效地降低磁盤I/O,使業務系統響應更為敏捷,滿足了高并發下應用服務的高呑吐要求。
關鍵詞: 移動位置服務SaaS;Redis;MongoDB
基于移動位置服務的應用是根據用戶所在位置提供的一種增值業務,主要通過移動定位技術獲得其當前所在位置,在電子地圖和業務平臺的支持下,提供位置相關的信息服務。通過互聯網提供軟件服務的SaaS(Software as a Service)模式具有企業初期零投入,不需服務器、系統研發等軟硬件投入等獨特的優點,為廣大中小企業解決前期資金投入不足的情況下開展信息化建設,引入管理信息系統提供了一個可行的模式。
1 項目簡介
基于此需求背景提出開發一種面向中小企業移動位置服務的SaaS平臺,幫助所有具有外勤、外巡、外服的戶外工作業務的中小企業降低成本,將定位技術與智能手機客戶端相結合,利用運營商的GSM/WCDMA等無線網絡,為企業提供在外工作人員的具體位置和行走軌跡,同時實現考勤簽到、快速審批、位置標注、語音群聊、數據上報、區域預警,更好地進行地理化分析、業績審視,快速響應客戶需求和有效管理員工,深度鞏固企業在市場中主體地位和增強企業核心競爭力。
2 業務數據分析
移動位置服務的SaaS平臺作為企業移動互聯網應用,應用過程將積累大量數據。其中包括:靜態信息(手機號碼、注冊信息、手機型號等);位置信息(行動軌跡、速度、停留時間、地點屬性);與APP關聯的數據(訪問行為、社交行為、交易行為等);交互特點(報告頻率、數據類型與格式等)。其數據容量和特點較傳統業務有較大地變化。
2.1 數據來源分析
數據來源包括終端采集的數據和SaaS平臺數據,終端數據涵蓋了Android、IOS智能終端和PC端,智能終端是企業應用的數據采集器,是企業人在業務活動中“人體器官”的延伸。同時還有部分數據源于PC端;另外系統運行過程中,會產生大量日志數據。
(1)終端采集的數據
①軌跡數據:以包括公司id、用戶id、經緯度、地址、定位時間、定位類型等信息的一個數據樣本為例,默認30 s采集一次,假如企業員工默認工作時間8小時,每個員工每天條數為2 080條,假定用戶數為10 000,那么每天有2 080萬條;單條數據占用空間184 KB,10 000用戶一天占用空間約為3 GB。
②常規業務數據:常規業務數據種類有考勤、工作計劃、工作日志、申請、事件提醒、通知公告、銷售上報等;保守預計單條數據容量為512 KB,按每個用戶每天產生15條相關業務,其數據量為7 680 KB,10 000用戶一天產生數據量約為73 MB。
③即時聊天和工作微博數據:即時聊天和工作微博數據為非結構化數據,包含如下種類:語音、圖片、文本、位置分享等。保守預計單條圖片語音數據量為: 100 KB,按每個用戶每天產生30條,其數據量為3 000 KB,10 000用戶一天產生數據量約為28 GB。
(2)平臺數據
作為服務眾多企業的云平臺,還有如下種類數據需要產生和管理:企業、企業組織、企業用戶、用戶通信錄、用戶通信錄個性化備注、群組名片等;平臺方面的數據暫且不作考量,與普遍的企業應用基本類似。
2.2 數據特點分析
(1)移動化。與PC應用相比較,移動應用數據采集的時空變化了,智能終端不知疲倦,可以自動采集上報如位置等信息;同時移動化使得采集數據的便捷性得到了極大提高,用手機拍照立即便可上傳,相比過去的照相機采集沒有空間限制也沒有鏈接PC上傳的限制。
(2)非結構化。采集的圖片語音等媒體數據非結構化,例如采集門店的貨品陳列的圖片數據等,工作微博分享的數據文檔化,與傳統結構化、需要事務支持的數據有明顯差異。
(3)平臺級增量化。與以往企業級應用對應一家企業增量相比,平臺級數據增量化帶來的數據量巨大增加,通過上面的分析,10 000用戶每天會帶來大約30 GB的數據增量。30 GB數據有些均勻地提交到平臺,有些會以峰值的方式提交到平臺;考勤通常集中在上下班時段,而軌跡則均勻分布在所有上班時間。
針對以上數據分析,如何解決其大容量和非結構化數據特點面臨的存儲和處理的挑戰?通過技術選型和前期的測試數據對比,選用了Redis+MySQL+Mongodb架構的解決方案。
3 相關技術
3.1 Redis簡介
Redis(Remote Dictionary Server)是一個使用ANSI C語言開發的開源的Key-Value存儲系統,它和目前較流行的Memcached類似,都是基于內存(緩存)的數據存儲方式,不同的是Redis支持的數據類型更加豐富并且對每種數據結構提供了豐富的操作。同時,Redis不同于Memcached之處在于它會將更新的數據異步的持久化到硬盤中或者把進行過的修改操作寫入日志文件中。Redis雖然是Key/Value形式的數據庫,但是它吸收了部分關系型數據庫的優點,如在能保存Lists和Sets類型的數據的同時,還能完成排序等高級功能,同時在實現INCR(自增)、SETNX(若不存在Key則創建并設值)等功能時保證其操作的原子性。在此基礎上還實現了Master-Slave(主從)同步[2]。Redis主從復制特點:(1)支持一個Master可以擁有多個Slave,同時Slave還可以接收其他的Slave;(2)主從復制不會阻塞Master和Slave,在同步數據時,Master和Slave都可以接收Client請求[2]。
3.2 MongoDB及其自動分片簡介[3]
MongoDB是一個基于分布式文件存儲的數據庫[4]。由C++語言編寫。它支持的數據結構非常松散,是類似json的bson格式,因此可以存儲比較復雜的數據類型。MongoDB的特點是面向集合存儲,模式自由,支持動態查詢、完全索引、查詢、復制和故障轉移,自動處理碎片[5]。MongoDB的核心理念在于文檔模型,它是MongoDB數據的基本單元,等價于關系型數據庫的行。MongoDB中的集合等價于關系型數據庫中的表。一個單一的MongoDB可以承載多個獨立的數據庫,每個數據庫可以擁有自己的集合和管理權限。
MongoDB的分片架構是指把數據分割成不同部分,在不同的機器上的存儲過程,通過分割數據到不同的服務器上,使得無需使用更強大的機器來存儲更多的數據和處理更大的負載。MongoDB支持自動分片,集群可以自動分割數據和數據的再均衡。MongoDB提供以下的分片技術:(1)對負載的變換和數據的分布自動平衡;(2)動態添加額外服務器;(3)無單點故障;(4)自動故障轉移[6]。
4 技術實現
4.1 架構功能角色
Redis+MySQL+Mongodb架構對應功能角色如下。
Redis:基于內存高速緩存,保存集群中央會話,即時通信離線消息隊列,即時通信重發消息集合,用戶令牌生命周期管理,應用高頻訪問數據緩存,HTML5模板數據緩存,靜態應用資源緩存。
MySQL:進行事務數據存儲:相關企業帳號數據,企業常規業務數據,企業平臺交易數據。
Mongodb:進行非結構化文檔數據存儲:包括圖片、圖標、語音、工作微博文本以及結合位置數據的非結構化的文檔數據,需要動態擴展無固定模式的數據,應用日志數據,需要map-reduce計算的數據。
4.2 可靠性和可用性保障措施
為了保證生產系統數據可靠性和可用性,規避Redis+MySQL+Mongodb單點故障,分別作了主從備份,在此基礎上采用了KEEPALIVE,通過VRRP協議實現了故障的自動切換。Redis配置了主從,MySQL配置了主從,Mongodb配置了切片;詳細配置清單舉例如下。
Redis主從配置需要在從配置文件Redis.conf指定主IP和端口:slaveof 192.168.10.10 6379
MySQL主從配置:
主配置:server-id=1;log-bin=mysql-bin;binlog-do-db=wqt_web
從配置:server-id=2;log-bin=msyql-bin;master-host=192.168.10.3;master-user=slaveuser;master-password=gotop4001680756;master-port=3306;…
Mongodb切片配置:
mongod-shardsvr-port 10001-dbpath=/home/data/shard11/-logpath /home/data/shard11/mongodb.log--fork
mongod-shardsvr-port 10002-dbpath=/home/data/shard12/-logpath
…
mongo 127.0.0.1:20000/admin
配置分片必須要鏈接admin集合。鏈接成功后可以把分片加入集群:
db.runCommand({"addshard":"127.0.0.1:10001"})
…
db.runCommand({"addshard":"127.0.0.1:10004"})
這樣就成功地把4個shard加入了分片。制定分片的規則如下:
db.runCommand({"shardcollection":"kingfihser.tablename","key":{"primaryKey":1}})
激活分片的設置:db.runCommand({"enablesharding":"kingfisher"}),最后成功的配置了分片。
4.3 詳細代碼
4.3.1 Redis實現案例
在通信中,作為發布訂閱隊列使用,Web發布消息,進入Redis發布訂閱頻道,通信中心消費此頻道消息,所有的信息發布都在Redis中進行,從而提高了響應的速度。
public boolean sendMsg(String msg){
boolean rebool=true;
Jedis jedis=null;
try{
jedis=(Jedis)pool.getResource();
jedis.publish("kingfisher.*",msg);
}catch(Exception e){
e.printStackTrace();
rebool=false;
}finally{
pool.returnResource(jedis);
}
return rebool;
}
4.3.2 Mysql實現
進行事務數據存儲:包括相關企業帳號數據,企業常規業務數據,企業與平臺交易數據。此部分的存儲計算采用HIBERNATE+SPRING方式實現。
4.3.3 Mongodb實現案例
(1)媒體數據利用GFS網格文件子系統存儲。
class fileservice(BaseHandler):
def get(self):
id=self.get_argument("id","")
f=GridOut(self.mongo.fs,ObjectId(id))
try:
fn=f.filename.lower()
…
self.write(f.read())
def post(self):
…
def delete(self):
…
(2)工作微博內容和二維空間索引,以及軌跡數據的索引和查詢。
class listmark(BaseHandler):
′′′
搜索工作微博列表
′′′
def get(self):
self.set_header("Content-Type", "application/json")
…
class mark(BaseHandler):
′′′
基于二維空間的搜索
′′′
def get(self):
self.set_header("Content-Type","application/json")
try:
…
(3).map-reduce計算做日志分析。
′′′
調度生成當天用戶訪問行為
′′′
class currdayuser(BaseHandler):
def get(self):
…
′′′
調度生成當天服務運行行為
′′′
class currdayservice(BaseHandler):
def get(self):
目前這種存儲結構,解決了項目中大數據存儲和實時云計算的需求。使用了Mongodb切片的水平動態添加,可不中斷平臺業務系統的同時保障擴容后的查詢速度和云計算效能;依據切片鍵索引分片,計算位于各切片獨立進行,使大數據下的實時分析成為現實。對于高頻訪問的數據放在了Redis中,有效地降低了磁盤I/O,使業務系統響應更為敏捷,滿足了高并發下的應用服務的高吞吐要求。雖然大數據的存儲和計算變得簡單,但由于版本和技術在日新月異的變化,數據系統的管理工作并不輕松。在新架構下的運維管理還會遇到新的挑戰并需不斷優化完善。
參考文獻
[1] 田濤,常青,邱桂蘋,等.基于Redis的人本電子健康系統的設計與實現[J].電子世界,2013(24):137-138.
[2] 曾超宇,李金香.Redis在高速緩存系統中的應用[J].微型機與應用,2012(12):11-13.
[3] 何杭鋒.基于FODO算法MongoDB自動分片的改進[J].計算機技術與發展,2013(7):127-130.
[4] 霍多羅夫,迪洛爾夫.MongoDB權威指南[M].程顯鋒譯北京:人民郵電出版社,2011.
[5] 呂明育,李小勇.NoSQL數據庫與關系數據庫的比較分析[J].微型電腦應用,2011,27(10):55-57.
[6] MongoDB features[OL]. http://www.cnblogs.com.[2011-06-01].