最近做docker image,编写shell 脚本,遇到以下问题,做个记录

1.问题一:

1
2
3
if [ "${1:0:1}" = '-' ]; then
set -- elasticsearch "$@"
fi

解释:以上if 条件是指第一个参数的第一个字符为-,则符合条件

2.问题二:

1
exec "$@"

解释:exec执行命令

3.问题三:

1
set -- elasticsearch "$@"

解释:set设置环境,这句话的意思其实是将elasticsearch 作为第一个参数补充到”$@”中
例如:
demo.sh

1
2
3
#!/bin/bash
set -- elasticsearch "$@"
echo "$@"

执行脚本

1
bash demo.sh hello truman

输出结果为:elasticsearch hello truman

4.问题四:

1
"$(id -u)"

解释:输出当前shell 环境UID(用户ID)

RediSearch 探索

简介

RediSearch是一个高性能的全文搜索引擎,可作为一个Redis Module 运行在Redis上,是由RedisLabs团队开发的。

特性

  • 多字段全文检索
  • 增量索引无性能损失
  • 文档排序
  • 复杂的子查询 and,or,not
  • 可选查询子句。
  • 基于前缀的搜索
  • 字段权重
  • 自动完成建议(使用模糊前缀建议)
  • 精确词组搜索,基于Slop的搜索
  • 基于Stemming的查询扩展在许多语言(使用Snowball)
  • 支持用于查询扩展和评分的自定义函数(请参阅扩展)。
  • 限制搜索到特定文档字段(最多支持8个字段)。
  • 数字过滤以及范围查找
  • 使用Redis自己的地理命令进行地理过滤
  • 支持任何utf-8编码文本
  • 检索完整的文档内容或只是ids
  • 将现有的HASH键自动索引为文档
  • 使用索引垃圾回收文档删除和更新

入门

安装/运行

1
2
3
4
5
wget https://github.com/RedisLabsModules/RediSearch/archive/v0.19.1.tar.gz
tar xvf v0.19.1.tar.gz
cd RediSearch-0.19.1/src
make all
nohup redis-server --loadmodule ./redisearch.so &

1. 创建索引

1
2
3
127.0.0.1:6379> FT.CREATE myIDs SCHEMA title TEXT WEIGHT 5.0 body TEXT url TEXT
OK

2. 增加文档到该索引

1
2
3
127.0.0.1:6379> FT.ADD myIDs doc1 1.0 FIELDS title "hello world" body "lorem ipsum" url "http://redis.io"
OK

3. 在该索引中搜索

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> ft.search myIDs "hello world" limit 0 10
1) (integer) 1
2) "doc1"
3) 1) "title"
2) "hello world"
3) "body"
4) "lorem ipsum"
5) "url"
6) "http://redis.io"

4. 删除索引

1
2
3
127.0.0.1:6379> ft.drop myIDs
OK

5. 添加并获取自动完成建议

1
2
3
4
5
127.0.0.1:6379> ft.sugadd autocomplete "hello truman" 100
(integer) 1
127.0.0.1:6379> ft.sugget autocomplete "he"
1) "hello truman"

引用

  1. redisearch.io

Redis 运维shell 工具

介绍

在Redis 集群运维过程中,经常需要做一些重复性工作,因为Redis 无中心设计,这就需要在每个节点中执行相同命令,对于这些重复性劳动工作完全可以通过shell处理,降低运维难度,减少工作量,以下是我在工作冲总结的脚本,仅供大家参考。

工具集

1. 集群健康状态检测

新建脚本redis_tool.sh,然后执行

1
sh redis_tool.sh clusterStatus 127.0.0.1 7000

2. 移除fail节点

新建脚本redis_tool.sh,然后执行

1
sh redis_tool.sh forget 127.0.0.1 7000

脚本内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/bin/sh

function clusterStatus(){
instans=`redis-cli -c -h $1 -p $2 cluster nodes|grep -v fail|awk '{print $2}'`
for var in ${instans[@]};
do
echo $var
host=${var%:*}
port=${var#*:}
redis-cli -c -h $host -p $port cluster info |grep cluster_state:fail
done
}

function forget(){
instans=`redis-cli -c -h $1 -p $2 cluster nodes|grep -v fail|awk '{print $2}'`
for var in ${instans[@]};
do
echo $var
host=${var%:*}
port=${var#*:}
failnodes=`redis-cli -c -h $host -p $port cluster nodes|grep fail|awk '{print $1}'`
for nodeid in ${failnodes[@]};
do
echo $nodeid
redis-cli -c -h $host -p $port cluster forget $nodeid
done

done
}

# main start
case $1 in
clusterStatus)
echo "check redis cluster cluster_state..."
clusterStatus $2 $3;
;;
forget)
echo "forget redis fail nodes ..."
forget $2 $3;
;;
*)
echo "Usage: the options [clusterStatus|forget]"
;;
esac

Redis4.0 新特性尝鲜

1.目录结构

  1. 目录
  2. 前言
  3. 环境搭建
    1. 下载
    2. 安装
    3. 集群搭建
  4. 特性尝鲜
    1. 注意事项
    2. 升级内容
    3. 模块系统
    4. PSYNC 2.0
    5. 缓存驱逐策略优化
    6. 非阻塞 DEL 、 FLUSHDB 和 FLUSHALL
    7. 交换数据库
    8. 混合RDBAOF持久化格式
    9. 内存命令
    10. 兼容 NAT 和 Docker
  5. 引用

2. 前言

2017-07-14 redis 4.0 Stable version release,新增了许多新功能,此次专门抽出时间,探索一些功能,把握Redis未来的发展方向,同时积累经验,为未来升级Redis打下坚实基础。学习新的东西,如果不将它记录下来,过上两周,基本上就忘记做过什么了,对知识的掌握不利,以后尽量所有的学习都能产生文字记录,便于自己总结学习各种技术,也能给新人带去一点便利。

3. 环境搭建

安装方式,较之前没有多大变化,还是写一下,便于新手学习。

3.1. 下载

1
2
$ wget http://download.redis.io/releases/redis-4.0.0.tar.gz
$ tar xzf redis-4.0.0.tar.gz

3.2. 编译安装

1
2
$ cd redis-4.0.0
$ make

如果需要将redis-cli,redis-server等相关命令安装到/bin目录下,全局使用的话,可以使用如下命令:

1
$ make install

或者利用软连接实现:

1
2
3
$ make
$ ln -s redis-4.0.0/src/redis-server /bin/redis-server
$ ln -s redis-4.0.0/src/redis-cli /bin/redis-cli

在编译中可能会遇到如下问题:

1
zmalloc.h:50:31: 错误:jemalloc/jemalloc.h:没有那个文件或目录

出现这个问题是libc 并不是默认的 分配器, 默认的是 jemalloc, 因为 jemalloc 被证明 有更少的 fragmentation problems 比libc,关于更详细信息可以查看redis中REAME,md,其中有详细介绍,此处不再细说。

解决办法:

1
make MALLOC=libc

3.3. 新建集群

按照官方指导,搭建3m+3s集群,端口号7000-7005

以下为创建脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/bin/bash
nodes=(7000 7001 7002 7003 7004 7005)
HOME_DIR=`pwd`
function create(){
echo "create"
if [ -d redis_cluster ];then
rm -rf redis_cluster
fi

mkdir redis_cluster
cd redis_cluster

mkdir `echo ${nodes[*]}`

for var in ${nodes[*]}
do
cd $var
touch $var-redis.conf
echo "port" $var >> $var-redis.conf
echo "cluster-enabled yes" >> $var-redis.conf
echo "cluster-config-file nodes.conf" >> $var-redis.conf
echo "cluster-node-timeout 5000" >> $var-redis.conf
echo "appendonly yes" >> $var-redis.conf
echo "daemonize yes" >> $var-redis.conf
echo "pidfile redis.pid" >> $var-redis.conf
cd ../
done
run;
src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

}

function run(){
echo run
for var in ${nodes[*]}
do
cd $HOME_DIR/redis_cluster/$var/
redis-server $var-redis.conf
cd $HOME_DIR/
echo Start redis ports ${var} finish.
done
}
function stop(){
cd $HOME_DIR/redis_cluster/
DIRS=`ls -l | grep "^d" | awk '{print $NF}'`
for d in $DIRS
do
PID=`cat $d/redis.pid`
if [ -n "$PID" ];then
kill -9 $PID
rm -f $d/redis.pid
fi
done
cd $HOME_DIR/
echo Stop redis ports ${DIRS} finish.
}


case $1 in
create)
echo " create redis cluster 锛?000,7001,7002,7003,7004.7005,7006,7007"
create
;;
run)
run
;;
stop)
stop
;;
*)
echo "Usage:[create|run|stop]"
;;
esac

执行

1
sh createCluster.sh create

一路回车即可,注意构建集群需要使用redis-trib.rb,需要额外执行

1
gem install redis

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[bigdata@trumanlab1 redis-4.0.0]$ redis-cli -c -h 127.0.0.1  -p 7000
127.0.0.1:7000> cluster nodes
63e698210378f4fda23c4070bea3b46f93952811 127.0.0.1:7000@17000 myself,master - 0 1500391716000 1 connected 0-5460
4091630217b64ece9a6fa55c26687a10c1f9a8b5 127.0.0.1:7001@17001 master - 0 1500391717501 2 connected 5461-10922
0b23853c3aa4f5b942a6239bc7bca71df36e121c 127.0.0.1:7005@17005 slave 12d05fb7c20bf001759f80cf3f65ad9df4b01af5 0 1500391716498 6 connected
12d05fb7c20bf001759f80cf3f65ad9df4b01af5 127.0.0.1:7002@17002 master - 0 1500391717000 3 connected 10923-16383
2e559b462362a9563f98b398af3984c05e25ef19 127.0.0.1:7003@17003 slave 63e698210378f4fda23c4070bea3b46f93952811 0 1500391716000 4 connected
c4f8e0a95579c772c7506c195b3c7984c73312b4 127.0.0.1:7004@17004 slave 4091630217b64ece9a6fa55c26687a10c1f9a8b5 0 1500391716000 5 connected
127.0.0.1:7000> set a a
-> Redirected to slot [15495] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get a
"a"
127.0.0.1:7002>

4. 特性尝鲜

4.1 注意事项

IMPORTANT: Redis Cluster users, please note that, as specified in the list
of incompatibilities, Redis 4.0 cluster bus protocol is not compatible with
Redis 3.2, so in order to upgrade, a mass reboot of the instances is needed
and rolling upgrades are not possible. This change was needed in order to
add compatibility for Containers/NAT, where the bus port at a fixed offset
was not an acceptable design, so we had to change many things, resulting
in the incompatible protocol.

4.0版本与3.2版本传输协议不兼容,更改该协议的目的是为了实现Containers/NAT
为了升级,需要重启大量节点,无法做到滚动升级。

4.2 升级内容

  • Different replication fixes to PSYNC2, the new 4.0 replication engine.
  • Modules thread safe contexts were introduced. They are an >experimental API right now, but the API is considered to be stable and usable when needed.
  • SLOWLOG now logs the offending client name and address. Note that this is a backward compatibility breakage in case old code assumes that the slowlog entry is composed of exactly three entries.
  • The modules native data types RDB format changed.
  • The AOF check utility is now able to deal with RDB preambles.
  • GEORADIUS_RO and GEORADIUSBYMEMBER_RO variants, not supporting the STORE option, were added in order to allow read-only scaling of such queries.
  • HSET is now variadic, and HMSET is considered deprecated (but will be supported for years to come). Please use HSET in new code.
  • GEORADIUS huge radius (>= ~6000 km) corner cases fixed, certain elements near the edges were not returned.
  • DEBUG DIGEST modules API added.
  • HyperLogLog commands no longer crash on certain input (non HLL) strings.
  • Fixed SLAVEOF inside MULTI/EXEC blocks.
  • Many other minor bug fixes and improvements.

4.3 模块系统

Redis 4.0 发生的最大变化就是加入了模块系统, 这个系统可以让用户通过自己编写的代码来扩展和实现 Redis 本身并不具备的功能, 具体使用方法可以参考 antirez 的博文《Redis Loadable Module System》: http://antirez.com/news/106
因为模块系统是通过高层次 API 实现的, 它与 Redis 内核本身完全分离、互不干扰, 所以用户可以在有需要的情况下才启用这个功能, 以下是 redis.conf 中记载的模块载入方法:

1
2
3
4
5
6
7
################################## MODULES #####################################

# Load modules at startup. If the server is not able to load modules
# it will abort. It is possible to use multiple loadmodule directives.
#
# loadmodule /path/to/my_module.so
# loadmodule /path/to/other_module.so

目前已经有人使用这个功能开发了各种各样的模块, 比如 Redis Labs 开发的一些模块就可以在 http://redismodules.com 看到, 此外 antirez 自己也使用这个功能开发了一个神经网络模块: https://github.com/antirez/neural-redis
模块功能使得用户可以将 Redis 用作基础设施, 并在上面构建更多功能, 这给 Redis 带来了无数新的可能性。

4.4 PSYNC 2.0

新版本的 PSYNC 命令解决了旧版本的 Redis 在复制时的一些不够优化的地方:

  • 在旧版本 Redis 中, 如果一个从服务器在 FAILOVER 之后成为了新的主节点, 那么其他从节点在复制这个新主的时候就必须进行全量复制。 在 Redis 4.0 中, 新主和从服务器在处理这种情况时, 将在条件允许的情况下使用部分复制。
  • 在旧版本 Redis 中, 一个从服务器如果重启了, 那么它就必须与主服务器重新进行全量复制, 在 Redis 4.0 中, 只要条件允许, 主从在处理这种情况时将使用部分复制。

4.5 缓存驱逐策略优化

新添加了 Last Frequently Used 缓存驱逐策略, 具体信息见 antirez 的博文《Random notes on improving the Redis LRU algorithm》: http://antirez.com/news/109
另外 Redis 4.0 还对已有的缓存驱逐策略进行了优化, 使得它们能够更健壮、高效、快速和精确。

4.6 非阻塞 DEL 、 FLUSHDB 和 FLUSHALL

在 Redis 4.0 之前, 用户在使用 DEL 命令删除体积较大的键, 又或者在使用 FLUSHDB 和 FLUSHALL 删除包含大量键的数据库时, 都可能会造成服务器阻塞。
为了解决以上问题, Redis 4.0 新添加了 UNLINK 命令, 这个命令是 DEL 命令的异步版本, 它可以将删除指定键的操作放在后台线程里面执行, 从而尽可能地避免服务器阻塞:

1
2
3
4
5
6
7
8
9
10

127.0.0.1:7002> set a test
OK
127.0.0.1:7002> get a
"test"
127.0.0.1:7002> unlink a
(integer) 1
127.0.0.1:7002> get a
(nil)

因为一些历史原因, 执行同步删除操作的 DEL 命令将会继续保留。
此外, Redis 4.0 中的 FLUSHDB 和 FLUSHALL 这两个命令都新添加了 ASYNC 选项, 带有这个选项的数据库删除操作将在后台线程进行:

1
2
3
4
5
redis> FLUSHDB ASYNC
OK

redis> FLUSHALL ASYNC
OK

4.7 交换数据库

Redis 4.0 对数据库命令的另外一个修改是新增了 SWAPDB 命令, 这个命令可以对指定的两个数据库进行互换: 比如说, 通过执行命令 SWAPDB 0 1 , 我们可以将原来的数据库 0 变成数据库 1 , 而原来的数据库 1 则变成数据库 0 。这种场景是在非集群模式下使用的,在集群模式是不支持切换数据库的。默认所有的节点使用index 0。
以下是一个使用 SWAPDB 的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
redis> SET your_name "aibibang"  -- 在数据库 0 中设置一个键
OK

redis> GET your_name
"aibibang"

redis> SWAPDB 0 1 -- 互换数据库 0 和数据库 1
OK

redis> GET your_name -- 现在的数据库 0 已经没有之前设置的键了
(nil)

redis> SELECT 1 -- 切换到数据库 1
OK

redis[1]> GET your_name -- 之前在数据库 0 设置的键现在可以在数据库 1 找到
"aibibang" -- 证明两个数据库已经互换

4.8 混合 RDB-AOF 持久化格式

Redis 4.0 新增了 RDB-AOF 混合持久化格式, 这是一个可选的功能, 在开启了这个功能之后, AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容, 其中 RDB 格式的内容用于记录已有的数据, 而 AOF 格式的内存则用于记录最近发生了变化的数据, 这样 Redis 就可以同时兼有 RDB 持久化和 AOF 持久化的优点 —— 既能够快速地生成重写文件, 也能够在出现问题时, 快速地载入数据。
这个功能可以通过 aof-use-rdb-preamble 选项进行开启, redis.conf 文件中记录了这个选项的使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
# [RDB file][AOF tail]
#
# When loading Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, and continues loading the AOF
# tail.
#
# This is currently turned off by default in order to avoid the surprise
# of a format change, but will at some point be used as the default.
aof-use-rdb-preamble no

4.9 内存命令

新添加了一个 MEMORY 命令, 这个命令可以用于视察内存使用情况, 并进行相应的内存管理操作:

1
2
3
4
5
6
127.0.0.1:7002> memory help
1) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
2) "MEMORY STATS - Show memory usage details"
3) "MEMORY PURGE - Ask the allocator to release memory"
4) "MEMORY MALLOC-STATS - Show allocator internal stats"

其中, 使用 MEMORY USAGE 子命令可以估算储存给定键所需的内存:

1
2
3
4
5
6

127.0.0.1:7002> set truman aibibang
-> Redirected to slot [2113] located at 127.0.0.1:7000
OK
127.0.0.1:7000> memory usage truman
(integer) 59

使用 MEMORY STATS 子命令可以查看 Redis 当前的内存使用情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
127.0.0.1:7000> memory stats
1) "peak.allocated"
2) (integer) 2228415
3) "total.allocated"
4) (integer) 2228474
5) "startup.allocated"
6) (integer) 1054396
7) "replication.backlog"
8) (integer) 1048584
9) "clients.slaves"
10) (integer) 16858
11) "clients.normal"
12) (integer) 49630
13) "aof.buffer"
14) (integer) 0
15) "db.0"
16) 1) "overhead.hashtable.main"
2) (integer) 112
3) "overhead.hashtable.expires"
4) (integer) 0
17) "overhead.total"
18) (integer) 2169580
19) "keys.count"
20) (integer) 2
21) "keys.bytes-per-key"
22) (integer) 587039
23) "dataset.bytes"
24) (integer) 58894
25) "dataset.percentage"
26) "5.0161914825439453"
27) "peak.percentage"
28) "100.00264739990234"
29) "fragmentation"
30) "1.2773568630218506"

使用 MEMORY PURGE 子命令可以要求分配器释放更多内存:

1
2
redis> MEMORY PURGE
OK

使用 MEMORY MALLOC-STATS 子命令可以展示分配器内部状态:

1
2
redis> MEMORY MALLOC-STATS
Stats not supported for the current allocator

4.10 兼容NAT和Docker

Redis 4.0 将兼容 NAT 和 Docker , 具体的使用方法在 redis.conf 中有记载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
########################## CLUSTER DOCKER/NAT support  ########################
# In certain deployments, Redis Cluster nodes address discovery fails, because
# addresses are NAT-ted or because ports are forwarded (the typical case is
# Docker and other containers).
#
# In order to make Redis Cluster working in such environments, a static
# configuration where each node known its public address is needed. The
# following two options are used for this scope, and are:
#
# * cluster-announce-ip
# * cluster-announce-port
# * cluster-announce-bus-port
#
# Each instruct the node about its address, client port, and cluster message
# bus port. The information is then published in the header of the bus packets
# so that other nodes will be able to correctly map the address of the node
# publishing the information.
#
# If the above options are not used, the normal Redis Cluster auto-detection
# will be used instead.
#
# Note that when remapped, the bus port may not be at the fixed offset of
# clients port + 10000, so you can specify any port and bus-port depending
# on how they get remapped. If the bus-port is not set, a fixed offset of
# 10000 will be used as usually.
#
# Example:
#
# cluster-announce-ip 10.1.1.5
# cluster-announce-port 6379
# cluster-announce-bus-port 6380

5. 引用

  1. Redis 4.0新功能介绍
  2. Redis 4.0 release note

oozie搭建教程

简介

Apache Oozie是Hadoop工作流调度框架。它是一个运行相关的作业工作流系统。这里,用户被允许创建向非循环图工作流程,其可以在并列 Hadoop 并顺序地运行。

它由两部分组成:

工作流引擎:一个工作流引擎的职责是存储和运行工作流程,由 Hadoop 作业组成:MapReduce, Pig, Hive.
协调器引擎:它运行基于预定义的时间表和数据的可用性工作流程作业。
Oozie可扩展性和可管理及时执行成千上万的工作流程(每个由几十个作业)的Hadoop集群。

Oozie 也非常灵活。人们可以很容易启动,停止,暂停和重新运行作业。Oozie 可以很容易地重新运行失败的工作流。可以很容易重做因宕机或故障错过或失败的作业。甚至有可能跳过一个特定故障节点。

部署

编译

1
2
3
4
5
Unix box (tested on Mac OS X and Linux)
Java JDK 1.7+
Maven 3.0.1+
Hadoop 0.20.2+
Pig 0.7+

1.下载及解压

1
2
$ wget http://apache.fayea.com/oozie/4.3.0/oozie-4.3.0.tar.gz
$ tar xvf oozie-4.3.0.tar.gz

2.编译

进入解压后的目录 oozie-4.3.0

1
$ mvn clean package assembly:single -DskipTests

在国内的同学可以将中央仓库设成阿里云的地址,这样下载速度能快一点,部分下载不下来的,建议手动在mvnrepository.com中央仓库下载一下

配置

编译好的文件在以下路径

1
oozie-4.3.0/distro/target/oozie-4.3.0-distro/oozie-4.3.0/

1.环境变量配置

1
$ vi /etc/profile

在profile文件中添加以下内容:

1
2
export OOZIE_HOME=/oozie-4.3.0/distro/target/oozie-4.3.0-distro/oozie-4.3.0
export PATH=$PATH:$OOZIE_HOME/bin

执行以下命令生效

1
$ source /etc/profile

2.hadoop 集群集成

修改core-site.xml,添加以下信息,该教程全程采用的是root用户,因此配置中填入的是root,如果是其他用户需要改成其他用户,切记,不然会报没有权限的错误的。修改该文件后,还需要重启hadoop集群,以便参数生效。

1
2
3
4
5
6
7
8
9
 <property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>

<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>

3.oozie配置

以下配置默认在oozie-4.3.0/distro/target/oozie-4.3.0-distro/oozie-4.3.0/ 目录下操作

  • 配置文件修改

修改conf目录下oozie-site.xml文件,默认配置可以运行,但是运行hadoop job会报错的。主要是将hadoop集群的配置信息导入oozie中

1
2
3
4
5
6
7
8
9
10
11
12
 <property>
<name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
<value>*=/data/bigdata/hadoop-2.6.0-cdh5.7.0/etc/hadoop</value>
<description>
Comma separated AUTHORITY=HADOOP_CONF_DIR, where AUTHORITY is the HOST:PORT of
the Hadoop service (JobTracker, HDFS). The wildcard '*' configuration is
used when there is no exact match for an authority. The HADOOP_CONF_DIR contains
the relevant Hadoop *-site.xml files. If the path is relative is looked within
the Oozie configuration directory; though the path can be absolute (i.e. to point
to Hadoop client conf/ directories in the local filesystem.
</description>
</property>
  • ext

新建libext目录

1
2
3
$ cd libext
$ wget http://archive.cloudera.com/gplextras/misc/ext-2.2.zip
$ cd ..
  • 打包
1
bin/oozie-setup.sh prepare-war
  • 复制依赖jar
1
2
3
4
$ cd oozie-4.3.0/distro/target/oozie-4.3.0-distro/oozie-4.3.0/oozie-server/webapps/oozie/WEB-INF/lib/
$ cp -rf /data/bigdata/hadoop-2.6.0-cdh5.7.0/share/hadoop/mapreduce1/lib/*.jar ./lib/
$ cp -rf /data/bigdata/hadoop-2.6.0-cdh5.7.0/share/hadoop/mapreduce1/*.jar ./lib/

删除其中mr1的包,及jsp-api.jar,jasper-compiler-5.5.23.jar

  • 上传 examples

上传examples及oozie-sharelib-4.3.0

1
2
3
4
$ tar xvf oozie-examples.tar.gz
$ tar xvf oozie-sharelib-4.3.0.tar.gz
$ hadoop fs -put examples examples
$ hadoop fs -put share share

4.运行

初始化数据库

1
$ bin/ooziedb.sh create -sqlfile oozie.sql -run

以下输出即为成功:

1
2
3
4
5
6
7
8
9
10
11
12
Validate DB Connection.
DONE
Check DB schema does not exist
DONE
Check OOZIE_SYS table does not exist
DONE
Create SQL schema
DONE
DONE
Create OOZIE_SYS table
DONE
Oozie DB has been created for Oozie version '4.3.0'

守护进程运行

1
$ bin/oozied.sh start

验证是否成功

1
$ bin/oozie admin -oozie http://localhost:11000/oozie -status

输出System mode: NORMAL即表示配置成功,或者在浏览器中打开
http://localhost:11000/oozie/

examples运行

1.执行map-reduce

1
$ oozie job -oozie http://localhost:11000/oozie -config examples/apps/map-reduce/job.properties -run

2.验证结果

1
2
$ oozie job -oozie http://localhost:11000/oozie -info 0000007-161223101553230-oozie-root-W

如下结果则证明成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Job ID : 0000007-161223101553230-oozie-root-W
------------------------------------------------------------------------------------------------------------------------------------
Workflow Name : map-reduce-wf
App Path : hdfs://192.168.0.105:8020/user/root/examples/apps/map-reduce/workflow.xml
Status : SUCCEEDED
Run : 0
User : root
Group : -
Created : 2016-12-23 08:40 GMT
Started : 2016-12-23 08:40 GMT
Last Modified : 2016-12-23 08:41 GMT
Ended : 2016-12-23 08:41 GMT
CoordAction ID: -

Actions
------------------------------------------------------------------------------------------------------------------------------------
ID Status Ext ID Ext Status Err Code
------------------------------------------------------------------------------------------------------------------------------------
0000007-161223101553230-oozie-root-W@:start: OK - OK -
------------------------------------------------------------------------------------------------------------------------------------
0000007-161223101553230-oozie-root-W@mr-node OK job_1482454814338_0025 SUCCEEDED -
------------------------------------------------------------------------------------------------------------------------------------
0000007-161223101553230-oozie-root-W@end OK - OK -
------------------------------------------------------------------------------------------------------------------------------------

RedisCluster 集群配置文件损坏修复

问题现象

启动集群后,log文件显示如下信息:

1
2
Unrecoverable error: corrupted cluster config file.

这种情况,因为集群cluster-config-file文件损坏引起,导致该节点无法启动

修复方案

  1. 首先在各个node上移除该出错节点
  2. 删除该cluster-config-file文件
  3. 重新启动该节点
  4. 将该节点加入集群
  5. 指定该节点的master,将该节点以slave加入集群(本次修复未执行,集群自动恢复正常)

实施步骤

一、首先在各个node上移除该出错节点

执行以下脚本,将fail节点移除出集群,该操作仅移除一个机器中的无用节点信息,如果是多个机器,请在host_array中添加多个机器IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
host_array=(192.168.0.101)
for var in ${host_array[@]};
do
for i in $(seq 7000 7012)
do
nodeids=`src/redis-cli -c -h $var -p $i cluster nodes|grep fail|awk '{print $1}'`
for d in $nodeids
do
echo $d
src/redis-cli -c -h $var -p $i cluster forget $d
done
done
done

二、删除该cluster-config-file文件

1
mv nodes-7004.conf nodes-7004.conf.bak

三、重新启动该节点

1
redis-server redis.conf

四、将该节点加入集群

在集群任意instance 执行以下命令

1
CLUSTER MEET <ip> <port>   //将ip和port所指定的节点添加到集群当中,让它成为集群的一份子

五、指定该节点的master,将该节点以slave加入集群

在此次修复场景中未进行第五步,集群自动分配成为不均衡节点的slave

如果集群未自动分配,在需要加入集群的实例上执行,指定为某一个master的slave

1
CLUSTER REPLICATE <node_id> //将当前节点设置为 node_id 指定的节点的从节点。

kafka patition计算

kafka生产信息的时候,可以指定该信息存储在具体的patition上,如果不指定会使用默认的算法计算要落的patition.以下是针对此做一个探讨和理解

消息路由

  1. 指定了 patition,则直接使用;
  2. 未指定 patition 但指定 key,通过对 key 的 value 进行hash 选出一个 patition
  3. patition 和 key 都未指定,使用轮询选出一个 patition。

Kafka Client计算patition

详细代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//创建消息实例
public ProducerRecord(String topic, Integer partition, Long timestamp, K key, V value) {
if (topic == null)
throw new IllegalArgumentException("Topic cannot be null");
if (timestamp != null && timestamp < 0)
throw new IllegalArgumentException("Invalid timestamp " + timestamp);
this.topic = topic;
this.partition = partition;
this.key = key;
this.value = value;
this.timestamp = timestamp;
}

//计算 patition,如果指定了 patition 则直接使用,否则使用 key 计算
private int partition(ProducerRecord<K, V> record, byte[] serializedKey , byte[] serializedValue, Cluster cluster) {
Integer partition = record.partition();
if (partition != null) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(record.topic());
int lastPartition = partitions.size() - 1;
if (partition < 0 || partition > lastPartition) {
throw new IllegalArgumentException(String.format("Invalid partition given with record: %d is not in the range [0...%d].", partition, lastPartition));
}
return partition;
}
return this.partitioner.partition(record.topic(), record.key(), serializedKey, record.value(), serializedValue, cluster);
}

// 使用 key 选取 patition
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
if (keyBytes == null) {
int nextValue = counter.getAndIncrement();
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
if (availablePartitions.size() > 0) {
int part = DefaultPartitioner.toPositive(nextValue) % availablePartitions.size();
return availablePartitions.get(part).partition();
} else {
return DefaultPartitioner.toPositive(nextValue) % numPartitions;
}
} else {
//对 keyBytes 进行 hash 选出一个 patition
return DefaultPartitioner.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
}

one step

创建topic-move-test.json,迁移可以指定多个topic

1
2
3
4
5
6
7
{"topics": [{
"topic": "upgrade-kafka"
},{
"topic":"upgrade-kafka1"
}],
"version": 1
}

two step

在kafka工作目录,执行以下生成迁移配置,其中91为需要迁移到的broker id

1
bin/kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181 --topics-to-move-json-file topic-move-test.json --broker-list "91" --generate

生成以下内容:

1
2
3
4
5
6
7
Current partition replica assignment

{"version":1,"partitions":[{"topic":"upgrade-kafka1","partition":1,"replicas":[96]},{"topic":"upgrade-kafka","partition":5,"replicas":[96]},{"topic":"upgrade-kafka1","partition":2,"replicas":[91]},{"topic":"upgrade-kafka","partition":1,"replicas":[92]},{"topic":"upgrade-kafka","partition":4,"replicas":[95]},{"topic":"upgrade-kafka1","partition":0,"replicas":[95]},{"topic":"upgrade-kafka","partition":3,"replicas":[94]},{"topic":"upgrade-kafka","partition":0,"replicas":[91]},{"topic":"upgrade-kafka","partition":2,"replicas":[93]}]}
Proposed partition reassignment configuration

{"version":1,"partitions":[{"topic":"upgrade-kafka","partition":5,"replicas":[91]},{"topic":"upgrade-kafka1","partition":1,"replicas":[91]},{"topic":"upgrade-kafka","partition":1,"replicas":[91]},{"topic":"upgrade-kafka","partition":4,"replicas":[91]},{"topic":"upgrade-kafka1","partition":2,"replicas":[91]},{"topic":"upgrade-kafka","partition":3,"replicas":[91]},{"topic":"upgrade-kafka1","partition":0,"replicas":[91]},{"topic":"upgrade-kafka","partition":0,"replicas":[91]},{"topic":"upgrade-kafka","partition":2,"replicas":[91]}]}

three step

新建expand-cluster-reassignment.json文件,将上一步输出放入,内容如下:

1
{"version":1,"partitions":[{"topic":"upgrade-kafka","partition":5,"replicas":[91]},{"topic":"upgrade-kafka1","partition":1,"replicas":[91]},{"topic":"upgrade-kafka","partition":1,"replicas":[91]},{"topic":"upgrade-kafka","partition":4,"replicas":[91]},{"topic":"upgrade-kafka1","partition":2,"replicas":[91]},{"topic":"upgrade-kafka","partition":3,"replicas":[91]},{"topic":"upgrade-kafka1","partition":0,"replicas":[91]},{"topic":"upgrade-kafka","partition":0,"replicas":[91]},{"topic":"upgrade-kafka","partition":2,"replicas":[91]}]}

four step

按自己需求可以重新编辑expand-cluster-reassignment.json内容,修改broker id.
执行迁移命令

1
bin/kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181 --reassignment-json-file expand-cluster-reassignment.json --execute

检查执行结果

1
bin/kafka-reassign-partitions.sh --zookeeper 127.0.0.1:2181 --reassignment-json-file expand-cluster-reassignment.json --verify

以下即为迁移成功:

1
2
3
4
5
6
7
8
9
10
11
Status of partition reassignment:
Reassignment of partition [upgrade-kafka,4] completed successfully
Reassignment of partition [upgrade-kafka,5] completed successfully
Reassignment of partition [upgrade-kafka1,0] completed successfully
Reassignment of partition [upgrade-kafka,2] completed successfully
Reassignment of partition [upgrade-kafka1,1] completed successfully
Reassignment of partition [upgrade-kafka,1] completed successfully
Reassignment of partition [upgrade-kafka,3] completed successfully
Reassignment of partition [upgrade-kafka,0] completed successfully
Reassignment of partition [upgrade-kafka1,2] completed successfully

Reference

  1. kafka.apache.org

zookeeper运维经验

参数配置

在默认zoo.cfg配置中,zookeeper生成的历史镜像,log不会删除,生成的频率也比较快,因此生产环境需要配置以下两个参数

  • autopurge.purgeInterval

解释:清楚间隔,单位小时,默认值为0,修改次值,表示启用清楚

  • autopurge.snapRetainCount

解释:保留数量,默认为3,最小值为3

引用

  1. zookeeper官网

kafka使用教程

shell操作

1.创建topic

–replication-factor 2:备份因子为2

–partitions 10:partitions数目为10

1
bin/kafka-topics.sh --create --zookeeper 192.168.0.101:2181 --replication-factor 2 --partitions 10 --topic upgrade-kafka_test

2.查询topic

列出所有的topic

1
bin/kafka-topics.sh --list --zookeeper localhost:2181

3.删除topic

首先需要确认集群是否配置delete.topic.enable=true,配置后即可删除,确保topic没有被使用。

1
2
bin/kafka-topics.sh --delete --zookeeper 192.168.0.101:2181 --topic upgrade-kafka_test

程序操作

参考

  1. kafka official website
0%