MySQL
关系型数据库存储系统,我们的DBA团队很强大,每人管理上百台MySQL服务器,其他就不多说了,网上资料太多了
Tokyo Cabinet
一个key-value的存储引擎,日本人开发,国内很多公司也开始使用,我们内部很多地方也用它来代替MySQL来做存储,比如我们的搜索结果页的用户资料,就是用它来做一层MySQL外的冗余存储,目的是加快搜索结果页的显示。在key-value并需要持久存储的场景下,用它比MySQL更有效,Cabinet本身只是一个存储引擎,没有网络处理能力,你可以用它作为自己的某个系统的下层存储引擎,更好的是搭配Tokyo Tyrant使用。
Tokyo Tyrant
一个支持Memcached传输协议的网络接口,由Tokyo Cabinet的作者开发,目的是为Tokyo Cabinet提供网络接入能力,即Tokyo Tyrant处理网络连接,协议解析,然后调用Tokyo Cabinet的API来完成持久化存储。
ICE
一个跨语言的网络通讯框架,框架本身提供了强大的通讯能力,管理工具,负载均衡方案,其跨语言能力也是一个很大的亮点,基于这个框架之上,我们选用合适的语言来提供合适的服务,比如我们使用C++来开发Cache服务,使用Java来开发一些逻辑服务。框架本身可以很重,也可以很轻,具体要看你怎么用:)
Memcached
一个纯内存的key-value的cache系统,高效、稳定,使用广泛,如果你连它都没听说过就太out啦,memcached本身不具备分布式能力,需要依靠Client来实现分布,这里强调一点的是,你应该选择一致性Hash来做key的分布。各种语言的client都有,我们使用spymemcached作为java的Client,spymemcached是一个异步的NIO的memcached client,对网络IO的处理非常的精巧,也更加高效,同时因为提供异步操作方式,可以让你对Memcached的操作有更好的控制能力,Memcached到1.4.0版本之后,开始支持binary protocol,spymemcached对其也支持的比较好,使用binary protocol可以提高对协议的解析效率和网络IO的读写效率。
上面说到我们使用ICE自己开发了Cache服务,为什么我们还要用Memcached呢?主要在对Cache的操作粒度不一样,Memcached对Cache对象以binary byte作为一个整体来操作,需要频繁的序列化和反序列化,我们使用ICE提供的Cache服务,可以以Cache对象的一个或者多个字段来操作,比如一个用户对象,我们可以只更新它的姓名,而Memcached
Nginx
高效、稳定的Web Server,我们利用其代理能力,做跨IDC的请求代理,同时也将其和我们的Resin(Java Web 容器)搭配,放在Resin的前面来解决Resin的对网络连接处理能力弱的问题,在一些小地方也用它来做7层的负载均衡
Resin
一个Java Web Server,比Tomcat更高效,是我们主要的Java Web容器
Squid
代理服务器,我们用他来做图片文件的反向代理缓存
LVS
能提供4层的负载均衡,高效、高可用,高并发。我们用他替代了很多硬件的负载均衡设备
Struts
Java web框架,不过这个已经是历史了,我们开发了一套自己的Web框架替代了它,未来我们也会把我们的内部的这套Web框架开源出来
Lucence
基于Java的搜索引擎框架,用它我们构建了一个搜索集群来提供搜人的服务
Netty
一个Java的网络框架,和apache的mina类似,但比mina更高效,我们用来做一些小的服务
Ganglia
一个监控系统,帮组我们了解我们每台Server的资源利用情况
还有些小东西就不列出来了,最后要说的一点就是,对这些开源软件或者系统,我们都非常的了解,或者说知根知底,从API到内部实现原理,甚至到一些源码的细节。
<!--
<div class="postmetadata alt" mce_tmp="1">
<small>
这篇文章发布于 2009年12月13日,星期天,2:57 下午,归类于 <a href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" mce_href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" title="查看 生产力电台 的全部文章" rel="category tag">生产力电台</a>。 您可以跟踪这篇文章的评论通过 <a href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/feed/" mce_href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/feed/">RSS 2.0</a> feed。
您可以<a href="#respond" mce_href="#respond">留下评论</a>,或者从您的站点<a href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/trackback/" mce_href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/trackback/" rel="trackback">trackback</a>。
</small>
</div>
-->
人人网中间层:求解篇
作者:人人网技术经理白伯纯 人人网UGC团队博客
书接上文,为了提高性能,在人人网的技术结构中,在数据库和页面之间,有中间层。中间层高性能的基础是用内存代替磁盘。
用内存代替磁盘
数据库系统的最大瓶颈在磁盘IO,大量的小数据请求不是磁盘的强项。人人网中间层服务就是利用了内存代替硬盘的方法来提高整体性能。有了这层服务以后,以前的数据库关联查询被提前计算并缓存,需要访问时直接获取。
通用的Memcached缓存方案也有些不足,数据不能自己变化,也不能部分变化。于是人人网选择了自己实现缓存的方式。
在自己实现缓存的过程中,管理内存相对容易,通信协议是比较复杂的部分,我们在这方面选择了开源的Ice通信框架(http://www.zeroc.com)来完成繁琐的工作,至今它都工作的很好。
Ice通信框架在人人网完成了两件事,通信和定位。客户端通过IceGrid组件定位到需要的服务地址,将请求发送到中间层服务,中间层服务将结果返回。客户端只需要知道一个地址就可以找到所有的服务;同时,众多服务也可以在不同的服务器之间随意迁移。在现在的人人网有超过500个Ice写成的中间层服务在运行。
定制的内存数据
用Ice解决了通信和部署的问题后,中间层服务就是核心的数据结构管理。概括的说,就是灵活变化,保证速度。下面列举若干使用了中间层服务的情况
一份数据 多种排序
在人人网的好友页,有很多排序方式可以显示好友列表。每种列表都是从一个按ID排序的服务中获取的,再经过排序,缓存在各个顺序的列表中。
随时间变化的数据
在很多列表页面,都会显示“在线标志”,这个标志是冗余在各个列表的缓存当中,定期刷新的。这些需要和cache一起实现的业务逻辑,在人人网中间层当中非常普遍。
特殊类型
我们用了一个bit保存用户的激活状态。200M内存可以保存全部int范围的状态。并且查询和更新速度飞快。
接下来的实践篇将会用这个为例子展示中间层的实现。
人人网中间层:实践篇
作者:人人网技术经理白伯纯 人人网UGC团队博客
人人网中间层:问题篇
人人网中间层:求解篇
之前的问题篇和求解篇描述了人人网在发展过程中遇到的问题,并且介绍了我们采用中间层来提高性能的解决方案。今天的实践篇将通过一个例子来实现一个中间层服务。
这个服务要达到的目的是快速的查询用户是否有效,数据将要使用bitset保存在内存中,每个用户一位,仅保存正整数约21亿,占用内存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命令编译成为服务端的Skeleton文件:
slice2cpp -I/opt/Ice-3.3/slice BitServer.ice
服务端
有了上面生成的服务端文件后,就可以实现我们自己的业务功能了。
BitServerI.h和BitServerI.cpp,暂时只是实现了单个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
然后自己实现客户端代码:
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);
}
}
性能测试
完成了代码,来测试一下性能吧。
首先启动服务器
target/bitserver –Ice.Config=config
再启动客户端
java -cp /opt/Ice-3.3/lib/Ice.jar:target/bitclient.jar /
renren.BitServerAdapter “BitServer:default -p 10000” 1022
在客户端调用增加循环50000次,单线程平均每秒处理一万次。
在多线程的环境下,单个服务器每秒可处理的请求8万次左右,已经超过了目前的需要。
<!--
<p class="postmetadata alt">
<small>
这篇文章发布于 2010年02月20日,星期六,6:19 下午,归类于 <a href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" title="查看 生产力电台 的全部文章" rel="category tag">生产力电台</a>。 您可以跟踪这篇文章的评论通过 <a href='http://ugc.renren.com/2010/02/20/renren-ice/feed/'>RSS 2.0</a> feed。
您可以<a href="#respond">留下评论</a>,或者从您的站点<a href="http://ugc.renren.com/2010/02/20/renren-ice/trackback/" rel="trackback">trackback</a>。
</small>
</p>
-->
<!--
<div class="postmetadata alt" mce_tmp="1">
<small>
这篇文章发布于 2010年01月11日,星期一,11:28 上午,归类于 <a href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" mce_href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" title="查看 生产力电台 的全部文章" rel="category tag">生产力电台</a>。 您可以跟踪这篇文章的评论通过 <a href="http://ugc.renren.com/2010/01/11/renren-ice-part2/feed/" mce_href="http://ugc.renren.com/2010/01/11/renren-ice-part2/feed/">RSS 2.0</a> feed。
您可以<a href="#respond" mce_href="#respond">留下评论</a>,或者从您的站点<a href="http://ugc.renren.com/2010/01/11/renren-ice-part2/trackback/" mce_href="http://ugc.renren.com/2010/01/11/renren-ice-part2/trackback/" rel="trackback">trackback</a>。
</small>
</div>
-->
<!--
<div class="postmetadata alt" mce_tmp="1">
<small>
这篇文章发布于 2009年12月13日,星期天,2:57 下午,归类于 <a href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" mce_href="http://ugc.renren.com/category/%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%94%b5%e5%8f%b0/" title="查看 生产力电台 的全部文章" rel="category tag">生产力电台</a>。 您可以跟踪这篇文章的评论通过 <a href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/feed/" mce_href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/feed/">RSS 2.0</a> feed。
您可以<a href="#respond" mce_href="#respond">留下评论</a>,或者从您的站点<a href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/trackback/" mce_href="http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren/trackback/" rel="trackback">trackback</a>。
</small>
</div>
-->
相关推荐
软件架构 研究开源软件架构 软件架构 研究开源软件架构 软件架构 研究开源软件架构 架构
48位开源软件作者站出来,解说他们的软件是如何架构的,以及为什么这么做? 如果你刚刚入门,想要学习前辈的思想,这两本书是个好开头。如果你是一位中级或高级开发者,想要了解同行们是如何解决难题的,它们同样有...
了解互联网公司所使用的Java技术栈 了解开发过程中朝夕相处的工具 了解日常开发任务的完整生命周期(开发到测试到生产发布的流程) 了解一个网站从小到大发展过程以及在各个阶段登场的中间件 以Apollo为例了解一个...
常见开源软件的架构
48位开源软件作者站出来,解说他们的软件是如何架构的,以及为什么这么做? 如果你刚刚入门,想要学习前辈的思想,这两本书是个好开头。如果你是一位中级或高级开发者,想要了解同行们是如何解决难题的,它们同样有...
解密淘宝网的开源架构解密淘宝网的开源架构解密淘宝网的开源架构
基于开源软件的WebGIS架构设计书 看过不后悔,不信试一试。
第三部分着重讲解在开源软件选型中非常重要的环节——开源软件许可,通过问答的方式向大家讲解开源许可相关的知识产权问题对开源软件选型的影响,并对开源许可中最重要的GPL协议进行了分析;第四部分向大家推荐一...
开源软件不仅在云计算、大数据、人工智能、区块链等新兴技术发展中占据重要地位,在操作系统、数据库等基础软件的影响力也不断扩大。随着整个软件供应链开源化趋势越来越明显,开源软件的知识产权纠纷也会越来越多。...
第1篇 了解开源软件 第1章 开源软件概述 1.1 开源软件的理解 1.2 开源软件的定义 1.3 开源软件定义的意义 1.4 开源软件和其他类型软件的比较 第2章 开源软件的历史与未来 2.1 开源软件的历史 2.2 开源运动背后的...
主题: 1、大数据时代趋势和数据库技术更新 ...附件有一个《CSDN_开源大数据技术架构设计_2015-09-08_Q35636787.avi》一小时的全程视频(145 MB),还有一个讲师用的《开源大数据技术架构设计培训资料.pptx》(61 MB)。
人人网架构发展 及人人网使用开源架构技术及特点。
原创!开源的SOA的技术参考架构!
安卓开源项目人人网客户端源码 , 可直接运行,虽然没有数据看不到具体内容,但是也可以学到很多东西
资源名称:oschina(开源社区)技术架构介绍内容简介:每日访问统计数据总览IP > 10w动态请求接近 300w 页面请求 80w,Ajax请求 220w高峰期并发连接数 2000oschina 硬件配置DELL SC 1435 (1台) CPU: 双 AMD 2G 内存:...
2021中国网络开源技术生态峰会PPT汇总,共21份。 轻量级k8s构建开放式边缘计算架构 白盒开放场景及研究探讨 大网网络操作系统+云网融合的智慧大脑 不断扩展的云网络边界和开源技术在其中的应用 网络操作系统-从开源...
Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目,并且是顶级项目。目前最新的发布版本是 2.0.1,未来不久将发布 2.1 版本。就 Ambari 的作用来说,就是创建、管理、监视 Hadoop 的...
第二篇探讨使用开源软件时需要注意的各项具体事宜,特别是与知识产权相关的方面,例如软件著作权、许可证等,然后分享搜索所需开源软件的技巧,并罗列了一些流行的开源软件。第三篇全面介绍如何参与开源社区的工作,...
淘宝网架构;解密淘宝网的开源架构,快来看一下吧
pdf相关的开源软件,包括xpdf,sumatrapdf,imageMagick。都是开源的。