lee的个人空间

    理论指导实践,实践验证理论

    对于扣订人员来说,用程序实现自动化流程处理是非常省事的,如同google的广告系统,它完全不需要人工干预,简直就是一部造钱的机器。

    让人蛋疼的是我所做的工作本是自动化的,近期由于合作方问题,导致数据不再符合自动化统计流程,领导有命:统计数据还是要形成常态出具的,悲催的我只能领命。

    对于大量的日志数据,虽不能全自动化,但也不至于完全靠手工,实现个半自动化统计程序应对短期的突发事故还是可行的

    日志格式以竖线分隔,需要统计出每个位置的点击数,需求比较简单,首先考虑的是利用shell来完成。

    可利用cut来截取所需字段,另shell script做数值运算也挺简单,但需要一个类似map的存储结构,位置作为key, 点击数作为value

    shell没有map类型数据结构,仅有的是array,查阅了相关array使用方法后,在特定场合可以将array充当map来使用——位置当作array的下标,该位置的点击数则充当array下标的值

    代码如下:

    #! /bin/bash
    #author sawenlee 2011-09-01
    #func   calculate the sum of each position
    #
    PATH=.:/usr/local/bin:/bin:/usr/bin:/usr/sbin/:/sbin:/usr/local/sbin:/home/dev/bin:/usr/local/mysql/bin
    export PATH
    base=/data/urlred
    #args length must be greater than 0
    if [ $# == "0" ]; then
    echo “Usage: [calc_click] src_file”
    exit 1
    fi
    declare -a result #we need an data structure to collect results
    declare -i num
    maxLen=100 #set array max length
    #this is the target file we are goting to handle
    txtFile=$base/$1
    if test -e $txtFile ; then
    echo “starting to handle file : $txtFile”
    echo “Index  count”
    for pos in `cat $txtFile | grep success| cut -d ‘|’ -f 4` ;  #截取位置元素
    do
    if [ $pos -lt $maxLen -a  $pos -gt 0 ]; then   #过滤掉无效的位置
    ((result[$pos]++))                                            #shell script的数值运算很特别
    fi
    done
    for  ((i = 1; i <= $maxLen; i++))                    #输出结果
    do
    if test ! -z “${result[$i]}”  ; then                    #如果有值才输出
    echo “$i ${result[$i]}”
    fi
    done
    else
    echo “$txtFile doesn’t exist”
    fi

     

    根据MapReduce计算的流程,在Map阶段选择好KeyValue,然后在reduce中输出计算结果,计算UV的话,最终的结果只是一个数字

    我最开始的思路是:

    map阶段选择常数1作为key,uid作为value,在reduce阶段将map输出放置到HashSet中排重,输出hashSet的size即为正确的UV

    我运行的日志如下:

    11/08/22 16:14:54 INFO mapred.JobClient:   FileSystemCounters
    11/08/22 16:14:54 INFO mapred.JobClient:     FILE_BYTES_READ=817583842
    11/08/22 16:14:54 INFO mapred.JobClient:     HDFS_BYTES_READ=11406242768
    11/08/22 16:14:54 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=1459132572
    11/08/22 16:14:54 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=9
    11/08/22 16:14:54 INFO mapred.JobClient:   Map-Reduce Framework
    11/08/22 16:14:54 INFO mapred.JobClient:     Reduce input groups=1
    11/08/22 16:14:54 INFO mapred.JobClient:     Combine output records=0
    11/08/22 16:14:54 INFO mapred.JobClient:     Map input records=5097005
    11/08/22 16:14:54 INFO mapred.JobClient:     Reduce shuffle bytes=0
    11/08/22 16:14:54 INFO mapred.JobClient:     Reduce output records=1
    11/08/22 16:14:54 INFO mapred.JobClient:     Spilled Records=17676018
    11/08/22 16:14:54 INFO mapred.JobClient:     Map output bytes=61164060
    11/08/22 16:14:54 INFO mapred.JobClient:     Combine input records=0
    11/08/22 16:14:54 INFO mapred.JobClient:     Map output records=5097005
    11/08/22 16:14:54 INFO mapred.JobClient:     Reduce input records=5097005
    从以上红色标记日志可以看出处理记录数为5097005条,但reduce分组为1,reduce输出结果也为1
    这是因为key值相同,在mapreduce过程中会将相同的key归并在一起,不难理解这种情况仅仅只有一个reduce任务
    由此造成的后果是reduce任务只会在集群其中一个节点上运行,不仅没有利用好集群处理能力,反倒因为大量数据集中而导致计算效率低下,如果出现OOM异常,那也算正常(因为将所有用户都放置到一个hashset中)
    改进:
    既然reduce任务负载不均衡是因为key单一导致,那可以打散key,把reduce任务分解成N个,分配到整个集群上计算;这就可以解决问题
    我在map阶段把uid整数化后(为什么要整数化,而不直接用字符串?这个大家都应该清楚,整数相对字符串而言,整数更节省存储容量,值比较效率更高) 对1000取模充当key,value为uid; 于是就有1000个不同的key,也将产生1000个reduce任务,这样就充分利用了集群的计算能力;
    map阶段     key: uid%1000                   value: uid
    这样就会产生0-999的key,reduce部分不需要改动,输出的结果可能如下:

    uid%1000=0       XXX

    uid%1000=1        XXX

    uid%1000=2       XXXX

    ……………………….

    uid%1000=998   XXXX

    uid%1000=999   XXXX

    上面输出的结果并非我需要的,但无碍,可以在这基础上再做mapreduce一遍,reduce任务里求和就可以了

    map代码:
    public void map(Object key, Text value, Context ctx)
    throws IOException, InterruptedException {
    try {

    String[] elements = value.toString().split(“\\|”); // 按|分隔符打散

    String userid = elements[7]; // 获取用户标识

    long uidHash = NetUtil.hash(NetUtil.computeMd5(userid), 0); // 哈希转整数

    int mapKey = (int) (uidHash % 1000);//取模将key打散

    ctx.write(new IntWritable(mapKey), new LongWritable(uidHash));

    } catch (Exception e) {
    e.printStackTrace();
    return;
    }
    }

    reduce代码

    public void reduce(IntWritable key, Iterable<LongWritable> values,
    Context ctx) throws IOException, InterruptedException {

    Set<Long> uidSet = new HashSet<Long>();

    Iterator<LongWritable> iter = values.iterator();
    while (iter.hasNext()) {
    long uid = iter.next().get();
    uidSet.add(uid);
    }

    ctx.write(key, new LongWritable(uidSet.size()));
    }

    运行后的日志如下:

    11/08/22 16:08:39 INFO mapred.JobClient:   FileSystemCounters
    11/08/22 16:08:39 INFO mapred.JobClient:     FILE_BYTES_READ=817583986
    11/08/22 16:08:39 INFO mapred.JobClient:     HDFS_BYTES_READ=11406242768
    11/08/22 16:08:39 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=1459132860
    11/08/22 16:08:39 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=7890
    11/08/22 16:08:39 INFO mapred.JobClient:   Map-Reduce Framework
    11/08/22 16:08:39 INFO mapred.JobClient:     Reduce input groups=1000
    11/08/22 16:08:39 INFO mapred.JobClient:     Combine output records=0
    11/08/22 16:08:39 INFO mapred.JobClient:     Map input records=5097005
    11/08/22 16:08:39 INFO mapred.JobClient:     Reduce shuffle bytes=0
    11/08/22 16:08:39 INFO mapred.JobClient:     Reduce output records=1000
    11/08/22 16:08:39 INFO mapred.JobClient:     Spilled Records=17676018
    11/08/22 16:08:39 INFO mapred.JobClient:     Map output bytes=61164060
    11/08/22 16:08:39 INFO mapred.JobClient:     Combine input records=0
    11/08/22 16:08:39 INFO mapred.JobClient:     Map output records=5097005
    11/08/22 16:08:39 INFO mapred.JobClient:     Reduce input records=5097005
    同样的输入记录数,但可以看到以分散成了1000个reduce任务,输出结果同样是1000个

    最近自己写的nio程序持续报错(client-server端借助mina实现)

    DefaultExceptionMonitor.exceptionCaught(45) 2011-09-02 09:40:57 | Unexpected exception.
    java.nio.channels.ClosedSelectorException
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:66)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
    at org.apache.mina.transport.socket.nio.NioProcessor.select(NioProcessor.java:69)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:961)
    at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
    at java.lang.Thread.run(Thread.java:595)

    通过搜索引擎没有查出问题,但可能的原因是线程阻塞在Selector.select()时,调用了wakeup方法,而此时selector已经关闭

    与淘宝大牛 @dennis zhuang 对这个问题做了一次交流,他与我一致认为问题不在mina上,而在于使用错误,导致mina关闭了selector。

    因client每发送一次消息都会报一次异常,Dennis 以此推断是我用短连接但没有复用NioSocketConnector造成的,client端发送完消息关闭NioSocketConnector就可能报ClosedSelectorException问题,这涉及mina的内部实现:

    当client端关闭connector,mina要关闭NioProcessor线程,此时线程正阻塞在select上,所以先关闭selector,然后唤醒它,mina就会提示selector已经被关闭

    此外创建NioSocketConnector代价太大,所以即使用短连接也得考虑复用它,而不是每通信完一次,就将其关闭,这样就可以解决异常问题(复用connector不关闭它),同时还能提高性能。当然最好的是用mina构建client-server的长连接,实现重连机制,通信稳定且性能更优!

     

    简要需求如下(注:以下域名和ip形式纯属假象,你肯定没见过a.b.c.d的ip,这些字母代表0-255之间的数字):

    1,aaa.com———>a.b.c.d:8080/web

    2,aaa.com/admin–>a.b.c.d:8082/admin

    3,bbb.com———->a.b.c.d:8083/wap

    经过多次的尝试,始终没法把第一条和第三条映射上,nginx的简化配置如下:

    server aaa.com

    location / {

    proxy_pass http://a.b.c.d:8080/web

    }

    location /admin{

    proxy_pass http://a.b.c.d:8082/admin

    }

    server bbb.com

    location /{

    proxy_pass http://a.b.c.d:8083/wap

    }

    # service nginx reconfigure后发现除了第二条映射生效外,其他两个都始终报302 404错误,然后将第一、三条 location / 分别改成 /web   /wap

    与/admin一致后,然后通过aaa.com/web  aaa.com/wap访问就能成功,通过这规律可能是一个域名只能映射到ip:port;而到模块名就必须也得在域名后加上相应的模块名;而且要用到模块名,在location处的映射必须与应用名一致即如果配置了下面这种形式同样会出错:

    server aaa.com

    location /myAdmin{

    proxy_pass http://a.b.c.d:8082/admin;

    }

    以上红色字体部分对某些应用必须要相同,否则没法跳转。

    根据现有情况,只能改变应用模块的访问方式了,将web,wap所有的应用名去掉,保证a.b.c.d:8080就能访问到web站点,而不需要加上/web,wap同理

    改动后自己服务器上测试后通过!

     

    nginx安装:http://www.javali.org/360

    hive特性:

    数据存储在hdfs上,依托hadoop集群实现并行计算

    采用hiveQL作为查询语言,与SQL极其相似

    Hive中存储的数据无固定格式要求,可随用户自定义

    可追加数据,但不支持更改

    可扩展性强,支持大规模并行计算

     

    hive安装
    请确保 hadoop集群处在运行状态
    当前用户环境变量中有HADOOP_HOME,如果不设置,hive没法运行

    $cd /opt/soft
    $wget  http://apache.etoak.com/hive/hive-0.7.0/hive-0.7.0-bin.tar.gz
    $tar -zxvf  hive-0.7.0-bin.tar.gz
    $mv hive-0.7.0 hive
    $cd hive/conf

    $cp hive-default.xml hive-site.xml
    $cd ../bin
    $./hive   启动hive进入命令行

    操作指南
    可见官网文档:https://cwiki.apache.org/confluence/display/Hive/GettingStarted#GettingStarted-SQLOperations

    Hive提供了很多的函数,可以在命令行下show functions罗列所有的函数
    你会发现这些函数名与mysql的很相近,绝大多数相同的,
    可通过describe function functionName 查看函数使用方法

    hive支持的数据类型很简单就int,string等原子类型, 连日期时间类型也不支持,

    但通过to_date unix_timestamp date_diff date_add date_sub等函数就能完成mysql同样的时间日期复杂操作

    分区
    hive与mysql分区有些区别,mysql分区是用表结构中的字段来分区(range,list,hash等),而hive不同,他需要手工指定分区列,这个列是独立于表结构,但属于表中一列,在加载数据时手动指定分区

    试用:
    create table mytest(id int,name string ,regtime string) PARTITIONED by (ds string) row format delimited fields terminated by ‘\t’ stored as textfile ;

    创建一个数据文件
    1       sawenlee        2011-07-28 22:23:12
    2       tonylee 2011-08-03 22:24:21
    3       nick    2011-08-02 6:2:43

    执行
    LOAD DATA LOCAL INPATH ‘../data/test.txt’ OVERWRITE INTO TABLE mytest  PARTITION (ds=’2011-08-02′);

    LOAD DATA LOCAL INPATH ‘../data/test.txt’ OVERWRITE INTO TABLE mytest  PARTITION (ds=’2011-08-03′);

    再看hive文件结构

    如果执行一个查询,hive会将其转换成map reduce在hadoop上执行(select * from mytest除外)

    select * from mytest where to_date(regtime) >to_date(’2011-8-1′);

    项目地址:http://code.google.com/p/newrsslib4j/

    源码下载:svn checkout http://newrsslib4j.googlecode.com/svn/trunk/ newrsslib4j-read-only

    下载jar包:   http://code.google.com/p/newrsslib4j/downloads/list

    描述:在rsslib4j源码基础上,保持外接口不变,添加了rss字节流编码探测及内部编码转换,理论上支持所有的编码,组件使用较原版更健壮、更稳定


    change log

    #1,引入了mozilla的jchardet包,作为组件一部分,用于探测rss字节流编码,新增了一辅助类Chaset.java 提供了几个静态编码探测方法:
    String guess(URL url);
    String guess(String path)
    String guess(InputStream in)


    #2,引入UnicodeReader替换原有的InputStreamReader,不用InputStreamReader的 原因在于某些UTF-8编码开始会带有BOM (Byte Order Mark) ;导致解析xml失败:Content is not allowed in prolog. 这是jdk1.5的bug,1.6已修复;在sun的buglist里发现了这个问题,并找到了UnicodeReader


    #3,改造RSSParser解析类,新加一个类属性 private InputSource is; 替换原有的InputStream,因原有没有考虑国际化编码问题,而InputSource可以Reader构造产生,改造完如下:
    /**
    * Set rss resource by URL
    * @param ur the remote url
    * @throws RSSException
    */
    public void setXmlResource(URL ur) throws RSSException{
    try{

    URLConnection con = u.openConnection();
    con.setReadTimeout(10000);
    String charset = Charset.guess(ur);
    is = new InputSource (new UnicodeReader(con.getInputStream(),charset));
    if (con.getContentLength() == -1 && is == null){
    this.fixZeroLength();
    }
    }catch(IOException e){
    throw new RSSException(“RSSParser::setXmlResource fails: “+e.getMessage());
    }
    }


    user guide
    代码片段:
    URL url = new URL(“http://cn.engadget.com/rss.xml”);
    RSSHandler handler = new RSSHandler();   RSSParser.parseXmlFile(url, handler, false);
    RSSChannel ch = handler.getRSSChannel();
    System.out.println(ch.toString());
    List<RSSItem> lst = handler.getRSSChannel().getItems();
    for (int j = 0; j < lst.size(); j++) {
    RSSItem itm = lst.get(j);
    System.out.println(itm.toString());
    }

    准备

    1. jdk1.6及以上
    2. cygwin
    3. eclipse3.X
    4. hadoop-0.20.2.tar.gz
    5. 参见hadoop分布式集群搭建一文

    cygwin安装
    进入cygwin首页,点击setup.exe
    在线安装,选择一个镜像点直接下一步;如果安装不成功,则换一个镜像

    默认的cygwin安装是不带openssh的以及vi工具的;前者是hadoop环境必备的,后者则用来编辑配置文件

    可以重新再点击setup.exe,进入到软件列表里,在查询框分别输入openssh 、vi
    点击条目变成install,而非skip ,下一步即可实现在线安装


    配置sshd
    $ ssh-keygen   一直按回车直到执行结束

    $ cat ~/.ssh/id_rsa.pub >>authorized_keys
    执行ssh localhost还需要密码的话,就分别执行chmod 755 authorized_keys


    安装hadoop
    将hadoop-0.20.2.tar.gz拷贝到CYGWIN_HOME/home/USER_NAME/下
    $ tar -zxvf hadoop-0.20.2.tar.gz
    $ mv hadoop-0.20.2 hadoop
    $ cd hadoop/conf
    $ vi hadoop-env.sh  设置JAVA_HOME 如果不设置则无法启动hadoop

    $ vi core-site.xml
    内容修改为:
    <property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:9770</value>
    </property>

    $ vi mapred-site.xml    我的cygwin_home是c:\cygwin 用户名是sawenlee
    内容修改为
    <property>
    <name>mapred.job.tracker</name>
    <value>localhost:9771</value>
    </property>
    <property>
    <name>mapred.system.dir</name>
    <value>C:\cygwin\home\sawenlee\hadoop\system\mapred.system.dir</value>
    </property>
    <property>
    <name>mapred.local.dir</name>
    <value>C:\cygwin\home\sawenlee\hadoop\data\mapred.local.dir</value>
    </property>
    <property>
    <name>mapred.child.tmp</name>
    <value>C:\cygwin\home\sawenlee\hadoop\data\temp</value>
    </property>

    $ vi hdfs-site.xml
    内容修改为
    <property>
    <name>dfs.name.dir</name>
    <value>C:\cygwin\home\sawenlee\hadoop\data\dfs.name.dir</value>
    </property>
    <property>
    <name>dfs.data.dir</name>
    <value>C:\cygwin\home\sawenlee\hadoop\data\dfs.data.dir</value>
    </property>
    <property>
    <name>dfs.permissions</name>
    <value>false</value>
    </property>
    <property>
    <name>dfs.replication</name>
    <value>1</value>
    </property>


    启动hadoop服务
    $ bin/hadoop namenode -format  #格式化namenode
    $ bin/start-all.sh  启动namenode datanode jobtracker tasktracker等


    配置eclipse插件
    将hadoop目录下的contrib/eclipse-plugin.jar拷贝到eclipse安装目录的plugins下
    重新启动eclipse即可看到右上角视图中多了一个map/reduce视角

    配置hadoop_home
    window–>preferences–>map/reduce设置hadoop安装路径,必须与服务配置一致,不然会产生意料不到的问题

    配置hdfs location
    在map/reduce视图下,new hadoop location…
    如下图配置: 注意第一个端口是在core-site.xml中配置的,第二个是在mapred-site.xml配置的,根据实际情况填写

    如果配置成功可以直接浏览到hdfs上的文件,如下图


    运行本地测试程序
    new project—>map/reduce project —>new class

    public class HdfsCat {

    /**
    * @param args
    * @throws IOException
    */
    public static void main(String[] args) throws IOException {
    String uri = “hdfs://localhost:9770/tmp/wordcount/test.txt”;
    Configuration cnf = new Configuration();
    FileSystem fs = FileSystem.get(URI.create(uri),cnf);
    InputStream in = null;
    try {
    in = fs.open(new Path(uri));
    IOUtils.copyBytes(in, System.out, 4096,false);
    }finally{
    IOUtils.closeStream(in);
    }
    }
    }

    直接run,如果没有出错,在控制台看到文件内容了,那么恭喜你,本地调试环境搭建成功了

    今天无意间发现开发服务器磁盘空间利用近100%,结合df & du查找出了罪魁祸首是mysql的数据文件和日志文件占用过多磁盘如图

    ibdata1占用了35G,mysql-bin.****占用近20G;而开发服务器是非主从架构,不存在日志复制,数据同步机制的。

    所以第一步可以把二进制文件清理掉

    以管理员身份登录mysql

    执行RESET MASTER清除所有的二进制日志

    另外还可以有针对性的删除
    PURGE MASTER LOGS TO & PURGE MASTER LOGS BEFORE
    执行PURGE MASTER LOGS TO ‘mysql-bin.******’命令,是单独删除日志文件
    执行PURGE MASTER LOGS BEFORE ‘yyyy-mm-dd hh:mm:ss’命令,是将在’yyyy-mm-dd hh:mm:ss’时间之前的所有日志进行删除

     

    如果存在主从同步,设置二进制日志文件失效时间可有效防止磁盘空间无止境的被占用

    expire_logs_days=3 这样日志文件只保留3天,如果设置0则代表日志文件永不失效

     

     

     

     

     

    ibdata1数据文件瘦身

    在网上查找了相关资料,ibdata1是存放innodb引擎数据和索引的文件,因开发服务器参数设置不当,所有数据库数据及索引都存放在一个文件,而且这个文件有个特点是:不能通过mysql命令缩小,删除或者drop数据(表)同样不会变小,但新增数据可重复利用空间;

    如果给ibdata1瘦身就只能先将库结构及数据dump备份成文件,然后drop掉所有的库,并删除掉ibdata1,利用mysql将之前备份的文件重建数据库

    如果采用独立表空间则可以避免这个问题,设置方式;此法有风险,请在备用机上测试OK后再尝试

    在my.cnf中的innodb块新增一行配置

    innodb_file_per_table

    重启server后,今后新建的innodb引擎表都会独立一个文件以table_name.ibd文件存在每个库数据文件夹下。

    准备

    • nginx-0.8.x
    • pcre-8.10
    • zlib-1.2.5

    并解压到/opt/soft目录下


    准备nginx用户,并加入到www组中:

    #追加一个www组
    groupadd -f www 

    #追加一个nginx用户
    useradd -s /sbin/nologin -g www nginx

    编译nginx:以下每个参数看着是- 实际是两个横线,要替换下

    ./configure –prefix=/usr/local/nginx \ 

    –user=nginx –group=www \

    –with-pcre=/opt/soft/pcre-8.10 \

    –with-zlib=/opt/soft/zlib-1.2.5 \

    –with-http_stub_status_module \

    –without-http_fastcgi_module \

    –without-http_memcached_module \

    –without-http_map_module \

    –without-http_geo_module \

    –without-http_autoindex_module


    make;make install

    #编译启动文件
    vi /etc/init.d/nginx

    将下述内容拷贝其中:

    #!/bin/bash
    # v.0.0.1
    # create by jackbillow at 2007.10.15
    # nginx – This shell script takes care of starting and stopping nginx.
    #
    # chkconfig: – 60 50
    # description: nginx [engine x] is light http web/proxy server
    # that answers incoming ftp service requests.
    # processname: nginx
    # config: /etc/nginx.conf
    # 目录需要替换
    nginx_path=”/usr/local/nginx”
    nginx_pid=”/usr/local/nginx/nginx.pid” 

    # Source function library.
    . /etc/rc.d/init.d/functions

    # Source networking configuration.
    . /etc/sysconfig/network

    # Check that networking is up.
    [ ${NETWORKING} = "no" ] && exit 0
    [ -x $nginx_path/sbin/nginx ] || exit 0
    RETVAL=0
    prog=”nginx”

    start() {
    # Start daemons.
    if [ -e $nginx_pid -a ! -z $nginx_pid ];then
    echo “nginx already running….”
    exit 1
    fi
    if [ -e $nginx_path/conf/nginx.conf ];then
    echo -n $”Starting $prog: ”
    $nginx_path/sbin/nginx -c $nginx_path/conf/nginx.conf &
    RETVAL=$?
    [ $RETVAL -eq 0 ] &&
    { touch /var/lock/subsys/$prog success $”$prog” }

    echo
    else
    RETVAL=1
    fi
    return $RETVAL
    }
    # Stop daemons.
    stop() {
    echo -n $”Stopping $prog: ”
    killproc -d 10 $nigx_path/sbin/nginx
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f $nginx_pid /var/lock/subsys/$prog
    }
    # See how we were called.
    case “$1″ in
    start)
    start
    ;;
    stop)
    stop
    ;;
    reconfigure)
    stop
    start
    ;;
    status)
    status $prog
    RETVAL=$?
    ;;
    *)
    echo $”Usage: $0
    {start |stop |reconfigure |status}


    exit 1
    esac
    exit $RETVAL


    #追加系统服务
    chkconfig –add /etc/init.d/nginx


    #分配执行权限
    chmod +x /etc/init.d/nginx


    #启动nginx
    service nginx start


    #停止nginx
    service nginx stop


    #重启nginx
    service nginx reconfigure


    #查看nginx状态
    service nginx status

     

    这次完全是奔着活动主题去的——当下火热的nosql,云计算平台的解决方案

    活动地点是在中关村某咖啡店,首先是签到领取t-shirt,进入会场演讲者steven早已就位,看到首页PPT投影在屏幕上时就已明白,T-shirt不是白送的,饮料也不是白喝的,演讲者Steven是来推广他家产品的。

    废话少说,直奔主题!

    couchbase有多款产品: couchbase server  &  cousebase single server & couchbase mobile

    couchbase server是这次分享的主角,毕竟是云计算的解决方案定位的主题

    couchbase server有以下特点:

    1,A distributed key-value NoSQL database——schema-less, auto-sharding, high-performance

    2,Horizontally scalable——可动态增删节点(Zero downtime topology change),通过界面操作即可,系统会自动rebalance节点数据

    3,Support hadoop integration——要做大量数据统计分析时可通过flume&sqoop将数据从couchbase迁移到hdfs

    4,Easy management and monitoring——完善友好的监控系统(可通过后台监测ops、内存、硬盘、网络等指标)

    couchbase架构

    moxi为分布式代理,通过key查找它的value位置完全由它来决定,相当于memcache客户端的分布式hash算法,couchbase 集成了memcachd充当缓存,它完全可以memcached模式运行,数据就完全存储在内存中,不会持久化到磁盘上。


    数据写入流程

    rebalance机制——如何能zero downtime topology change,仅仅是在节点扩展时,迁移需要迁移的数据,如下图node1&node2中仅仅迁移了多余的两组数据,所以速度还是非常快的

    这仅仅是本次会议总结,今后有机会再测试下它的性能;附上一张现场讨论PP

    couchbase官方网站:http://www.couchbase.com/products-and-services/overview

    培训文档点这里下载