3. Memcached详细解释

流程概述

  1. 数据存储:保存数据A到mc时,需要先分配空间Item给数据A。
  2. 数据查找:对于获取数据,通过Hash表进行查找。
  3. 数据过期:通过LRU队列进行过期处理

数据存储

为了解释是如何分配空间Item的,那么就要先讲一下Mc的整体结构。

Mc声明了一个slabclass_t的结构体类型,一个slabclass_t类型数组slabclass(全局变量)。数组的每一个元素是一个slab链表。每一个slab链表所分配的内存大小不同。

我们在启动的时候就还会看到这个

memcached -p 11211 -m 44m -vv -f1.25
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
....
slab class  12: chunk size      1184 perslab     885
.... 
slab class  41: chunk size    771184 perslab       1
slab class  42: chunk size   1048576 perslab       1

如何分配

  1. 在do_item_alloc中获取item

    1. 首先根据LRU队列,选择过期的item,返回该item,使用该item
    2. 如果都没有过期,那么分配新的slab。实际上就是分配新的page,然后根据chunk size进行内存切割。选择一个item,返回该item。【注意】即使启动参数-m 44M限定的最大内存使用完毕,如果某一个slabclass没有slab,那么依然可以分配一个page,就会出现内存大于44m的情况。在do_slabs_newslab函数中
    3. 如果都没有过期,并且不能够分配新的slab,那么就会强行霸占没有过期的item。返回该item

      有一篇大牛的文章(2009年)中提到了相同的问题。 http://timyang.net/data/Memcached-lru-evictions/

  2. 场景:
    我以下面的方式启动

    memcached -p 11211 -m 44m -vv -f1.25
    

下面的方式写入数据

for (i = 0; i < 10922 * 44m; i++)
{
    set( i, '1', 0); // 写入长度为1,0代表过期时间
}

这样的话44m空间全部用完。当我们再次写入长度为1000的,将会写入到 slab class 12中。但是我们知道44m空间,已经用完,但实际上我们发现slab class 12可以写入。这儿刚好验证了【注意】中的内容

##LRU队列:

上面讲述了如何分配item,那么分配以后的item如何进行管理和查找呢,就需要LRU队列和Hash表。LRU队列管理Item,LRU队列是一个双向链表,个数与subclass的个数相同。同一个subclass的所有item都归同一个LRU队列管理。

在item.c中

static item *heads[LARGEST_ID];
static item *tails[LARGEST_ID];
static crawler crawlers[LARGEST_ID];
static itemstats_t itemstats[LARGEST_ID];
static unsigned int sizes[LARGEST_ID];

通过LRU队列的操作,可以更清楚明白LRU队列的作用:

  1. 插入:插入到LRU队列的头部
  2. 更新:在LRU队列中,排的越靠后就认为越少被使用的item,那么其被淘汰的概率就越大,所以新的item(访问时间新)要排在不那么新的item前面,所以插入在头部是必须的。
    do_item_update就是先把item从LRU队列中删除,再插入LRU队列,更新time字段(time表示最后访问时间)

Hash表

  1. 当item分配并赋值以后,需要注册到LRU队列和Hash表中。注册到Hash表以后,将方便我们进行查询。利用item的数据部分(data字段)和键长(nkey字段)进行hash。Hash表的结构是常见的拉链结构。
  2. Hash表的扩展
    Hash表的长度并不是不变的。当Hash表中的Item数量达到了Hash表长度的1.5倍时,那么就会扩展哈希表的长度,然后重新进行Hash
    由于这一步耗时,是通过专门的线程 迁移线程进行的。
  3. Hash表与Item的关系
    Item在分配以后,会通过do_item_link do_\item_unlink将Item注册到Hash表和LRU队列中

过期失效处理

  1. 一个item在两种情况下会过期失效

    item的expire时间戳到了
    用户使用flush_all将全部item变成过期失效
    
  2. 懒惰删除
    只有在进行get时,才会进行判断,然后进行删除

重要原则:

  1. 按照预定大小,将分配的slab分割成特定长度的块
  2. 分配给某个slab的内存不能给其他slab使用。已经分配出去的slab不会被回收或者重新分配,因为这种原理,也就出现了【注意】里面所描述的情况
  3. item里面不仅仅存放缓存对象的value,还包括key,expire,time,flag等详细信息。其中time表示最后一次访问时间,expire表示过期时间。

场景

场景1:
一开始大量长度为1kb,全部占用,之后存储大量10kb,只有一个slab,那么10kb大量访问,那么就会出现没到过期时间,数据全部失效。

2. Memcache启动及Telnet命令

1. Memcached启动选项

  1. “p:” 小写p,memcached监听的tcp端口。默认端口为11211, 该选项的参数赋值给settings.port
  2. “m:” 小写m。memcached能够使用的最大内存值,默认是64MB。参数单位为MB。该参数赋值给settings.maxbytes
  3. “v” 小写v。输出memcached运行时的一些信息。-v -vv -vvv输出的信息依次增加。该选项会增加settings.verbose的值
  4. “d” 以守护进程的形式运行memcached
  5. “f:” item的扩容因子。默认值为1.25。该选项的参数值可以是小数但必须大于1.0。该选项参数将赋值给settings.factor
  6. “n:” 设置最小的item能存储多少字节的数据。该选项参数赋值给settings.chunk_size.
  7. “C:” 大写C。memcached默认是使用CAS的,本选项是禁用CAS。本选项会将settings.use_cas赋值为false
  8. “B:” memcached支持文本协议和二进制协议。该选项的参数用于指定使用的协议。默认情况下是根据客户端的命令而自动判断(也叫协商),参数只能取auto、binary、ascii这三个字符串值。将参数将赋值给settings.binding_protocol
  9. “I:” 大写i。slab分配器中,每一个页的大小。这个选项的参数是一个数值表示页的大小。默认单位是B也可以在数值后面带K或者M(大小写都行),表示KB和MB。页的大小小于1KB或者大于128MB都是不允许的。不推荐使用该选项。本选项参数会赋值给settings.item_size_max
  10. “P:” 大写P。指定pid文件。存放当前mc进程的pid
  11. “t:” 该选项的参数用于指定worker线程的个数,不建议超过64个。如果不设置该选项默认有4个线程。该参数会赋值给settings.num_threads
  12. “c:” 小写c。最多允许多少个客户端同时在线(这个值不等价于listen函数的第二个参数),该选项和后面的b选项有所不同。 默认值为1024个。该选项参数赋值给settings.maxconns。
  13. “u:” 小写u。当以root用户启动memcached的时候需要指定memcached的所属用户,其他用户启动memcached不需要此选项

举例

memcached -d -p 11211 -P /var/run/memcached.pid -c 4096 -t 4 -m 1024 -u root -v

2. 一些高级telnet命令

stats slabs
查看 memcache的slab class的状态,能够知道数据分布的范围,每个slab有多少页

stats cachedump 1 0
第三个字段是slab的标识
第四个字段表示拉取的该slab下的数据,第四个字段0表示不受限制(但实际上只会拉取1M的数据, 并不会全拉)

3. 基础Memcached命令

Memcached 有 4 种类型的命令:

1. 存储命令(set/add /replace/append/prepend)
指示服务器储存一些由键值标识的 数据。客户端发送一行命令,后面跟着数据区块;然后,客户端等待接收服务器回传 的命令行,指示成功与否。
2. 读取命令(get/bget/gets)指示服务器返回与所给键值相符合的数据(一个请求中右 一个或多个键值)。客户端发送一行命令,包括所有请求的键值;服务器每找到一项内容,都会发送回客户端一行关于这项内容的信息,紧跟着是对应的数据区块;直到服务器以一行“END”回应命令结束。
3. 状态命令(stat)被用于查询服务器的运行状态和其他内部数据。 
4. 其他命令,如 flush_all,version,quit 等。


COMMAND    DESCRIPTION    EXAMPLE
get    Reads a value    get mykey
set    Set a key unconditionally    set mykey 0 60 5
add    Add a new key    add newkey 0 60 5
replace    Overwrite existing key    replace key 0 60 5
append    Append data to existing key    append key 0 60 15
prepend    Prepend data to existing key    prepend key 0 60 15
incr    Increments numerical key value by given number    incr mykey 2
decr    Decrements numerical key value by given number    decr mykey 5
delete    Deletes an existing key    delete mykey
flush_all    Invalidate specific items immediately    flush_all
Invalidate all items in n seconds    flush_all 900
stats    Prints general statistics    stats
Prints memory statistics    stats slabs
Prints memory statistics    stats malloc
Print higher level allocation statistics    stats items
stats detail
stats sizes
Resets statistics    stats reset
version    Prints server version.    version
verbosity    Increases log level    verbosity
quit    Terminate telnet session    quit

stats命令详解

pid    memcache服务器的进程ID
uptime    服务器已经运行的秒数
time    服务器当前的unix时间戳
version    memcache版本
pointer_size    当前操作系统的指针大小(32位系统一般是32bit)
rusage_user    进程的累计用户时间
rusage_system    进程的累计系统时间
curr_items    服务器当前存储的items数量
total_items    从服务器启动以后存储的items总数量
bytes    当前服务器存储items占用的字节数
curr_connections    当前打开着的连接数
total_connections    从服务器启动以后曾经打开过的连接数
connection_structures    服务器分配的连接构造数
cmd_get    get命令(获取)总请求次数
cmd_set    set命令(保存)总请求次数
get_hits    总命中次数
get_misses    总未命中次数
evictions    为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items)
bytes_read    总读取字节数(请求字节数)
bytes_written    总发送字节数(结果字节数)
limit_maxbytes    分配给memcache的内存大小(字节)
threads    当前线程数

参考文章
http://blog.mimvp.com/2015/01/memcache-start-telnet-command-xiangjie/

1. memcache概述

概述

  1. memcached的特征
    memcached 作为高速运行的分布式缓存服务器,具有以下的特点。
    1. 协议简单
    2. 基于 libevent 的事件处理
    3. 内置内存存储方式
    4. memcached 不互相通信的分布式
      mc是分布式缓存服务器,完全取决于客户端的实现

Memcache的内存分配

  1. 基本概念
    1. Page
      分配给Slab的内存空间,默认是 1MB。
      分配给Slab之后根据slab的大小切分成chunk。
    2. Chunk 用于缓存记录的内存空间。
    3. Slab Class:特定大小的Chunk数组
  2. 保存
    memcached 根据收到的数据的大小,选择最适合数据大小的 slab。 memcached 中保存着 slab 内空闲 chunk 的列表,根据该列表选择 chunk, 然后 将数据缓存于其中。
  3. 调优
    使用Growth Factor进行调优,默认是1.25

  4. 小结

    将固定大小的内存(page)分割成各种尺寸的块(chunk)
    把尺寸相同的块分组,叫做slab classes

Memcache的过期

memcached不会释放已分配的内存。记录超时后,客户端就无法再 看见该记录(invisible,透明), 其存储空间即可重复使用。
Lazy Expiration
memcached 内部不会监视记录是否过期,而是在 get 时查看记录的时间戳,检查 记录是否过期。 这种技术被称为 lazy(惰性)expiration。因此,memcached 不会在过期监视上耗费 CPU 时间。

gitflow工作流

概述

一. 现有开发方式

在原有的开发中,我们的工作方式有两种,一是master上直接修改,二是开一个分支feature,开发测试直接合并master。

存在的问题:

  1. 代码不能进行review
  2. master分支不能保持可用状态

二. 引入pull request

我们引入pull request的目的很简单,就是进行code review。code review对比的是两个分支。

接下来,我们将会介绍两种工作方式,我们将采用gitflow这种工作流,为了让大家有个更加清晰的了解,我们先介绍单纯采用分支的工作方式,然后再介绍采用gitflow工作流的方式。

三. 最简单的采用分支的工作方式

最简单的方式,我们所有的开发(包括简单的一次修改和复杂的新功能开发)都是走分支,分支开发完毕以后跟master进行比较,从而进行code review。流程简单如下

simple

1. 从master分支checkout出feature/fa分支
2. 在feature/fa分支进行开发,每个节点代表一次修改和一次commit
3. 将本地的feature/fa 推到远程仓库,从而其他小伙伴能够拉取代码
4. 分支feature/fa开发完毕以后,开始进行code view,我们需要到xxxx..net上创建一个merge request。
    4.1 如果在review中发现代码修改,那么在feature/fa分支进行修改,然后再将feature/fa分支push到远程仓库即可
5. 分支开发完毕,现在切到master分支,在master分支上拉取远程仓库origin的master分支
6. 将feature/fa分支合并到mater分支上。
7. 将master分支推到远程仓库origin的master从而完成开发。

四. 引入gitflow工作流

(一) gitflow的简要介绍

在gitflow中有两个永久存在的分支develop和master分支,有很多临时的功能分支feature,release,hotfix。详细介绍可以看 http://nvie.com/posts/a-successful-git-branching-model/

(二) 我们如何使用gitflow

结合我们项目特点,目前我们使用阉割版的gitflow,不使用它的hotfix和release分支,仅仅使用master,develop,feature三个分支。流程如下:

gitflow

1. 开辟一个feature分支,我们使用gitflow命令,好处就是他默认从develop分支checkout出一个分支
2. 正常的分支开发,每个节点代表依次修改和commit
3. 将本地的feature/fa 推到远程仓库,从而其他小伙伴能够拉取代码
4. 分支feature/fa开发完毕以后,开始进行code view,我们需要到xxxxx..net上创建一个merge request。
    4.1 如果在review中发现代码修改,那么在feature/fa分支进行修改,然后再将feature/fa分支push到远程仓库即可
5. 将feature/fa分支合并到develop分支,并删除feature/fa分支,听着很复杂,实际上只需要执行一条命令 git flow feature finish fa即可
6. 将develop分支推送到远程仓库,之所以这样是为了让小伙伴同步代码
7. 分支开发完毕,现在切到master分支,在master分支上拉取远程仓库origin的master分支
8. 将develop分支合并到mater分支上。
9. 将master分支推到远程仓库origin的master从而完成开发。

四. 受限分支master

  1. 目前存在问题

    到目前为止,我们引入了pull request进行codereview,引入工作流gitflow规范大家的开发流程。但是!但是!master分支依然允许所有的人进行操作,那么可能有人不遵循规则,而对master进行修改和上线。

  2. 解决方法

    通过gitlab,我们对master分支进行保护,即受限分支。只有具有权限的小伙伴才能对远程仓库的master分支进行操作。当然了,你操作你本地的master分支木有问题,但你想向远程的master分支推送,不好意思,你被禁止了。

  3. 引入受限分支以后,开发流程的变化

    在上面描述的流程中,gitflow的7,8,9三步交给具有操作master分支权限的小伙伴来执行。

五 参考文章

http://nvie.com/posts/a-successful-git-branching-model/

svn迁移git-完美保留日志

迁移流程–完美保留日志

  1. 生成用户列表

    svn log --xml | grep author | sort -u | perl -pe 's/.*>(.*?)<.*/$1 = $1 <$1\@compony.suffix>/' > users.txt

  2. 从svn克隆到新的目录

    git svn clone https://your_svn_reposity/project_name/ –authors-file=users.txt –no-metadata -s git_project_name

  3. 从svn仓库拉取文件到新的目录

    cd git_project_name
    git svn fetch

  4. 校验文件是否一致:

    diff -rbB –brief svn_cloudfs git_cloudfs | grep -v .svn

  5. 添加远程仓库

    git remote add origin git@xxxx.net:xxx.git

  6. 将代码上传到git仓库

    git push

zsh基础知识

一. 安装和配置Zshell

  1. 安装

    sudo yum install zsh

  2. 配置
    自动化安装
    curl -L http://install.ohmyz.sh | sh

手动安装

a. git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
b. cp ~/.zshrc ~/.zshrc.orig
c. cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
d. chsh -s /bin/zsh
e. restart zsh

二. Zshell的好处

请直接转到这篇文章
http://blog.jobbole.com/80620/

三. 参考文章

http://blog.jobbole.com/80620/
http://www.unixmen.com/install-oh-zsh-ubuntu-arch-linux-fedora/?utm_source=tuicool&utm_medium=referral

mysql 锁的问题

6.5 锁问题

0. 概述

通过锁定机制可以实现事务的隔离性要求,使得事务可以并发地工作。锁提高了并发,但是却会带来潜在的问题。不过好在因为事务隔离性的要求,锁只会带来三种问题,如果可以防止这三种情况的发生,那将不会产生并发异常。这三种问题分别是脏读(dirty read),不可重复读(Non-repeatable read),更新丢失。

1. 脏读

脏数据是指未提交的数据,如果读到了脏数据,即一个事务可以读到另外一个事务中未提交的数据,则显然违反了数据库的隔离性。脏读指的就是在不同的事务下,当前事务可以读到另外事务未提交的数据,简单来说就是可以读到脏数据。

在下表中,事务的隔离级别由默认的可重复读(repeatable read)变成了未提交读( read uncommitted).SessionB读取了SessionA中没有提交的数据,违反了数据库的隔离性。

step session A sessionB
1 set @@tx_isolation=’read-uncommitted’
2 set @@tx_isolation=’read-uncommitted’
3 start transaction start transaction
4 select mtime from learn2 where id = 9; 9.row mtime = 9000
5 update learn2 set mtime = mtime - 100 where id = 9
6 select * from learn2 where id = 9 mtime = 8900

在MysqlInnoDb中虽然是脏读,但如果在sessionB中执行update learn2 set mtime = mtime - 100 where id = 9;依然需要等待,sessionA中为id=9这一行加锁了

2. 不可重复读

  1. 在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。在第一个书屋的两次读数据之间,由于第二个事务的修改并提交commit以后,那么第一个事务的两次读到的数据就可能不一样,这样在一个事务内两次读到的数据是不一样的情况,称为不可重复读。
  2. 不可重复读和脏读区别
脏读 不可重复读
读取到没有提交的数据 读取到其他事务已经提交的数据
违反了隔离性 违反了一致性

举例

step session A sessionB
1 set @@tx_isolation=’read-committed’
2 set @@tx_isolation=’read-ncommitted’
3 start transaction start transaction
4 select mtime from learn2 where id = 9; ### 9.row mtime = 8900
5 update learn2 set mtime = mtime - 100 where id = 9
6 select * from learn2 where id = 9 #mtime = 999
7 commit;
8 select * from learn2 where id = 9 #mtime = 8800

在会话A step5更新后,会话B step6没有发生脏读现象。但在commit以后,会话B step8得到的mtime与会话B step6的mtime取值不同。

在InnoDB存储引擎中,通过使用Next-Key Lock算法来避免不可重复读的问题。在MySQL官方文档中将不可重复读的问题定义为Phantom Problem即幻像问题。在Next-Key Lock算法下,对于索引的扫描,不仅是锁住扫描到的索引,而且还锁住这些索引覆盖的范围(gap)。因此在这个范围内的插入都是不允许的。这样就避免了另外的事务在这个范围内插入数据导致的不可重复读的问题。因此,InnoDB存储引擎的默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,避免了不可重复读的现象。

3. 更新丢失

case1

step session A sessionB
1 start transaction start transaction
2 select * from learn2 where id = 9; mtime = 9999 select * from learn2 where id = 9 mtime = 9999
3 update learn2 set mtime = mtime - 999 where id = 9
4 update learn2 set mtime = mtime - 100 where id = 9
5 commit
6 commit
7 select * from learn2 where id = 9; mtime = 8900 select * from learn2 where id = 9 mtime = 8900

第3步update操作锁住id=9这一行(排它锁),第4步sessionB更新的时候进行等待,只有第5步commit以后第4步的update才更新成功。
由于排它锁的存在并且update基于是mtime的数据库取值,保证了不会存在丢失更新的问题。但如果update xx set mtime = some_value 这样的操作,那么就会出现丢失更新的现象。

case2

step session A sessionB
1 start transaction start transaction
2 select * from learn2 where id = 9; mtime = 9999 select * from learn2 where id = 9 mtime = 9999
3 update learn2 set mtime = 999 where id = 9
4 update learn2 set mtime = 100 where id = 9
5 commit
6 commit
7 select * from learn2 where id = 9; mtime = 100 select * from learn2 where id = 9 mtime = 100

如何避免这种丢失更新的情况发生呢
case3

step session A sessionB
1 start transaction start transaction
2 select * from learn2 where id = 9 for update; mtime = 9999
3 select * from learn2 where id = 9 for update; # 等待 其真正发生是在sessionA的commit以后
4 一系列操作 一系列操作
5 update learn2 set mtime = 999 where id = 9
4 update learn2 set mtime = 100 where id = 9
5 commit
6 commit
7 select * from learn2 where id = 9; mtime = 100 select * from learn2 where id = 9 mtime = 100

在这个例子中,sessionB的select ..for update操作是在sessionA commit以后才会发生。commit之前,sessionB一直处于等待状态。sessionA提交以后,select的结果是mtime = 999;

在上述的例子中为什么不直接允许UPDATE语句,而首先要进行SELECT…FOR UPDATE的操作。的确,直接使用UPDATE可以避免丢失更新的问题发生。在实际应用中,应用程序可能需要首先检测用户的余额信息,查看是否可以进行转账操作,然后再进行最后的UPDATE操作,因此在SELECT与UPDATE操作之间可能还存在一些其他的SQL操作。

有用的mysql命令

查询隔离级别
SELECT @@global.tx_isolation; 
SELECT @@session.tx_isolation; 
SELECT @@tx_isolation;
设置隔离级别
set @@tx_isolation='read-committed'

参考文章:
http://techlog.cn/article/list/10182853
姜承尧. “MySQL技术内幕:InnoDB存储引擎 第2版”

转义字符

0.概述

转义字符标志着在一个字符序列中出现在它之后的后续几个字符是一种替代解释。

判断某字符是否为转义字符由上下文确定。转义字符标志着转义序列escape sequence开始的那个字符。

转义字符原本是指ASCII的十进制27,16进制1B,8进制033所定义的字符,对应标准键盘的ESC键,老式键盘”Ctrl+[“。

后来将狭义的转义字符的含义引申开来,在各种计算机语言和协议中,标志着一个转义序列开始的那个字符,都叫做Escape character.

在C语言中 \是转义字符。
在Shell语言中 \033是转义字符
在URL协议中 %是转义字符

1. 定义

转义序列通常有两种功能。第一个是编码一个句法上的实体,如设备命令或者无法被字母表直接表示的特殊数据。第二种功能,也叫字符引用,用于表示无法在当前上下文中被键盘录入的字符(如字符串中的回车符),或者在当前上下文中会有不期望的含义的字符(如C语言字符串中的双引号字符”,不能直接出现,必须用转义序列表示

控制字符与转义字符是两个不同的概念。转义字符不属于控制字符;控制字符也不属于转义字符。
大多数ASCII控制字符单独都具有控制功能,因此它们不是转义字符

2. 举例

  1. shell 输出红色hello

    echo -e "\e[0;31mhello\e[0m"
    
  2. shell 将出现WARN这一行绿色字体显示;出现ERR这一行加上红色背景色

    echo "ERRhello" > aa.txt
    echo "WARNdfajo" >> aa.txt
    cat aa.txt | sed -e 's/.*WARN.*/\x1b[0;36m&\x1b[0m/i' -e 's/.*ERR.*/\x1b[93;41m&\x1b[0m/i'
    
  3. url 中转义字符是%。其中%后面跟一个ASCII码,可以在http://www.searchtb.com/wp-content/uploads/2012/04/ascii0.jpg 图中找到该ASCII码对应的字符

    http://www.baidu.com/helo=fw fwe&str=sfa
    该urlurlencode后对应的是
    http%3A%2F%2Fwww.baidu.com%2Fhelo%3Dfw+fwe%26str%3Dsfa
    

Mac 安装storm环境

1. 安装

  1. 获取storm-starter源代码

    git clone https://github.com/nathanmarz/storm-starter.git

  2. cd storm_starter

  3. mvn package

  4. 使用 Intellij

    1. Open File > Import Project… and navigate to the storm-starter directory of your storm clone (e.g. ~/git/storm/examples/storm-starter).
    2. Select Import project from external model, select “Maven”, and click Next.
      In the following screen, enable the checkbox Import Maven projects automatically. Leave all other values at their defaults. Click Next.
    3. Click Next on the following screen about selecting Maven projects to import.
      Select the JDK to be used by IDEA for storm-starter, then click Next.
      At the time of this writing you should use JDK 6.
      It is strongly recommended to use Sun/Oracle JDK 6 rather than OpenJDK 6.
    4. You may now optionally change the name of the project in IDEA. The default name suggested by IDEA is “storm-starter”. Click Finish once you are done

可能出现的问题

  1. org.apache.zookeeper.ClientCnxn - Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect.
    解决方案:
    http://blog.csdn.net/myemail_sl/article/details/11074017
    设置执行参数。在Deault VM Arguments中设置-Djava.net.preferIPv4Stack=true
  2. 如果出现缺少module.xml 那么需要重新导入一次项目即可。
  3. java.lang.NoClassDefFoundError: backtype/storm/topology/IRichSpout….
    http://blog.jobbole.com/88203/ 这篇文章给出了解释。
    解决方案:在pom.xml将storm的scope由provided修改为compile即可。

Mac 安装Hbase环境

1. 安装

  1. 安装brew
  2. 安装Hbase

    brew install hbase 
    

2. 说明

Hbase运行模式分为单机、伪分布式、全分布式三种。我尝试使用单机,但由于zookeeper的原因没有搭建成功,目前使用伪分布式的方式运行。
在Hbase中http://hbase.apache.org/book.html#zookeeper 介绍了Hbase和Zookeeper的关系。

3. 配置修改

  1. 修改hbase-env.sh

    #export HBASE_MANAGES_ZK=true
    

    修改为

    export HBASE_MANAGES_ZK=false
    
  2. 修改hbase-site.xml
    其中hbase.rootdir的value必须跟hadoop中core-site.xml中fs.default.name相同。如果不同,则会引起ERROR: Can't get master address from ZooKeeper; znode data == null

    <configuration>
      <property>
       <name>hbase.rootdir</name>
       <value>hdfs://localhost:9000/hbase</value>
      </property>
      <property>
       <name>hbase.cluster.distributed</name>
       <value>true</value>
      </property>
    </configuration>
    

3. 启动并运行例子

  1. 依次执行下面三个命令
    start-hbase.sh
    可以通过jps查看是否正确运行

    13489 Jps
    9633 QuorumPeerMain
    13315 HMaster
    6597 DataNode
    6838 ResourceManager
    6935 NodeManager
    6505 NameNode
    13419 HRegionServer
    6715 SecondaryNameNode

如果没有QuorumPeerMain 要去看hbase-env.sh中是否设置正确

  1. 运行一个例子
    创建一个名为 test 的表,这个表只有一个 列族 为 cf。可以列出所有的表来检查创建情况,然后插入些值。

    hbase(main):003:0> create ‘test’, ‘cf’
    0 row(s) in 1.2200 seconds
    hbase(main):003:0> list ‘test’
    test
    1 row(s) in 0.0550 seconds
    hbase(main):004:0> put ‘test’, ‘row1’, ‘cf:a’, ‘value1’
    0 row(s) in 0.0560 seconds
    hbase(main):005:0> put ‘test’, ‘row2’, ‘cf:b’, ‘value2’
    0 row(s) in 0.0370 seconds
    hbase(main):006:0> put ‘test’, ‘row3’, ‘cf:c’, ‘value3’
    0 row(s) in 0.0450 seconds
    以上我们分别插入了3行。第一个行key为row1, 列为 cf:a, 值是 value1。HBase中的列是由 列族前缀和列的名字组成的,以冒号间隔。例如这一行的列名就是a.

检查插入情况.

Scan这个表,操作如下

hbase(main):007:0> scan 'test'
ROW        COLUMN+CELL
row1       column=cf:a, timestamp=1288380727188, value=value1
row2       column=cf:b, timestamp=1288380738440, value=value2
row3       column=cf:c, timestamp=1288380747365, value=value3
3 row(s) in 0.0590 seconds

Get一行,操作如下

hbase(main):008:0> get 'test', 'row1'
COLUMN      CELL
cf:a        timestamp=1288380727188, value=value1
1 row(s) in 0.0400 seconds

disable 再 drop 这张表,可以清除你刚刚的操作

hbase(main):012:0> disable 'test'
0 row(s) in 1.0930 seconds
hbase(main):013:0> drop 'test'
0 row(s) in 0.0770 seconds 

关闭shell

hbase(main):014:0> exit

参考文章

  1. http://abloz.com/hbase/book.html#quickstart
  2. http://www.jianshu.com/p/510e1d599123