在PyCon上有童鞋提供了一個(gè)類似概念的分享,不過(guò)不大適合一般類型的互聯(lián)網(wǎng)項(xiàng)目,感覺(jué)有點(diǎn)過(guò)于另類。不過(guò)我實(shí)現(xiàn)這個(gè)方案是在看到PyCon的分享之前。算是同樣的訴求不同的實(shí)現(xiàn)方式吧。且我這里只是實(shí)現(xiàn)了一個(gè)數(shù)據(jù)訪問(wèn)的組件而不是Server。
首先本文的方法來(lái)自FriendFeed分享的如何使用MySQL數(shù)據(jù)庫(kù)的分享。簡(jiǎn)而言之就是把Python對(duì)象直接dumps后zip壓縮存儲(chǔ)在MySQL一個(gè)字段里。這樣不就Schemaless了么?存什么數(shù)據(jù)類型,類什么結(jié)構(gòu),MySQL都不需要知道,加個(gè)屬性什么的都不需要修改數(shù)據(jù)庫(kù)表結(jié)構(gòu),對(duì)于業(yè)務(wù)快速變更、快速增長(zhǎng)的互聯(lián)網(wǎng)業(yè)務(wù)來(lái)說(shuō)再合適不過(guò)了。訪問(wèn)對(duì)象直接通過(guò)主鍵查詢,快速直接。but,查詢?cè)趺崔k?有的童鞋可能會(huì)問(wèn)。OK,查詢這事得分兩說(shuō),如果是簡(jiǎn)單的檢索,可以通過(guò)建索引表的方式來(lái)解決,或者呢用外部的索引,比如lucent,還能全文檢索哦。現(xiàn)在而今眼目下我實(shí)現(xiàn)了索引表索引的方式,因?yàn)橥獠康乃饕绞奖容^千奇百怪,所以如果需要可以根據(jù)具體情況自己來(lái)寫(xiě)一個(gè),反正實(shí)現(xiàn)相應(yīng)的幾個(gè)方法就行。
直接上一個(gè)例子來(lái)說(shuō)明。假設(shè)要實(shí)現(xiàn)一個(gè)blog,需要存blog的信息,先定義一個(gè)blog的模型類(需要import什么大家自動(dòng)腦補(bǔ))
這個(gè)connection是因?yàn)槲疫€沒(méi)想好如何能無(wú)縫結(jié)合到Django中又能兼顧脫離Django獨(dú)立使用的暫時(shí)措施,完成版會(huì)去掉
如果在使用django的話只需要 python manage.py shell 然后 Blog.objects.create_table()
這個(gè)時(shí)候會(huì)自動(dòng)創(chuàng)建模型定義的表和索引表
數(shù)據(jù)表 blogs:
同時(shí)建立兩個(gè)索引表
CREATE TABLE `blog_idx_post_date` (
`id` int(10) unsigned NOT NULL,
`post_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_blogs_by_post_date` (`post_date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `blog_idx_auther` (
`id` int(10) unsigned NOT NULL,
`auther` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_blogs_by_auther` (`auther`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這個(gè)時(shí)候,可以通過(guò) Blog.objects.create(title=u"標(biāo)題",content=u"內(nèi)容",post_date=datetime.datetime.now(),auther=user) 或者Blog.objects.create(title=u"標(biāo)題",content=u"內(nèi)容",post_date=datetime.datetime.now(),auther=user.id)
就能夠創(chuàng)建一個(gè)Blog的對(duì)象。這個(gè)時(shí)候blogs表和兩個(gè)索引表都會(huì)插入數(shù)據(jù)。不過(guò)blogs表中的object列是人類無(wú)法理解的火星文..........
通過(guò)id直接獲取對(duì)象 Blog.objects.get(1),根據(jù)索引獲取 Blog.objects.auther.query(auther=user.id) 或者 Blog.objects.auther.query(auther=user)
這個(gè)會(huì)生成SQL,SELECT `id` FROM `blog_idx_auther` WHERE `auther`=%s 然后取出match到對(duì)象的id列表,然后遍歷id列表,通過(guò) Blog.objects.get(id)獲得的對(duì)象列表。
Blog.objects.get(id)的時(shí)候是有對(duì)象緩存的(現(xiàn)階段通過(guò)redis實(shí)現(xiàn)),所以經(jīng)過(guò)測(cè)試,速度是靠譜的。而相對(duì)MangoDB來(lái)說(shuō),MySQL的數(shù)據(jù)存儲(chǔ)也更加靠譜一點(diǎn),所以相比換現(xiàn)在而今眼目下還不怎么靠譜的mangodb來(lái)作為主存儲(chǔ)來(lái)說(shuō),基于MySQL的Schemaless方案還是相對(duì)靠譜的。
由于現(xiàn)在這個(gè)東西還是處于在項(xiàng)目中孵化的階段還沒(méi)有能夠達(dá)到可以獨(dú)立開(kāi)源出來(lái)供大家?jiàn)蕵?lè)的程度,所以請(qǐng)大家對(duì)這個(gè)方案多提意見(jiàn)建議咯,源代碼估計(jì)能夠在春節(jié)后達(dá)到能夠公布出來(lái)見(jiàn)人的階段。