Ganglia是UC Berkeley发起的一个开源集群监视项目,设计用于测量数以千计的节点。Ganglia的核心包含gmond、gmetad以及一个Web前端。Ganglia集群主要用来监控系统性能,它由RRDTool工具处理数据,并生成相应的监控相关的图形,并提供一个Web控制台来直观地提供给客户端,管理员可以通过丰富的图形来对整个被监控的物理机器集群节点进行评估。Ganglia能够监控的内容很多,如CPU利用率 、Mem利用率、硬盘利用率, I/O负载、网络流量情况等,通过曲线很容易见到每个节点的工作状态,对合理调整、分配系统资源,提高系统整体性能起到重要作用。需要知道的是,Ganglia可以做系统监控,但是,目前它不支持服务器异常或故障报警功能。 Ganglia监控集群架构 下面,我们参考《Monitoring with Ganglia》一书,对Ganglia的架构有一个基本了解,然后在配置使用过程中,能够更好地理解监控的基本原理。下面是Ganglia的整体架构,如图所示: 通过上图我们可以看到,Ganglia集群主要是由gmond、gmetad、gweb这3个守护进程组成,其中gmetad进程相当于监控集群的Master,而多个gmond
Hive-0.12.0的Web接口HWI安装、配置、改造及使用
使用Hive的HWI接口,可以通过在Web页面上提交HQL查询操作,并浏览查询结果数据。默认情况下,HWI只支持浏览结果数据,不能够下载查询结果文件(当然,HWI可能也是考虑通过Web下载大量的结果数据,对服务器造成压力,或者处于安全方面的考虑)。我们对HWI进行了简单的改造,改造内容主要是增加了一个内置的文件服务器,可以通过页面进行查询,然后下载结果文件。 HWI安装配置 首先,要保证Hadoop集群正常运行,Hive能够正常使用。 先要安装Ant,如下所示: wget http://mirrors.hust.edu.cn/apache//ant/binaries/apache-ant-1.9.4-bin.tar.gz tar xvzf apache-ant-1.9.4-bin.tar.gz ln -s /usr/local/apache-ant-1.9.4-bin /usr/local/ant 修改Hive的环境配置文件hive-env.sh,增加如下配置内容: export ANT_LIB=/usr/local/ant 将如下JAR文件拷贝到${HIVE_HOME}/lib目录下面: // 用于编译JSP文件 jasper-compiler-5.5.23.jar jasper-runtime-5.5.23.jar // 替换默认的servlet-api-2.5-20081211.jar,我使用的是apache-tomcat-7.0.53/lib下面的s
Memcached服务器安装、配置、使用详解
我使用的是CentOS 6.4系统,安装的Memcached版本为1.4.20。这里,记录一下安装配置的过程,以及如何使用一些常用的客户端来访问Memcached存储的数据。 安装配置 首先,编译、安装、配置libevent库,执行如下命令: wget https://github.com/downloads/libevent/libevent/libevent-1.4.14b-stable.tar.gz tar xvzf libevent-1.4.14b-stable.tar.gz ln -s /usr/local/libevent-1.4.14b-stable /usr/local/libevent cd /usr/local/libevent ./configure make make install 然后,编译、安装、配置Memcached,执行如下命令行: wget http://www.memcached.org/files/memcached-1.4.20.tar.gz tar xvzf memcached-1.4.20.tar.gz ln -s /usr/local/memcached-1.4.20 /usr/local/memcached ./configure --with-libevent=/usr/local/libevent/ make make install 如果没有出错,安装成功。 管理memcached服务 启动Memcached 一般情况下,简单地可以使用类似如下形式,启动Memcached服务: /usr/local/bin/memcached -d -m 64 -I 20m -u root -l 192.
Node.js入门学习笔记
关于Node.js介绍,我们引用官网(http://nodejs.org/)的一段文字说明: Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. Google Chrome浏览器基于V8的,它是一个开源的JavaScript引擎,能够编译和执行JavaScript代码,在执行速度上有很大的优势。使用Node.js能够很容易地构建快速、可扩展的网络应程序,它使用了事件驱动、非阻塞I/O模型实现,具有轻量、高效的特点,适合于构建运行在分布地设备之上的数据密集型实时应用程序。 下面通过参考各种资料,从各个方面,概括地总结一下Node.js,是我们对Node.js有一个直观的了解: 使用JavaScript运行于服务端的平台上,自然继承了JavaScript语言的一些特性; Node.js基于单线程、基于非阻塞I/O模型实现; 适合于数据密集型应用,不适用于计算密
Spring+Mybatis实现动态SQL查询
在报表类应用中,通常需要根据不同的维度去组合复杂的查询条件,然后构造SQL去执行查询。如果只是通过在程序中简单地拼接SQL语句,工作量会非常大,而且代码可能也非常难以维护。Mybatis支持动态SQL查询功能,可以通过配置动态的SQL来简化程序代码中复杂性,不过,这个颇有点XML编程的韵味,通过XML来处理复杂的数据判断、循环的功能,其实也很好理解。 准备工作 下面,我们首先创建一个MySQL示例表,如下所示: CREATE TABLE `traffic_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `domain` varchar(64) NOT NULL, `traffic_host` varchar(64) NOT NULL, `month` varchar(8) NOT NULL, `monthly_traffic` int(11) DEFAULT '0', `global_traffic_rank` int(11) DEFAULT '0', `native_traffic_rank` int(11) DEFAULT '0', `rank_in_country` varchar(64) DEFAULT NULL, `address` varchar(200) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, `traffic_type` int(2) DEFAULT '-1', `status` int(2) DEFAULT '0', `cr
HDFS格式化过程分析
我们知道,Namenode启动时可以指定不同的选项,当指定-format选项时,就是格式化Namenode,可以在Namenode类中看到格式化的方法,方法签名如下所示: private static boolean format(Configuration conf, boolean isConfirmationNeeded, boolean isInteractive) throws IOException 在该方法中,首先调用FSNamesystem类的方法,获取到待格式化的name目录和edit目录: Collection<File> editDirsToFormat = Collection<File> dirsToFormat = FSNamesystem.getNamespaceDirs(conf); FSNamesystem.getNamespaceEditsDirs(conf); 跟踪调用FSNamesystem类的方法,可以看到,实际上获取到的目录为: name目录:是根据配置的dfs.name.dir属性,如果没有配置,默认使用目录/tmp/hadoop/dfs/name。 edit目录:是根据配置的dfs.name.edits.dir属性,如果没有配置,默认使用目录/tmp/hadoop/dfs/name。 在上面format方法中,创建对应的name目录和edit目录,对应如下代码行: FSNamesystem nsys = new FSNamesystem(new FSImage(dirsToFormat,
内部排序算法:基数排序
基本思想 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。 基数排序可以采用两种方式: LSD(Least Significant Digital):从待排序元素的最右边开始计算(如果是数字类型,即从最低位个位开始)。 MSD(Most Significant Digital):从待排序元素的最左边开始计算(如果是数字类型,即从最高位开始)。 我们以LSD方式为例,从数组R[1..n]中每个元素的最低位开始处理,假设基数为radix,如果是十进制,则radix=10。基本过程如下所示: 计算R中最大的元素,求得位数最大的元素,最大位数记为distance; 对每一位round<=distance,计算R[i] % radix即可得到; 将上面计算得到的余数作为bucket编号,每个bucket中可能存放多个数组R的元素; 按照bucket编号的顺序,收集bucket中元素,就地替换数组R中元素; 重复2~4,最终数组R中的元素为有序。 算法实现 基数排序算法,Java实现,代码如下所示: p
内部排序算法:归并排序
基本思想 n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: 初始状态:无序区为R[1..n],有序区为空。 第1趟排序: 在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1] 交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 …… 第i趟排序: 第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k],将它与无序区的第1个记录R[i]交换,使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。 算法实现 归并排序算法,Java实现,代码如下所示: public abstract class Sorter { public abstract void sort(int[] array); } public class MergeSorter extends Sorter { @Override public void sort(int[] array) { int[] auxArray = new int[array.length];
内部排序算法:堆排序
基本思想 堆的定义 n个关键字序列kl,k2,…,kn称为堆,当且仅当该序列满足如下性质之一(简称堆性质): ki≤k2i且ki≤k2i+1 或 ki≥k2i且ki≥k2i+1(1≤i≤FLOOR(n/2)) 若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若 存在)结点的关键字。 小根堆:根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小的。 大根堆:根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大的。 我们可以选择大根堆或者小根堆中的任意一个来进行排序。 排序思想 用大根堆排序的基本思想: 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区。 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得 到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key。 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个
内部排序算法:快速排序
基本思想 设当前待排序的数组无序区为R[low..high],利用分治法可将快速排序的基本思想描述为: 分解: 在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无需参加后续的排序。 注意:划分的关键是要求出基准记录所在的位置pivotpos,划分的结果可以简单地表示为(注意pivot=R[pivotpos]): R[low..pivotpos-1].keys ≤ R[pivotpos].key ≤ R[pivotpos+1..high].keys 其中low≤pivotpos≤high。 求解: 通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high] 快速排序。 组合: 因为当“求解”步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言, “组合”步骤不需要做什么,可看作是空操作。 算法实现 快速排序算法
内部排序算法:希尔排序
基本思想 先取一个小于n的整数d1作为第一个增量,把待排序的全部记录分成dx个组。所有距离为d1的倍数的记录放在同一个组中。 先在各组内进行直接插人排序。 然后,取第二个增量d2<d1重复上述的分组和排序。 直至所取的增量dt=1(dt<dt-x<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。 算法实现 希尔排序算法,Java实现,代码如下所示: public abstract class Sorter { public abstract void sort(int[] array); } public class ShellSorter extends Sorter { @Override public void sort(int[] array) { int d = array.length; do { d /= 2; shellPass(array, d); // 根据逐渐减小的间隔增量,循环调用一趟排序 } while (d > 1); } /** * 希尔一趟排序 * @param d 间隔增量 */ private void shellPass(int[] array, int d) { Integer tmp; for (int i = d; i <
内部排序算法:冒泡排序
基本思想 将被排序的记录数组R[0..n-1]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其 向上”飘浮”。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。 具体过程,如下所示: 初始状态:R[0..n-1]为无序区。 第一趟扫描:从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者 在上,则交换二者的位置,即依次比较(R[n-1], R[n-2])、(R[n-2], R[n-3])、…、(R[1], R[0]);对于每对气泡(R[j+1], R[j]),若R[j+1].key第一趟扫描完毕时,”最轻”的气泡就飘浮到该区间的顶部,即关键字最小的记录被放在最高位置R[0]上。 第二趟扫描:扫描R[1..n-1]。扫描完毕时,”次轻”的气泡飘浮到R[1]的位置上……最后,经过n-1趟扫描可得到有序区R[0..n-1]。 注意: 第i趟扫描时,R[0..i-1]和R[i..n-1]分别为当前的有序区和无序区。扫描仍是从无序区底 部向上直至该区顶部。扫描完毕时,该区中最轻气泡飘浮到顶部