国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
人人網(wǎng)中間層-系統(tǒng)架構(gòu)

人人網(wǎng)中間層:問題篇

由開源軟件組成的系統(tǒng)

與很多大型的網(wǎng)站一樣,人人網(wǎng)的系統(tǒng)全部是由開源軟件構(gòu)建的。使用Nginx做前端接入,resin做容器,Memcached做通用cache,MySQL做數(shù)據(jù)庫,使用Linux操作系統(tǒng)。
除了上述的部分外,人人網(wǎng)還有一個與眾不同的中間層。中間層以服務(wù)的形式存在,位于MySQL和resin中間,提供高并發(fā)低成本的數(shù)據(jù)訪問層。

數(shù)據(jù)庫的壓力

在上述結(jié)構(gòu)系統(tǒng)中,數(shù)據(jù)庫的性能往往成為系統(tǒng)瓶頸。人人網(wǎng)在發(fā)展的過程中不斷重構(gòu),改變最大的就是數(shù)據(jù)庫部分。大概的步驟是“優(yōu)化SQL”,“業(yè)務(wù)拆分”,“垂直拆分”和“水平拆分”幾個階段,關(guān)于數(shù)據(jù)庫優(yōu)化的細節(jié)將來再引用到這里。
經(jīng)過優(yōu)化后的數(shù)據(jù)庫,單臺可以承擔每秒3000次的主鍵查詢。再提高性能的優(yōu)化,我們采用的方案是使用中間層。

性能目標

增加中間層可以在不增加服務(wù)器數(shù)量的前提下,提高服務(wù)的整體性能,并且提高系統(tǒng)的可擴展性。這里簡要列舉一些使用中間層服務(wù)優(yōu)化的效果。

實時更新的數(shù)據(jù)

用戶的個人信息數(shù)據(jù),目前的寫操作500次/秒,讀操作2萬次/秒。這些數(shù)據(jù)分布在數(shù)十個數(shù)據(jù)表中,如果用數(shù)據(jù)庫做10次主鍵查詢,需要的時間將會非??捎^。中間層的緩存服務(wù)把這個性能穩(wěn)定在了99.9%的請求時間小于20ms。
判斷好友關(guān)系,讀操作900次/秒。這個操作現(xiàn)在使用6G內(nèi)存存儲了所有的好友關(guān)系,在2ms內(nèi)返回任意兩人的好友關(guān)系。
關(guān)聯(lián)查詢,僅好友列表就有1300次/秒。如果使用關(guān)聯(lián)查詢,數(shù)據(jù)庫需要同步很多無用的字段?,F(xiàn)在只需要兩次內(nèi)存請求,并且衍生出很多種類的排序。

大量聚合的訪問

聚合的頁面在SNS中是訪問量最大的部分。首頁集成的功能多達17個模塊,這些模塊之間的關(guān)系相對獨立。為了快速的把這些數(shù)據(jù)集合在一起,就需要迅速獲取數(shù)據(jù)。
我們對整體技術(shù)框架的要求是,關(guān)鍵頁面執(zhí)行時間要在100ms以內(nèi)。

Session同步

眾多的resin服務(wù)器之間,如何共享用戶身份驗證的結(jié)果,在各種session共享機制中,我們的方案是使用中間層服務(wù)來集中存儲的。

待續(xù)

問題篇只是開端,接下來的“求解篇”將會分析人人網(wǎng)中間層的主要應(yīng)用場景。“實踐篇”將會舉例一個典型的中間層服務(wù)。

人人網(wǎng)中間層:求解篇

為了提高性能,在人人網(wǎng)的技術(shù)結(jié)構(gòu)中,在數(shù)據(jù)庫和頁面之間,有中間層。中間層高性能的基礎(chǔ)是用內(nèi)存代替磁盤。

用內(nèi)存代替磁盤

數(shù)據(jù)庫系統(tǒng)的最大瓶頸在磁盤IO,大量的小數(shù)據(jù)請求不是磁盤的強項。人人網(wǎng)中間層服務(wù)就是利用了內(nèi)存代替硬盤的方法來提高整體性能。有了這層服務(wù)以后,以前的數(shù)據(jù)庫關(guān)聯(lián)查詢被提前計算并緩存,需要訪問時直接獲取。
通用的Memcached緩存方案也有些不足,數(shù)據(jù)不能自己變化,也不能部分變化。于是人人網(wǎng)選擇了自己實現(xiàn)緩存的方式。
在自己實現(xiàn)緩存的過程中,管理內(nèi)存相對容易,通信協(xié)議是比較復(fù)雜的部分,我們在這方面選擇了開源的Ice通信框架(http://www.zeroc.com)來完成繁瑣的工作,至今它都工作的很好。
Ice通信框架在人人網(wǎng)完成了兩件事,通信和定位??蛻舳送ㄟ^IceGrid組件定位到需要的服務(wù)地址,將請求發(fā)送到中間層服務(wù),中間層服務(wù)將結(jié)果返回。客戶端只需要知道一個地址就可以找到所有的服務(wù);同時,眾多服務(wù)也可以在不同的服務(wù)器之間隨意遷移。在現(xiàn)在的人人網(wǎng)有超過500個Ice寫成的中間層服務(wù)在運行。

定制的內(nèi)存數(shù)據(jù)

用Ice解決了通信和部署的問題后,中間層服務(wù)就是核心的數(shù)據(jù)結(jié)構(gòu)管理。概括的說,就是靈活變化,保證速度。下面列舉若干使用了中間層服務(wù)的情況

一份數(shù)據(jù) 多種排序

在人人網(wǎng)的好友頁,有很多排序方式可以顯示好友列表。每種列表都是從一個按ID排序的服務(wù)中獲取的,再經(jīng)過排序,緩存在各個順序的列表中。

隨時間變化的數(shù)據(jù)

在很多列表頁面,都會顯示“在線標志”,這個標志是冗余在各個列表的緩存當中,定期刷新的。這些需要和cache一起實現(xiàn)的業(yè)務(wù)邏輯,在人人網(wǎng)中間層當中非常普遍。

特殊類型

我們用了一個bit保存用戶的激活狀態(tài)。200M內(nèi)存可以保存全部int范圍的狀態(tài)。并且查詢和更新速度飛快。
接下來的實踐篇將會用這個為例子展示中間層的實現(xiàn)。

人人網(wǎng)中間層:實踐篇

之前的問題篇和求解篇描述了人人網(wǎng)在發(fā)展過程中遇到的問題,并且介紹了我們采用中間層來提高性能的解決方案。今天的實踐篇將通過一個例子來實現(xiàn)一個中間層服務(wù)。
這個服務(wù)要達到的目的是快速的查詢用戶是否有效,數(shù)據(jù)將要使用bitset保存在內(nèi)存中,每個用戶一位,僅保存正整數(shù)約21億,占用內(nèi)存256M。

開始編碼

下面的代碼都在這個位置保存:http://gitorious.org/renren/bitserver。

接口定義

定義接口如下:

#include <Ice/BuiltinSequences.ice>
module renren {
struct BitSegment {
int begin;
int end;
Ice::ByteSeq data;
};
interface BitServer {
bool get(int offset);
Ice::BoolSeq gets(Ice::IntSeq offsets);
BitSegment getSegment(int begin, int end);
};
};

這個BitServer.ice文件,通過slice2cpp命令編譯成為服務(wù)端的Skeleton文件:

slice2cpp -I/opt/Ice-3.3/slice BitServer.ice

服務(wù)端

有了上面生成的服務(wù)端文件后,就可以實現(xiàn)我們自己的業(yè)務(wù)功能了。
BitServerI.h和BitServerI.cpp,暫時只是實現(xiàn)了單個get的接口。

#ifndef __BitServerI_h__
#define __BitServerI_h__#include <BitServer.h>

#define SIZE_OF_BIT 2147483647
#include <bitset>

namespace renren
{

class BitServerI : virtual public BitServer
{
public:
void initialize();

virtual bool get(::Ice::Int,
const Ice::Current&);

virtual ::Ice::BoolSeq gets(const ::Ice::IntSeq&,
const Ice::Current&);

virtual ::renren::BitSegment getSegment(::Ice::Int,
::Ice::Int,
const Ice::Current&);
private:
std::bitset<SIZE_OF_BIT> bits_;
};

}

#endif

#include <BitServerI.h>
#include <Ice/Ice.h>int main(int argc, char** argv) {
int status = 0;
Ice::CommunicatorPtr ic;
try{
ic = Ice::initialize(argc, argv);
Ice::ObjectAdapterPtr adapter = ic->createObjectAdapter(“BitServer”);
renren::BitServerI* obj = new renren::BitServerI;
obj->initialize();
adapter->add(obj, ic->stringToIdentity(“BitServer”));
adapter->activate();
ic->waitForShutdown();
} catch (const Ice::Exception& e) {
std::cerr << e << std::endl;
status = 1;
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
status = 1;
} catch () {
std::cerr << “unknown exception” << std::endl;
status = 1;
}
if (ic) {
try {
ic->destroy();
} catch (const Ice::Exception& e) {
std::cerr << e << std::endl;
status = 1;
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
status = 1;
} catch () {
std::cerr << “unknown exception” << std::endl;
status = 1;
}
}
return status;
}

void
renren::BitServerI::initialize() {
for (int i=0; i<0xFFFFF;i=i+2) {
bits_[i]=true;
}
}

bool
renren::BitServerI::get(::Ice::Int offset,
const Ice::Current& current)
{
if(offset < 0) return false;
return bits_[offset];
}

::Ice::BoolSeq
renren::BitServerI::gets(const ::Ice::IntSeq& offsets,
const Ice::Current& current)
{
return ::Ice::BoolSeq();
}

::renren::BitSegment
renren::BitServerI::getSegment(::Ice::Int begin,
::Ice::Int end,
const Ice::Current& current)
{
return ::renren::BitSegment();
}

客戶端

我們使用Java作為客戶端,首先用slice2java工具生成Java的Proxy類。

slice2java -I/opt/Ice-3.3/slice BitServer.ice

然后自己實現(xiàn)客戶端代碼:

package renren;class BitServerAdapter {
private final String endpoints_;
private Ice.Communicator ic_;
private renren.BitServerPrx prx_;

public BitServerAdapter(String endpoints) {
this.endpoints_ = endpoints;
}

public void initialize() {
ic_ = Ice.Util.initialize();
prx_ = renren.BitServerPrxHelper.uncheckedCast(ic_.stringToProxy(endpoints_));
}

public boolean get(int id) {
return prx_.get(id);
}

public static void main(String[] args) {
BitServerAdapter adapter = new BitServerAdapter(args[0]);
adapter.initialize();
boolean ret = adapter.get(Integer.valueOf(args[1]));
System.out.println(ret);
System.exit(0);
}
}

性能測試

完成了代碼,來測試一下性能吧。
首先啟動服務(wù)器

target/bitserver –Ice.Config=config

再啟動客戶端

java -cp /opt/Ice-3.3/lib/Ice.jar:target/bitclient.jar \
renren.BitServerAdapter “BitServer:default -p 100001022

在客戶端調(diào)用增加循環(huán)50000次,單線程平均每秒處理一萬次。

在多線程的環(huán)境下,單個服務(wù)器每秒可處理的請求8萬次左右,已經(jīng)超過了目前的需要。

來自:http://ugc.renren.com/2009/12/28/renren-ice-problem/http://ugc.renren.com/2010/01/11/renren-ice-part2/http://ugc.renren.com/2010/02/20/renren-ice/

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
用ICE開發(fā)分布式程序
ICE的深度技術(shù)分析【轉(zhuǎn)載】
很不多的ICE架構(gòu)入門學(xué)習例子
人人網(wǎng)里的美女
平遙
貓撲話題的公共主頁 - 人人網(wǎng),renren.com,貓撲話題,網(wǎng)絡(luò)媒體,公共主頁
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服