My Octopress Blog

life and I

Twitter Storm

| Comments

简介

Twitter Storm是Twitter开源的一个实时流数据处理框架,主要基于Java,部分可用 python。原来是BackType开发的,后被Twitter收购,整理后开源。主要用于下面三个领域

  1. 信息流处理(stream processing): 处理实时数据和更新数据库
  2. 连续计算(continuous computation): 可以连续查询并反馈给用户
  3. 分布式远程过程调用(distributed rpc): 处理密集数据。

特点如下

  1. 编程模型类似mapreduce,简化复杂性
  2. 使用各种语言,默认支持clojure, java, ruby, python。支持其他语言需要实现storm的通信协议
  3. 容错性。管理工作进程和节点的故障
  4. 水平扩展。计算在多线程,进程和服务器间进行
  5. 可靠消息处理。storm保证每个消息至少被完整处理一次
  6. 快速。 使用zeromq为底层消息队列
  7. 本地模式。用于快速开发和调试

storm-start

编译及安装

jdk

首先需要安装jdk支持否则会提示缺少tools.jar,需要注意的是要安装jdk6,jdk7编译 会有问题。具体步骤见install jdk on ubuntu

注意如果先安装jdk,然后安装maven2的话,需要重新设置下jdk版本,具体见上面的安装

twitter4j

然后去下载twitter4j,否则安装时会 提示缺少这个库支持,而且也下载不来,应该是被墙了。

在编译twitter4j时,利用其文件夹内的package.sh文件。只有twitter-core编译成功 其他的没有库支持,而且也下不来,需要首先安装twitter-core

下载最新的jdk6进行编译的话,缺少json包支持,需要在twitter4j-core文件夹中的 pom.xml中添加json包依赖见maven2 json

需要忽略test进行编译打包,首先完成core的编译,然后安装

1
2
3
4
5
$cd  twitter4j-core
$mvn compile
$mvn package -Dmaven.test.skip=true
$mvn install:install-file -DgroupId=org.twitter4j -DartifactId=twitter4j-core -Dversion=2.2.6-SNAPSHOT -Dpackaging=jar -Dfile=target/twitter4j-core-2.2.6-SNAPSHOT.jar
$cd ..

然后编译安装twitter-async

1
2
3
4
5
$cd twitter4j-async
$mvn compile
$mvn package -Dmaven.test.skip=true
$mvn install:install-file -DgroupId=org.twitter4j -DartifactId=twitter4j-async -Dversion=2.2.6-SNAPSHOT -Dpackaging=jar -Dfile=target/twitter4j-async-2.2.6-SNAPSHOT.jar
$cd ..

最后编译安装twitter-stream

1
2
3
4
5
$cd twitter4j-stream
$mvn compile
$mvn package -Dmaven.test.skip=true
$mvn install:install-file -DgroupId=org.twitter4j -DartifactId=twitter4j-stream -Dversion=2.2.6-SNAPSHOT -Dpackaging=jar -Dfile=target/twitter4j-stream-2.2.6-SNAPSHOT.jar
$cd ..

storm-start

利用maven进行编译测试

1
mvn -f m2-pom.xml compile exec:java -Dexec.classpathScope=compile -Dexec.mainClass=storm.starter.WordCountTopology

打包

1
mvn -f m2-pom.xml package

注:如果需要在单机模式下运行打包内的文件,需要首先安装storm的release版本 然后运行

1
storm jar target/storm-starter-0.0.1-SNAPSHOT-jar-with-dependencies.jar storm.starter.WordCountTopology

安装storm

依赖

build-essential

1
sudo apt-get install build-essential

zookeeper

1
2
3
4
5
 wget http://ftp.meisei-u.ac.jp/mirror/apache/dist//zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz
 tar zxf zookeeper-3.3.3.tar.gz
 cp -R zookeeper-3.3.3 /usr/local/
 ln -s /usr/local/zookeeper-3.3.3/ /usr/local/zookeeper
 vi ~./bashrc (设置ZOOKEEPER_HOME和ZOOKEEPER_HOME/bin)

编辑/etc/enviroment,添加

1
2
ZOOKEEPER_HOME=/usr/loacl/zookeeper
PATH="$PATH:$ZOOKEEPER_HOME/bin"

设置配置文件

1
2
3
 cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper/conf/zoo.cfg (用zoo_sample.cfg制作$ZOOKEEPER_HOME/conf/zoo.cfg)
 sudo mkdir /tmp/zookeeper
 sudo mkdir /var/log/zookeeper

好的,zookeeper的单机安装已经完成了。

zeromq

1
2
3
4
5
6
7
 wget http://download.zeromq.org/historic/zeromq-2.1.7.tar.gz
 tar zxf zeromq-2.1.7.tar.gz
 cd zeromq-2.1.7
 ./configure
 make
 make install
 sudo ldconfig (更新LD_LIBRARY_PATH)

./configure时会遇到uuid

jzmq

1
2
3
4
5
6
7
8
9
 cd jzmq
 ./autogen.sh
 ./configure
 touch src/classdist_noinst.stamp
 cd src/org/zeromq/
 javac *.java
 cd ../../../
 make
 sudo make install

需要安装pkg-config, libtool, automake

需要创建classdist_noinst.stamp后编译java文件否则会报错

1
`classdist_noinst.stamp', needed by `org/zeromq/ZMQ.class'.  Stop

完成后设置PATH

参考

Twitter Storm:What & Why?

Twitter Storm 实时数据处理框架分析总结

Twitter Storm 在生产集群运行拓扑

Twitter Storm blog 参考

blog one

tter storm 配置项

storm-starter

storm

Twitter Storm 安装实战

安装twitter storm集群组件ZeroMQ,jzmq时遇到的一系列问题

taobaoer blog

Apache Kafka 介绍

| Comments

来源

此项目最开始由Linkedln开发并开源的一个消息系统。Linkdeln将其作为 可读写的流以及服务状态的数据管道。对于一个网站来说,读写流 经常用来记录页面浏览信息,展示信息以及搜素信息,这些信息一般由日志 系统进行记录。服务状态包括当前机器的cpu, IO, 请求时间, 服务日志等。 近年来,服务状态日益成为衡量网站质量的标志。

使用读写流以及服务状态的例子

  • 消息广播(News feed) 朋友活动的广播
  • 用户评分以及相关性计算
  • 安全:需要可以进行监测恶意攻击,平衡集群负载等操作
  • 监控
  • 报表以及离线数据处理:hadoop

活跃数据特性

大流量的数据活跃无法确定大小。传统的日志方式是一种离线的处理方式 比如离线的报告和压缩。对于实时系统,这种方式时延就泰高了。现有的消息队列系统 处理周期。kafka作为一个队列系统可以分别处理离线以及实时的问题。

linkdedln的模块结构

一个kafka的队列系统可以对应于多个模块的数据处理。还可以利用其进行不同数据中心的 数据备份。

kafka集群并不是在数据中心中集中进行部署并提供服务,而是根据数据流拓扑部署多个 集群,不同集群间通过同步来进行数据流处理,其中镜像集群只是源集群的一个消费者。 下面的图示表示了这个过程

kafka设计

  • kafka为一般情况下的持久化消息队列系统
  • 设计约束主要考量吞吐量而不是功能
  • 消息处理模块记录所处理消息的状态,而不是消息提供模块
  • kafka被设计为分布式部署,其中消息的生产者,代理者和消费者可以分布于整个集群

基础

消息是模块间通信的基础单元,消息被发布到代理不同主题的服务器上,某些消费模块 订阅该主题,那么所有被发布的消息都被订阅该主题的消费者收到。

kafka的分布式方案对于生产者和代理者来说比较明晰,但是对于消费者,需要一个特别的 设置和支持。消费者组的概念可以类似于JMS中的队列以及主题,这里的消费者组 可以作为一个逻辑上的单一消费者出现在集群中。对于队列,可以把所有的消费者 作为一个组,而将不同的消费者组成不同的组则对应了主题。一般的情况是根据 不同的主题分为不同的逻辑组,逻辑组作为一个单独的对象出现在集群中。kafka的一个 额外特性是在大量的数据下,不论一个主题内有多少消费者,一个消息只存储一次。

消息持久化和缓存

Kafka的持久化和缓存依赖于文件系统。对于硬盘来说,顺序读写的性能是随机读写性能 的10000倍,某些情况下顺序访问硬盘比随机访问内存要快。

现代操作系统都会为硬盘申请内存作为缓存。操作系统会倾向于将所有空闲的内存 分配给硬盘作为缓存,虽然这样会造成内存重新申请的性能损失。硬盘通过该缓冲区进行 读写,这个特性除非用直接的I/O操作,否则不会轻易被关闭。所以,即使一个进程缓存了 所有的数据,该数据也可能被复制进系统页缓存中,这样造成所有的东西被存储了2次

另外,基于JVM的应用对于内存的使用存在两个问题

  1. 对象使用内存很高基本两倍于对象存储的内存
  2. 在堆内数据增长的时候,垃圾回收机制比较简单和消耗性能

由于上面两点,利用文件系统缓存机制要优于直接利用内存缓存或类似机制。因此 kafka至少保持可用内存的两倍大小的缓存,如果需要存储压缩数据,则变成4倍大小 因此,对于一个32GB内存的机器,kafka会保持28-30GB的缓存,而不需要担心GC影响。 另外,一旦服务重启,这个缓存可以快速的重新载入,而进程内缓存需要在内存中重新申请 或者由代码进行初始化。所以这种机制简化了代码逻辑,对于内存和文件系统的同步 由操作系统完成。

基于以上,这种设计非常简单:不是在内存中保存数据,然后需要的时候flush进硬盘 ,而是反过来,首先将所有数据写入文件系统的一个持久化日志中而不是由进程调用 flush数据操作。这意味着只要将数据写入内核页缓存中,然后给系统一个配置,多长 时间或者多大数据后将数据flush进硬盘中即可。

恒定的时间消耗

一般来说消息系统的元数据都是BTree存储的,虽然其可操作性强,时间开销是O(logN). 但是结合硬盘操作后,随机查找增多造成性能损耗严重。而日志系统的读取是顺序, 写入是直接在文件后进行添加,虽然比BTree没有更好的操作性,但是时间开销是O(1) 的,而且读取不会锁住写入操作或者彼此加锁。这样设计的一个显著优势是不再受数据大小的限制。 这样可以保存数据很长的时间,而不是一旦消息被分发就会被删除。

效率优化手段

假设消息量较大,但是对于每个发布的消息而言,消费的次数要大于生成的次数,因此 优化的手段在消费者更加有效。

两个影响性能的部分为

  • 大量的网络请求
  • 多余的数据拷贝

对于网络请求,根据消息特性进行分组,可以将同组消息打包为”message set”,每次 可以将多个消息打包后发送,而不是单独发送每个消息。对于MessageSet,接口简单 一般不需要进行序列化和反序列化

消息日志被broker保存其硬盘上。因此,即使单个字节的消息也可以被不同的brokeer和 consumer共享。

现代unix系统可以支持代码直接将页面缓存的数据直接发送给网络缓存,减少中间拷贝 次数。Linux中利用sendfile系统调用完成这个功能,Java提供了标准库调用FileChannel.transferTo 接口

一般来说对于通过socket发送系统中的数据需要通过以下几个步骤

  1. 内核空间上,硬盘读取到页面缓存
  2. 用户空间读取内核空间的数据
  3. 在将数据从用户空间写入到内核空间的socket缓存
  4. 系统将socket缓存中的数据拷贝到NIC缓存中

需要4此拷贝,2次系统调用。利用sendfile,可以直接将页面缓存拷贝到网络中, 因此只有第4步拷贝到NIC缓存中

对于同个主题的多个consumer,利用zero-copy技术,数据只需要拷贝到页面缓存中 一次,并且对于多个网络输出进行复用,因此速度基本可达网络硬件的上限。

端到端的压缩

某些时候,系统瓶颈不再于cpu而是网络能力。而由用户简单的将消息压缩后传送给 消息系统无法降低消息间的冗余,更有效的消息压缩应该是将一组消息进行压缩后传输, 更理想的是端到端的方式,数据传输前被压缩后通过producer传输给server,server 不解压直接传送给cosumer,然后由consumer进行解压。

kafka支持递归的消息集合。一组消息被打包后传输给server,然后这组消息被传输给 所有的consumer进行解压后处理。

消费者状态

分布式

生产者

支持hadoop和其他数据载入

实现细节

API设计

网络层设计

消息设计及格式

日志

分布式

#

Zikpin Intro

| Comments

简介

Zipkin是一个分布式的追踪系统,可以通过该系统获取各个服务的时间数据。Twitter用 它来管理信息收集以及查询服务组件。它的思想来源于Google Dapper

对一个分布式系统进行跟踪监控的原因在于我们可以获取系统服务的深层次数据,比如 某个服务的响应时间,根据这点可以判断当前分布式系统的性能瓶颈以及其他信息。Zikpin 获取这些信息后通过浏览器显示在web上

其体系结构如下

每个被追踪的消息在系统中传送时都带了一个追踪标识,zipkin通过该标识在追踪系统 中标记信息,判断时间。所有带有追踪标识的消息在被服务端传送出去时通过工具库将 该消息传送给zipkin系统。

{ % img https://github.com/twitter/zipkin/raw/master/doc/architecture-1.png % }

组件

Finagle

这使一个基于JVM的异步网络框架,通过它可以创建异步RPC,任何基于JVM的语言都 可以用它来创建客户端/服务端

Frinagle在twitter中被广泛使用。可以在其上添加追踪功能,目前客户端和服务端均 支持Trift和HTTP协议,缓存部分只支持Memcache和Redis(So far we have client/server support for Thrift and HTTP as well as client only support for Memcache and Redis.)

初始化一个finagle server并绑定追踪服务

1
2
3
4
5
6
ServerBuilder()
  .codec(ThriftServerFramedCodec())
    .bindTo(serverAddr)
    .name("servicename")
      .tracerFactory(ZipkinTracer())
        .build(new SomeService.FinagledService(queryService, new TBinaryProtocol.Factory()))

初始化一个客户端类似上面的操作,一旦指定Zipkin为追踪服务,那么请求在开始和 结束的时候被自动追踪,相应的服务和机器也会被同时记录。

可以自定义添加更多的追踪信息

1
Trace.record("starting that extremely expensive computation")

除了字符串也可以添加key-value信息

1
Trace.recordBinary("http.response.code", "500")

Ruby Thrift

利用一个gem追踪请求,可以用里面的RackHandler生成id,并通知追踪系统该id。下面 是一个ruby thrift client的例子

1
2
3
client = ThriftClient.new(SomeService::Client, "127.0.0.1:1234")
client_id = FinagleThrift::ClientId.new(:name => "service_example.sample_environment")
FinagleThrift.enable_tracing!(client, client_id), "service_name")

Querulous

是一个一个SQL的接口库,基于Scala实现

Cassie

是一个Finagle内部的基于Cassandra client库的实现

1
cluster.keyspace(keyspace).tracerFactory(ZipkinTracer())

Transport

利用Scribe作为传输模块,利用该模块可以将服务的追踪信息传输给zipkin和hadoop。

Scribe已经停止开发了,是否有替换?

Zipkin collector daemon

信息收集器,一旦追踪信息传送到收集器,该模块会判断其有效性,存储并索引它。

Storage

存储模块,现在是利用Cassandra实现。可以选择不同的存储方式

比如HBase?

Zipkin query daemon

查询模块,通过简单的Trift api查找追踪存储后的信息

UI

显示追踪信息,该模块是一个利用D3的Rails应用

模块间关系如下:

安装配置

Cassandra

利用下面的命令链接当前工程
```bash
bin/cassandra-cli -host localhost -port 9160 -f zipkin-server/src/schema/cassandra-schema.txt
```

Zookeeper

Scribe

Scribe配置如下

```xml
<store>
  category=zipkin
    type=network
      remote_host=123.123.123.123
        remote_port=9410
          use_conn_pool=yes
            default_max_msg_before_reconnect=50000
              allowable_delta_before_reconnect=12500
                must_succeed=no
                </store>
```

Zipkin server

1
2
3
4
5
6
7
8
9
10
11
12
git clone https://github.com/twitter/zipkin.git
cd zipkin
cp zipkin-scribe/config/collector-dev.scala zipkin-scribe/config/collector-prod.scala
cp zipkin-server/config/query-dev.scala zipkin-server/config/query-prod.scala
Modify the configs above as needed. Pay particular attention to ZooKeeper and Cassandra server entries.
bin/sbt update package-dist (This downloads SBT 0.11.2 if it doesn't already exist)
scp dist/zipkin*.zip [server]
ssh [server]
unzip zipkin*.zip
mkdir -p /var/log/zipkin
zipkin-scribe/scripts/collector.sh -f zipkin-scribe/config/collector-prod.scala
zipkin-server/scripts/query.sh -f zipkin-server/config/query-prod.scala

Zipkin UI

是一个标准的Rails 3应用

  1. 升级Zookeeper server的配置。用来定位查询器
  2. 发布到何时的Rail 3 server上

zipkin-tracer gem

通过Rack Handler在Rails 应用中添加追踪信息,在 config.ru中

1
2
use ZipkinTracer::RackHandler
  run <YOUR_APPLICATION>

运行一个简单的Hadoop任务

如果设置Scribe存储到Hadoop上,会产生一系列难以操作数据的报告。因此,利用一个 Scalding来写Hadoop任务

  1. 要运行hadooop任务,需要生成一个全包含的jar包

    sbt 'project zipkin-hadoop' compile assemble

  2. 修改scald.rb指向需要运行hadoop任务的机器名

  3. 如果需要,升级scald.rb中的jarfile的版本

  4. 通过scald.rb脚本运行hadoop任务

    bash ./scald.rb --hdfs com.twitter.zipkin.hadoop.[classname] --date yyyy-mm-ddThh:mm yyyy-mm-ddThh:mm --output [dir]

Google论文笔记

Google Dapper是google发表于2010年的一篇关于分布式服务监控以及查询的论文

目的

方式

跟随者

Interview 100 Pro

| Comments

简述

下面是关于程序员面试100题的相关笔记。不全面但是自己可以供参考

题目

题目1

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何 新的结点,只调整指针的指向

方案1 先完成左子树的转换,链接中间节点后,再完成右子树的转换,然后链接中间节点和右子树

方案2 中序遍历

中序遍历的算法

题目2

定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素。要求函数 min、push 以及 pop 的时间复杂度都是 O(1)

解析

方案

题目3

输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个 子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为 O(n)

解析

方案

题目4

题目11

输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于 右子树的结点。用递归和循环两种方法完成树的镜像转换

解析

对于递归,类似递归遍历方式,在递归前交换左右子树;至于非递归,可以用循环可以用一个栈 来模拟递归操作。

题目12

输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印

解析

就是用队列层次遍历

题目13

在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b

解析

简单来说O(n2)的依次比较。可以用哈希。类似的题目,找出相同的字符,相同字符 的次数,出现次数最多的字符。在一个巨大的文件内出现次数最多的k个成员等等

题目14

n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数字(第一个 为当前数字本身,第二个为当前数字的下一个数字) 。当一个数字删除后,从被删除数字的下一个继续删除 第 m 个数字。求出在这个圆圈中剩下的最后一个数字

解析

约瑟夫问题,可以直接用stl::list模拟行为,然后直接操作。或者利用推导完成递归公式。

题目15

关于类中的深浅拷贝问题,需要自定义拷贝构造函数以及重载等号,另外为了避免指针 被外面别的类删除,可以考虑用引用计数的方式

题目16

用最快的方法求fibonacci数列的第 n 项

解析

由于递归会重复计算很多次相同的值,那么可以考虑从0到n的计算,这样可以省去重复的 次数,复杂度是o(n)

可以有利用数学归纳发发现log(n)的算法

题目17

输入一个表示整数的字符串,把该字符串转换成整数并输出。例如输入字符串”345”,则输出整数 345

解析

问题不难,在c/c++ java python中都有现成的方法,但是大都不够严谨全面。

可以考虑用一个全局变量来标识是否输入合法,标准c中的atoi就是这样做的。

题目18

-用两个栈实现队列

解析

一个栈出一个栈入,出栈非空一直出,空则将入栈内的数据导入其中

如何用两个队列实现一个栈,可以考虑n个数先入一个队列,一旦要出的话,将前n-1个都 出队,然后入队进另一个队列。每次操作都如此

题目19

输入一个链表的头结点,反转该链表,并返回反转后链表的头结点

需要保存反转节点的子节点

题目20

如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字 符串二的子串。注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。请编写一个函数, 输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。 例如:输入两个字符串 BDCABA 和 ABCBDAB,字符串 BCBA 和 BDAB 都是是它们的最长公共子串,则 输出它们的长度 4,并打印任意一个子串

解析

经典的动态规划问题。

题目 26

输入一个正数 n,输出所有和为 n 连续正数序列

类似10题

27

输入一棵二元树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度

递归遍历二叉树

28

递归的考察

似乎穷举和动态规划的方式

值得深入思考下

29

输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数 组的后半部分。要求时间复杂度为 O(n)

和快速排序类似,但是这个比较的时候不是比较大小,而是除以2看余数是否为0

值得注意的是结构的安排和算法不同部分的解耦

30

给出如下 CMyString 的声明,要求为该类型添加赋值运算符函数

1
2
3
4
5
6
7
8
9
class CMyString
{
  public:
  CMyString(char* pData = NULL);
  CMyString(const CMyString& str);
  ~CMyString(void);
  private:
  char* m_pData;
};

除了需要注意的4点外,能够更好的设计结构,利用析构函数更好

31

输入一个链表的头结点,从尾到头反过来输出每个结点的值。链表结点定义如下

me:顺序访问,然后用个栈

解析:

可以用递归,也是用栈,但是是在函数层次的栈

32

用 C++设计一个不能被继承的类。

me: 固定类大小,静态类?

解析:

构造和析构私有

利用模板和虚继承

33

给定链表的头指针和一个结点指针,在 O(1)时间删除该结点

me:

1
2
3
4
phead->value=pdelete->value;
ptr = phead;
phead=phead->next;
delete(ptr);

解析:

们需要需要把给定的结点的下一个结点的数据拷 贝到给定的结点中

34

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个 只出现一次的数字。要求时间复杂度是 O(n) ,空间复杂度是 O(1)

me: 类似bit排序,扫描放入,但是空间复杂度是o(n)

解析:

如果一个数组中只有一个出现一次,其他出现两次,连续异或后只剩下出现一次的数字

(me: 首先连续异或,然后用异或后的数字分别异或所有的值能够出现在数组内的两个值就是)

我们在结果数字中找到第一个为 1 的位的位置,记为第 N 位。现在我们以第 N 位是不是 1 为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第 N 位都为 1,而第二个子数组的每个数字的第 N 位都为 0

35

两个单向链表,找出它们的第一个公共结点

me: 组成两个环,一个每次步进1,一个每次步进2,相遇的那一点

可能会遇到后面的公共点

解析:

我们先要分别遍历两个链表得到它们的长度,并求出两个长度之差。在长的 链表上先遍历若干次之后,再同步遍历两个链表,知道找到相同的结点

#

参考

Mongodb权威指南 Notes

| Comments

入门

  • 文档是数据的基本单元
  • 具有javascript shell
  • 单个实例可以容纳多个独立数据库

文档

javascript中文档表现为对象

区分类型且区分大小写

文档中不能有重复的键

集合

集合就是一组文档。

集合是无模式的

MongoDB Simple

| Comments

简介

  • 拓展了关系数据库的功能,比如辅助索引,范围查询以及排序

  • 内置MapReduce的支持

  • 文档丰富,接口友好

  • MongoDB是一个面向文档的数据库。

  • 没有模式

  • 易于扩展

  • 速度快

  • 管理方便

简单安装和运行

  1. 直接下载二进制包
  2. 在根目录创建/data/db/目录
  3. 运行bin/mongod

on Ubuntu

设置GPG key

1
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10

在/etc/apt/sources.list.d/中创建10gen.list添加如下行

1
deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen

然后运行

1
2
sudo apt-get update
sudo apt-get install mongodb-10gen

设置

配置文件在/etc/mongodb.conf

教程

在其官方网站Mongodb上有一个Try it out的教程

Spring入门到精通笔记

| Comments

概述

模块划分

  • 核心是控制反转,通过配置文件完成业务对象间的依赖注入。
  • 提供事物处理功能
  • 简单有效的JDBC应用
  • 强大灵活的Web框架

特点

  • 良好的分层
  • 以IOC为核心,促使开发人员面向接口编程
  • 良好架构设计
  • 代替EJB
  • MVC代替MVC2
  • 和Struts, Hibernate结合

安装

安装Eclipse及插件

下载eclipse安装

Help->Install New Software 添加插件库 http://download.eclipse.org/webtools/repository/indigo/ 然后进行安装

ubuntu安装tomcat

设置eclipse及tomcat

Setting up a Tomcat server in Eclipse

1
2
3
4
5
6
sudo apt-get install tomcat7
cd /usr/share/tomcat7
sudo ln -s /var/lib/tomcat7/conf conf
sudo ln -s /etc/tomcat7/policy.d/03catalina.policy conf/catalina.policy
sudo ln -s /var/log/tomcat7 log
sudo chmod -R 777 /usr/share/tomcat7/conf

Installation

Config with Eclipse

HelloWorld

基础例子

创建工程

创建一个java工程

添加依赖库

需要在build path中添加

  • commons-logging-1.1.1.jar
  • log4j-1.2.16.jar
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.4.jar
  • spring-asm-3.2.0.M1.jar
  • spring-beans-3.2.0.M1.jar
  • spring-context-3.2.0.M1.jar
  • spring-core-3.2.0.M1.jar
  • spring-expression-3.2.0.M1.jar

添加代码

HelloWorld.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Hello;

public class HelloWorld {

  public String msg = null;

  public void setMsg(String s){
      this.msg = s;
  }

  public String getMsg(){
      return msg;
  }
}
TestHello.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Hello;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import Hello.HelloWorld;

public class TestHello {
  public static void main(String[] args) throws Exception{
      ApplicationContext helloContext = new FileSystemXmlApplicationContext(
              "config.xml");
      HelloWorld hw = (HelloWorld)helloContext.getBean("HelloWorld");
      System.out.println(hw.getMsg());
  }

}

配置log4j以及config.xml

log4j.properties
1
2
3
4
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
config.xml
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean id="HelloWorld" class="Hello.HelloWorld">
      <property name="msg">
          <value>HelloWorld</value>
      </property>
  </bean>
</beans>

其中

改写例子

定义接口

HelloInter.java
1
2
3
4
5
package Hello;

public interface HelloInter {
      public String doSalutation();
}

实现EnHello和CnHello

ChHello.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Hello;

public class ChHello implements HelloInter{
  public String msg = null;
  public void setMsg(String msg){
      this.msg = msg;
  }
  public String getMsg(){
      return msg;
  }

  public String doSalutation(){
      return "你好" + this.msg;
  }
}
EnHello.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Hello;

public class EnHello implements HelloInter{
  private String msg = null;
  public void setMsg(String s){
      this.msg = s;
  }
  public String getMsg(){
      return this.msg;
  }
  public String doSalutation(){
      return "Welcome" + this.msg;
  }
}

更新TestHello

TestHello.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package Hello;


import org.springframework.context.ApplicationContext;

public class TestHello {
  public static void main(String[] args) throws Exception{
      ApplicationContext helloContext = new FileSystemXmlApplicationContext(
              "config.xml");
      HelloWorld hw = (HelloWorld)helloContext.getBean("HelloWorld");
      System.out.println(hw.getMsg());

      System.out.println("\n============\n");

      HelloInter ch = (HelloInter)helloContext.getBean("CnHello");
      System.out.println(ch.doSalutation());

      System.out.println("\n============\n");

      HelloInter eh = (HelloInter)helloContext.getBean("EnHello");
      System.out.println(eh.doSalutation());
  }

}

修改config.xml

config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="HelloWorld" class="Hello.HelloWorld">
<property name="msg">
<value>HelloWorld</value>
</property>
</bean>
<bean id="CnHello" class="Hello.ChHello">
<property name="msg" value='嗨'></property></bean>
<bean id="EnHello" class="Hello.EnHello">
<property name="msg" value="Hi"></property></bean>
</beans>