璐村惂鐢ㄦ埛_005tSVG馃惥 -
关注数: 0 粉丝数: 2 发帖数: 84 关注贴吧数: 4
Google文件系统 Google文件系统GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,但可以提供容错功能。它可以给大量的用户提供总体性能较高的服务。1、设计概览(1)设计想定GFS与过去的分布式文件系统有很多相同的目标,但GFS的设计受到了当前及预期的应用方面的工作量及技术环境的驱动,这反映了它与早期的文件系统明显不同的设想。这就需要对传统的选择进行重新检验并进行完全不同的设计观点的探索。GFS与以往的文件系统的不同的观点如下:1、部件错误不再被当作异常,而是将其作为常见的情况加以处理。因为文件系统由成百上千个用于存储的机器构成,而这些机器是由廉价的普通部件组成并被大量的客户机访问。部件的数量和质量使得一些机器随时都有可能无法工作并且有一部分还可能无法恢复。所以实时地监控、错误检测、容错、自动恢复对系统来说必不可少。2、按照传统的标准,文件都非常大。长度达几个GB的文件是很平常的。每个文件通常包含很多应用对象。当经常要处理快速增长的、包含数以万计的对象、长度达TB的数据集时,我们很难管理成千上万的KB规模的文件块,即使底层文件系统提供支持。因此,设计中操作的参数、块的大小必须要重新考虑。对大型的文件的管理一定要能做到高效,对小型的文件也必须支持,但不必优化。3、大部分文件的更新是通过添加新数据完成的,而不是改变已存在的数据。在一个文件中随机的操作在实践中几乎不存在。一旦写完,文件就只可读,很多数据都有这些特性。一些数据可能组成一个大仓库以供数据分析程序扫描。有些是运行中的程序连续产生的数据流。有些是档案性质的数据,有些是在某个机器上产生、在另外一个机器上处理的中间数据。由于这些对大型文件的访问方式,添加操作成为性能优化和原子性保证的焦点。而在客户机中缓存数据块则失去了吸引力。4、工作量主要由两种读操作构成:对大量数据的流方式的读操作和对少量数据的随机方式的读操作。在前一种读操作中,可能要读几百KB,通常达 1MB和更多。来自同一个客户的连续操作通常会读文件的一个连续的区域。随机的读操作通常在一个随机的偏移处读几个KB。性能敏感的应用程序通常将对少量数据的读操作进行分类并进行批处理以使得读操作稳定地向前推进,而不要让它来来回回的读。5、工作量还包含许多对大量数据进行的、连续的、向文件添加数据的写操作。所写的数据的规模和读相似。一旦写完,文件很少改动。在随机位置对少量数据的写操作也支持,但不必非常高效。6、系统必须高效地实现定义完好的大量客户同时向同一个文件的添加操作的语义。(2)系统接口GFS提供了一个相似地文件系统界面,虽然它没有向POSIX那样实现标准的API。文件在目录中按层次组织起来并由路径名标识。(3)体系结构:一个GFS集群由一个master和大量的chunkserver构成,并被许多客户(Client)访问。如图1所示。Master和 chunkserver通常是运行用户层服务进程的Linux机器。只要资源和可靠性允许,chunkserver和client可以运行在同一个机器上。文件被分成固定大小的块。每个块由一个不变的、全局唯一的64位的chunk-handle标识,chunk-handle是在块创建时由 master分配的。ChunkServer将块当作Linux文件存储在本地磁盘并可以读和写由chunk-handle和位区间指定的数据。出于可靠性考虑,每一个块被复制到多个chunkserver上。默认情况下,保存3个副本,但这可以由用户指定。Master维护文件系统所以的元数据(metadata),包括名字空间、访问控制信息、从文件到块的映射以及块的当前位置。它也控制系统范围的活动,如块租约(lease)管理,孤儿块的垃圾收集,chunkserver间的块迁移。Master定期通过HeartBeat消息与每一个 chunkserver通信,给chunkserver传递指令并收集它的状态。
boost::thread简要分析(3):线程局部存储及其它(TLS,TSS) 转自:http://blog.vckbase.com/billdavid/archive/2005/08/03/5736.html 多线程编程中还有一个重要的概念:Thread Local Store(TLS,线程局部存储),在boost中,TLS也被称作TSS,Thread Specific Storage。boost::thread库为我们提供了一个接口简单的TLS的面向对象的封装,以下是tss类的接口定义:class tss{public: tss(boost::function1 * pcleanup); void* get() const; void set(void* value); void cleanup(void* p);};分别用于获取、设置、清除线程局部存储变量,这些函数在内部封装了TlsAlloc、TlsGetValue、TlsSetValue等API操作,将它们封装成了OO的形式。但boost将该类信息封装在detail名字空间内,即不推荐我们使用,当需要使用tss时,我们应该使用另一个使用更加方便的类:thread_specific_ptr,这是一个智能指针类,该类的接口如下:class thread_specific_ptr : private boost::noncopyable // Exposition only{public: // construct/copy/destruct thread_specific_ptr(); thread_specific_ptr(void (*cleanup)(void*)); ~thread_specific_ptr(); // modifier functions T* release(); void reset(T* = 0); // observer functions T* get() const; T* operator->() const; T& operator*()() const;};即可支持get、reset、release等操作。thread_specific_ptr 类的实现十分简单,仅仅为了将tss类“改装”成智能指针的样子,该类在其构造函数中会自动创建一个tss对象,而在其析构函数中会调用默认参数的 reset函数,从而引起内部被封装的tss对象被析构,达到“自动”管理内存分配释放的目的。以下是一个运用thread_specific_ptr实现TSS的例子:#include #include #include #include boost::mutex io_mutex;boost::thread_specific_ptr ptr; // use this method to tell that this member will not shared by all threadsstruct count{ count(int id) : id(id) { } void operator()() { if (ptr.get() == 0) // if ptr is not initialized, initialize it ptr.reset(new int(0)); // Attention, we pass a pointer to reset (actually set ptr) for (int i = 0; i < 10; ++i) { (*ptr)++; boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": " << *ptr << std::endl; } } int id;};int main(int argc, char* argv[]){ boost::thread thrd1(count(1)); boost::thread thrd2(count(2)); thrd1.join(); thrd2.join(); return 0;}此外,thread库还提供了一个很有趣的函数,call_once,在tss::init的实现中就用到了该函数。该函数的声明如下:void call_once(void (*func)(), once_flag& flag);该函数的Windows实现通过创建一个Mutex使所有的线程在尝试执行该函数时处于等待状态,直到有一个线程执行完了func函数,该函数的第二个参数表示函数func是否已被执行,该参数往往被初始化成BOOST_ONCE_INIT(即0),如果你将该参数初始化成1,则函数func将不被调用,此时call_once相当于什么也没干,这在有时候可能是需要的,比如,根据程序处理的结果决定是否需要call_once某函数func。call_once在执行完函数func后,会将flag修改为1,这样会导致以后执行call_once的线程(包括等待在Mutex处的线程和刚刚进入call_once的线程)都会跳过执行func的代码。需要注意的是,该函数不是一个模板函数,而是一个普通函数,它的第一个参数1是一个函数指针,其类型为void (*)(),而不是跟boost库的很多其它地方一样用的是function模板,不过这样也没有关系,有了boost::bind这个超级武器,想怎么绑定参数就随你的便了,根据boost的文档,要求传入的函数不能抛出异常,但从实现代码中好像不是这样。以下是一个典型的运用call_once实现一次初始化的例子:#include #include #include int i = 0;int j = 0;boost::once_flag flag = BOOST_ONCE_INIT;void init(){ ++i;}void thread(){ boost::call_once(&init, flag); ++j;}int main(int argc, char* argv[]){ boost::thread thrd1(&thread); boost::thread thrd2(&thread); thrd1.join(); thrd2.join(); std::cout << i << std::endl; std::cout << j << std::endl; return 0;}结果显示,全局变量i仅被执行了一次++操作,而变量j则在两个线程中均执行了++操作。其它boost::thread 目前还不十分完善,最主要的问题包括:没有线程优先级支持,或支持线程的取消操作等,而且,目前的实现机制似乎不大容易通过简单修改达到这一要求,也许将来的某个版本会在实现上出现较大调整,但目前支持的接口应该会相对保持稳定,目前支持的特性也还会继续有效。
1 下一页