爲什麼用*? 爲什麼不用*?

爲什麼用*? 爲什麼不用*?
2011年03月10日
  離開RoR有一段時間了,本來不想提些負面的東西,不過JE獵頭(機器人?還是感謝下)給我發過幾次工作信息,所以我還是來表明下態度,說點感受吧。
  我做過一段時間RoR,感覺小項目還是可以的,一旦項目發展到一定規模,RoR的各種優勢都會變得不明顯。
  我現在所在的公司網站大概每天3億PV,服務器加起來也有上千臺,同時在線人數接近60萬,各種數據每秒訪問量都上萬,所以不是任何數據庫能負載的,即使 是把數據庫分庫分表(這種情況下用RoR的ActiveRecord也不方便)。目前是按業務劃分把各種業務邏輯和cache用C++寫中間件,前臺 PHP用socket來調用(WebService?太慢),我所知道的一些國內同等訪問量的網站也都是使用類似的方式。
  不使用ActiveRecord的RoR項目是什麼樣的? 這個我還沒仔細想過。我使用過1.1.6和之前的版本,對於網站的分層目錄支持似乎都不是很好,而大型網站通常都會有很多層分級目錄,這樣是不是 ActionPack又得考慮要不要再用?看看還剩下什麼?ActionWebService?目前很少用到WebService,所以基本上RoR對於 我目前所在的項目來說已經沒什麼有意義的東西了。
  網站做到一定規模,要解決的東西都是很繁瑣的,結果會有一大批人來做,每個人做的都是些非常簡單的部分,唯一的要求就是在同樣的功能下如何加快效率,服務器畢竟不可以無限增加,而且服務器越多維護成本也越高,cache/HA同步成本也越高。
  前段時間公司請了些人來做敏捷培訓,結果是培訓完了,根本沒什麼效果,人家的例子和我們的相差太大。公司讓我做RoR培訓, 我也推掉了,目前我還看不到公司裏使用RoR的合適場合。所以最近關注的都是併發、分佈方面的東西。
  爲什麼用RoR?理由也很簡單,在中小型網站項目上,它還是可以用來快速開發原型。我去年用RoR做過一個小項目,大部分時間花在數據庫建模、網站邏輯、後臺工作自動化、JS腳本等。
  RE: 其實到了全球排名前10之內的網站規模,不管用RoR,PHP,Java,還是Perl,C++都會面臨同樣的問題,編程語言的差異反而不存在了。你的題目也可以改成"爲什麼用Java,爲什麼不用Java?"或者"爲什麼用PHP,爲什麼不用PHP?"
  RE: 主要不是說語言,而是框架,java裏面可能是hibernate + struts + velocity,面對拆庫拆表的情況,hibernate怕也會力不從心,最後可能也只有struts+velocity還能發揮點作用,爲了簡單還不 如jsp算了,這跟我上面所說的RoR的情況相似。我以前看到許多知名的大網站都用PHP,感覺不能理解,後來想通了,規模上去了,什麼ORM都用不上 了,邏輯放前臺也不方便,就會形成一些中間層,每個只負責單一業務邏輯,這樣前臺只需要一個處理顯示邏輯的東西,PHP/JSP好像很合適,不過PHP更 得開發人員青睞,修改了放上去就能看到效果(RoR好像也要development模式才行?)。
  RE: ALL
  (Twitter遇到的麻煩: http://blog.csdn.net/dhansson/archive/2007/05/24/1 623837.aspx)Twitter是一個很令人驚歎的成功故事。我很有幸能和開發團隊談過他們富有挑戰性的開發經歷。那個時候,他們需要在只有很少緩存的16塊芯片情況下,巧妙的處理超過11000次每秒的訪問請求。
  Rails讓開發的過程變成一個開心的過程,但是當你需要經歷所有其他開發環境同樣的擴容過程時,這個對比會顯得很突兀。或許這是一個自然的反應來爲這個反差找一個替罪羊,而無論這個替罪羊(Rails)是多麼的自然。
  當你在使用開源軟件,發現有些要求是這個軟件無法達到的時候,這就是你給開源軟件作回報的大好機會。與其坐在原地等待某些廠家來解決你的問題,使用開源軟件會給你獨特的機會,來做自己命運的主人。與其作這個社區的旁觀者,不如作一個參與者。對於用高級編程語言(比如說Ruby)實現的程序框架Rails,以上的話尤其貼切,因爲作貢獻的門檻非常的低。
  很贊同
  特別是最後一句
  作爲一個每日訪問量上億、數千臺服務器的巨頭網站
  應該表現出自己對於技術社羣的貢獻
  而不是等着那些從來沒有機會做那麼大的網站的開源貢獻者們來幫忙解決只有你那麼大的網站纔會遇到的問題
  前幾天聽了個課程,講的是公司經營發展的,一般公司前2年是快速成長期,技術通常還不上檔次,也比較散。之後5年是規範期,大概到這個5年的末期各個產品纔會規範成熟。目前我們剛剛過完前2年,技術上纔剛剛從db/php的2層架構往db/midware/php的3層上轉型。國外公司也許技術上比較好一些,經過2年就有拿得出手的產品(比如rails)去開源,國內恐怕還差得很遠。
  大網站技術是分散的,通常每一個部分的技術層次都非常低,除了方案整個可以拿來討論以外,討論每一個部分的技術都會讓人覺得沒有含金量,想想 C++調用數據庫並緩存數據有什麼技術含量?前臺PHP通過socket訪問C++中間層有什麼技術含量?通常一樣中間層項目時間緊的話在現有項目上改一天就能完成,至少我覺得這樣的事找應屆生一樣能做,唯一長點見識的就是整個系統架構的把握和大型網站整體負載的一些數據,公司倒覺得應屆生理解架構並發現風險的能力差了,而這正是公司想要的。只有把網站架構拿來討論纔是有意義的,不過把整個網站的架構拿出來討論那不是掀了自己的底嘛。
  我並沒有參與過大型高併發高負載網站的建設,不過對樓主的一些觀點存在疑問,請教一下:
  各種數據每秒訪問量都上萬,所以不是任何數據庫能負載的,即使是把數據庫分庫分表(這種情況下用RoR的ActiveRecord也不方便)。目前是按業 務劃分把各種業務邏輯和cache用C++寫中間件,前臺PHP用socket來調用(WebService?太慢),我所知道的一些國內同等訪問量的網 站也都是使用類似的方式。
  疑問:
  因爲數據庫壓力採用分庫分表的話,我理解中的Hibernate/JPA應該可以應付這樣的場景,保持多個sessionFactory,根據合適的策略選擇相應 的sessionFactory 。雖然我沒使用過rails,但是 ActiveRecord同時連接多個數據庫應該是一個很合理的需求。
  如果 rails應用到幾個大型高併發高負載項目裏面,會碰到具體的應對高併發高負載而設計的系統架構所帶來的問題,伴隨這些具體問題的解決,rails似乎也不能成爲架構高性能網站的阻礙哦。比如樓主提到的分庫分表,多級目錄的問題。
  以前用hibernate主要是做一些表的映射、關聯,更深層的應用就沒有了,所以也沒什麼經驗,拿個具體的情況來分析一下吧。
  目前主要數據庫是mysql,由於數據庫存儲限制:
  1、通常會把用戶名和密碼放一個庫(負載相對較少,但也要依賴cache)。
  2、用戶基本資料拆開多臺DB按用戶名或ID hash,用戶擴展信息也拆開多臺。
  3、用戶積分因爲太敏感,甚至使用了oracle來保證效率和穩定性(事實證明它比mysql慢。。它的C++綁定也更不穩定)。
  4、用戶發帖是保存在文件的,數據庫只保存文件鏈接發帖人等簡單信息。
  5、用戶之間的消息是放數據庫的,當然也是按用戶名hash到多臺,這時候要查詢我給別人的消息和別人給我的消息,就得從2個表裏面查,因爲你給別人的消息是按別人的用戶名hash到某一臺上,別人給你的是按你的用戶名hash的,所以增加一條消息就得往2個庫各寫一條。
  以上列舉了一部分應用,當然由於庫拆得比較散,基本上每個庫都會有冗餘字段。
  上面這種情況下,能不能分析一下hibernate和ActiveRecord用得比較舒服的部分?
  我在用rails的時候,ActiveRecord對於多數據庫支持並不好,即使是有這樣的方案也是非方的技巧。分表情況下表之間的關聯基本上沒法做,如果沒有關聯,ActiveRecord的意義只是幫我們生成SQL?
  多級目錄不是最大的問題,也不是阻礙性能的問題,俺只想找個最後的理由把RoR不適用這個項目說得更充分些。。。
  謝謝你能夠提供更多的信息來參與討論, 針對你提到的2),這樣的情況下,按照我的理解,現有的java的orm框架無法針對不同庫的表作映射。 activeRecord應該也沒有考慮到這種情況。
  不知道你們作出的分庫的依據是什麼,我覺得更合理的分庫依據應該根據負載壓力和模塊獨立性來分離,比如你提到的消息發送應該是統一的模塊,按照用戶名hash到不同的庫的話,對於業務層開發帶來一定的複雜度。
  分表的話,java的orm有些策略可以繞着解決,比如用繼承策略來解決。但是也是比較彆扭。 不過,我更想了解的是你們作出的分表的依據是什麼?
  這樣的情況下,模型的關聯映射在現有的orm框架下確實太牽強了,即使用了,收到的效果也是很小的,模型也會隨之退化到單實體+基本類型外鍵的維護上來,如果讓我選擇的話,基本上也是選擇spring的jdbcTemplate了。
  如果覺得java orm是促進開發效率的一個基本前提的話,那麼在系統架構選擇上,特別是數據庫架構設計上,可能還要更慎重一些,因爲不同於數據庫底層開發,orm對於數據庫的要求會有一些苛刻。爲了最大化獲得模型映射的效果,有一些建議不知道是否合理:
  在考慮訪問壓力的情況下,儘量按照耦合緊密的原則分庫,使得某一個庫的表關聯能夠作充分的模型映射,而對於少數的外庫關聯仍然需要做手工的維護,不過已經簡化到最小。
  因爲數據量大而分表的話,可以採用多態映射關聯來做和多表的關聯。
  基本上分庫主要原因都是和容量或性能有關,上億用戶,每個用戶只保存一個用戶名和密碼,也有好幾G的數據。
  爲了登錄部分效率考慮,用戶名和密碼拆到一個庫中,因爲這部分讀取並不是特別頻繁,所以目前用主備方式,備的目的是主掛掉至少不會讓用戶無法登錄,頂多無法註冊而已。
  用戶的基本資料字段是固定的,但容量有些大,訪問也比較頻繁。之前用戶沒有中間層,所以拆庫來提高效率。現在有中間層,拆庫的意義也變了,領導不希望任何一臺機器故障影響到所有用戶,影響部分用戶還是勉強可接受的。實際上隨着用戶的不斷增加,即便是使用中間層也會有壓力,畢竟中間層只是幫數據庫擋了讀取的壓力,而讀寫比例通常情況下是10:1左右。
  用戶擴展信息,這個是一對多的,一個用戶可自定義不同的字段,通常是用戶有修改時更新一下,讀取壓力並不大,同樣是因爲中間把把讀取壓力都擋掉了,但容量非常大。
  當然也考慮過如果有中間層,是不是數據庫不用拆得這麼細,目前也做過一些合併工作,不過意義並不大,因爲所有數據庫容量加起來以T計,不管是備份還是擴容甚至修復硬件故障都會影響用戶很長時間,現在拆得這麼細,通常一個點的故障只會影響一部分用戶的一部分功能。目前硬件故障還是會經常有的,比如某國外品牌的服務器故障率非常高。擴容也是經常會有的,文件每天上傳量就超過2T,每月都增加存儲。數據庫差不多每3月-6月都要重新拆分一次,因爲容量。
  樓主的做法和我當時在網易的做法非常相似,不過我們當時就是JDBC,拆表的方法我用Hibernate實現過,不過拆庫就比較麻煩了,如果不涉及事務還好。
  ebay也是拆庫拆表的方式,在應用級處理之間的關聯關係,我想越是大型的系統,在應用級處理的方式越原始,不能用框架,或是需要自己寫框架處理。
  還有一點,我認爲整體網站應該拆分爲非常細小的應用,一個應用只處理一樣事情,應用之間的調用可以用HTTP、Socket,不建議Webservice,效率較低。
  還是我一開始說的,99.99%的中小網站永遠不會變成大型網站。所以"如何開發中小網站"的知識不能應用於大型網站,並不是一個嚴重的問題。
  另一方面,大型網站會遇到一些特殊的問題。這些問題也許別人也會遇到,但只有他們有足夠的錢來解決。出於社會責任感,他們應該把這些解決方案貢獻給開源社區。
  具體到這個案例,就是樓主應該說"我告訴你們如何用Ruby(甚至Rails)處理複雜的數據庫",而不是問"Ruby on Rails應該如何處理這些複雜的數據庫"。這纔是一個大型網站,一個受到最多用戶關注的組織,一個擁有最強技術力量和最多資金的組織應該有的態度。
  說到底,開發大型網站和中小型網站的方法可能大不一樣,這就帶來一個問題,有比較豐富的中小型網站經驗的架構師不一定能勝任大型網站,反過來應該也成立,把大型網站的方法弄到中小網站上,會不會造成開發週期長?中間是不是有個鴻溝?
  事情都是這樣的,誰能一開始想那麼遠呢?先揀手頭的合適的工具上手再說,以後再慢慢改慢慢優化。即使到最後把以前的都推翻了也是覈算的。
  順便說,如果富客戶越來越流行,以後連eruby/jsp/php這些動態頁面顯示層大概也沒用了,就只剩中間件+靜態頁面+富客戶。。。
  我也是這麼想的,富客戶+中間件,靜態頁面都沒必要了,呵呵。
  那這種中間件,用Rails是再合適沒有了,Rails已經提供了完善的REST和XML輸出支持,什麼Flex啊,Ext-js啊,都合作良好,你唯一要做的,就是把ActiveRecord改成ActiveCICS或者ActiveTuxteo或者ActiveSocket...
  這也是合理的。目前我們用C++寫中間件,都是自定義協議格式。如果直接提供給客戶端,協議上還得包裝成XML或其它,一些安全方面的邏輯還是要有一層,因爲這些C++中間件基本上都是內網使用,不考慮安全性,也沒辦法考慮,它的功能相當於自己實現高性能cache的數據庫,每一個調用相當於一個存儲過程。
  通常銀行系統對於穩定性、邏輯原子性的要求比較高,性能要求相對較低,我在網銀上轉帳通常一次操作要十幾秒,但在網站系統上這是不可接受的。網站通常對於性能和穩定性要求比較同,操作原子性都排到後面了,有時候甚至是異步寫,比如用戶發個帖子加5分,我只要保證他馬上能看到帖子,馬上能刷新他cache裏的分數,什麼時候加到數據庫裏面作永久存檔都不重要。這種需求的差異帶來的數據庫設計差異也是比較大的。
  你的第一個方法,對於一個用戶多條記錄的,比如論壇發帖是可以的,不過通常論壇是按最後回覆來排序,分開是否不合適?這種方式對於支付系統還是可以考慮的。
  第二個方法,我前面簡單描述過,通常不能把一個用戶所有信息放在一起,因爲有時候某些表負載會比較高,不希望一些不重要的系統影響到登錄、積分這些嚴重影響用戶體驗的。全部放在一起,可能就會分出更多的相同結構的數據庫服務器,維護也是比較麻煩的。另外有些相互關聯的比如某用戶的好友,某用戶是誰的好友這2個反向關係,其它一些我發出的郵件和我收到的郵件,每添加一條記錄都是要寫2個不同表的。
  公司有產品部門,他們會分析哪些東西對用戶是最敏感的,頁面元素甚至一個小鏈接一個小圖標對用戶的影響,所有的系統架構基本上都要考慮他們的分析結果,通常他們的意見都是和用戶非常貼近的。
  如果不採用你們目前的做法,而是把用戶分在不同的庫中,"這些系統在某些時候可能處於極高負載之下"還會發生嗎?異步操作還有必要嗎?
  不同的用戶只會對不同的服務器產生壓力,根本不會出現處理不過來的高峯,10臺不行,就20臺,100臺,10000臺...,因爲水平擴展總是可能,而且近乎於無限制。
  但如果是按照分用戶屬性的方法,畢竟屬性是有限的,不可能無限分解的,所以,會存在一個上限。
  另外,從程序改動來說,分用戶的方法,會使得過渡相當平滑,對於業務層來說,編程模式同一個數據庫沒有任何區別,除了在從一臺服務器升級到兩臺,需要改變一段代碼外,後續增加的服務器可以通過配置來完成,完全不需要改變任何代碼。 但如果是分屬性的方法,業務層是否還能做到透明呢?
  Link:
  爲什麼用RoR?爲什麼不用RoR? http://www.javaeye.com/topic/94774?page=3
  解決海量數據的新思路 分佈式數據庫: http://www.javaeye.com/topic/212046
  SOHU這幾年一些門戶級別的程序系統(C/C++開發) : http://dynamiclu.javaeye.com/blog/484766
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章