通知设置 新通知
elasticsearch的索引如何才能做到平滑切换
空心菜 回复了问题 2 人关注 1 个回复 4993 次浏览 2015-09-18 23:22
elasticsearch配置文件详解
OpenSkill 发表了文章 0 个评论 3363 次浏览 2015-09-18 11:26
elasticsearch的config文件夹里面有两个配置文件:elasticsearch.yml和logging.yml,第一个是es的基本配置文件,第二个是日志配置文件,es也是使用log4j来记录日志的,所以logging.yml里的设置按普通log4j配置文件来设置就行了。
下面主要讲解下elasticsearch.yml这个文件中可配置的东西:
cluster.name: elasticsearch
配置es的集群名称,默认是elasticsearch,es会自动发现在同一网段下的es,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集群。
node.name: "Franz Kafka"
节点名,默认随机指定一个name列表中名字,该列表在es的jar包中config文件夹里name.txt文件中,其中有很多作者添加的有趣名字。
node.master: true
指定该节点是否有资格被选举成为node,默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master。
node.data: true
指定该节点是否存储索引数据,默认为true。
index.number_of_shards: 5
设置默认索引分片个数,默认为5片。
index.number_of_replicas: 1
设置默认索引副本个数,默认为1个副本。
path.conf: /path/to/conf
设置配置文件的存储路径,默认是es根目录下的config文件夹。
path.data: /path/to/data
设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开,例:
path.data: /path/to/data1,/path/to/data2
path.work: /path/to/work
设置临时文件的存储路径,默认是es根目录下的work文件夹。
path.logs: /path/to/logs
设置日志文件的存储路径,默认是es根目录下的logs文件夹
path.plugins: /path/to/plugins
设置插件的存放路径,默认是es根目录下的plugins文件夹
bootstrap.mlockall: true
设置为true来锁住内存。因为当jvm开始swapping时es的效率会降低,所以要保证它不swap,可以把ES_MIN_MEM和ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的内存分配给es。同时也要允许elasticsearch的进程可以锁住内存,linux下可以通过`ulimit -l unlimited`命令。
network.bind_host: 192.168.0.1
设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0。
network.publish_host: 192.168.0.1
设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址。
network.host: 192.168.0.1
这个参数是用来同时设置bind_host和publish_host上面两个参数。
transport.tcp.port: 9300
设置节点间交互的tcp端口,默认是9300。
transport.tcp.compress: true
设置是否压缩tcp传输时的数据,默认为false,不压缩。
http.port: 9200
设置对外服务的http端口,默认为9200。
http.max_content_length: 100mb
设置内容的最大容量,默认100mb
http.enabled: false
是否使用http协议对外提供服务,默认为true,开启。
gateway.type: local
gateway的类型,默认为local即为本地文件系统,可以设置为本地文件系统,分布式文件系统,hadoop的HDFS,和amazon的s3服务器,其它文件系统的设置方法下次再详细说。
gateway.recover_after_nodes: 1
设置集群中N个节点启动时进行数据恢复,默认为1。
gateway.recover_after_time: 5m
设置初始化数据恢复进程的超时时间,默认是5分钟。
gateway.expected_nodes: 2
设置这个集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复。
cluster.routing.allocation.node_initial_primaries_recoveries: 4
初始化数据恢复时,并发恢复线程的个数,默认为4。
cluster.routing.allocation.node_concurrent_recoveries: 2
添加删除节点或负载均衡时并发恢复线程的个数,默认为4。
indices.recovery.max_size_per_sec: 0
设置数据恢复时限制的带宽,如入100mb,默认为0,即无限制。
indices.recovery.concurrent_streams: 5
设置这个参数来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5。
discovery.zen.minimum_master_nodes: 1
设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
discovery.zen.ping.timeout: 3s
设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,对于比较差的网络环境可以高点的值来防止自动发现时出错。
discovery.zen.ping.multicast.enabled: false
设置是否打开多播发现节点,默认是true。
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点。
下面是一些查询时的慢日志参数设置
index.search.slowlog.level: TRACE
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.query.debug: 2s
index.search.slowlog.threshold.query.trace: 500ms
index.search.slowlog.threshold.fetch.warn: 1s
index.search.slowlog.threshold.fetch.info: 800ms
index.search.slowlog.threshold.fetch.debug:500ms
index.search.slowlog.threshold.fetch.trace: 200ms
docker run bash failed
空心菜 回复了问题 2 人关注 1 个回复 5496 次浏览 2015-09-17 00:18
openstack nova集成docker
Geek小A 发表了文章 0 个评论 4628 次浏览 2015-09-16 19:31
docker已经可以作为compute driver来使用,脱离了原来HEAT的模式,可以做到真正地使用nova来启动容器.这里记录一下openstack Kilo + docker 1.8的集成过程.所有组件环境基于centos7.
架构图如下:
安装docker
在compute node节点上安装docker,强烈建议安装docker-engine 1.8,需要linux3.1的kernal版本,拥有较高的生产稳定性,并且有启动用户组,旧版的docker-io是没有用户组,集成的时候docker.sock的权限每次都是手工修改很不方便.
# curl -sSL https://get.docker.com/ | sh
# usermod -aG docker nova
# systemctl enable docker.service
# systemctl start docker.service
安装novadocker
直接从github上clone安装
# pip install -e git+https://github.com/stackforge/nova-docker#egg=novadocker
# cp -R src/etc/nova/rootwrap.d /etc/nova/
# chmod -R root.nova /etc/nova/rootwrap.d
# cd src/novadocker/
# python setup.py install
配置nova调用docker驱动
# vi /etc/nova/nova.conf
compute_driver = novadocker.virt.docker.DockerDriver
配置glance支持容器格式
# vi /etc/glance/glance-api.conf (修改后重启glance-api服务)
container_formats = ami,ari,aki,bare,ovf,docker
Fix bug设置
由于novadocker开发的版本是基于nova比较新的版本,在现在发行的版本中使用会有一个BUG,下面是修复记录.
1.重启openstack-nova-compute服务时提示没有找到oslo_log模块
# pip install oslo.log2.重启openstack-nova-compute服务时提示没有找到hv_type模块
通过代码定位发现目前的版本中模块是nova.compute.hvtype3.直接导入driver测试提示报错,CONF没有’my_ip’这个opt配置
修改/usr/lib/python2.7/site-packages/novadocker/virt/docker/driver.py
把from nova.compute import hv_type 改为 from nova.compute import hvtype
通过代码排查发现目前的openstack是使用oslo.config这个模块包来做cfg的导入和导出4.直接导入driver测试提示继续报错,没有找到hvtype.DOCKER属性
但是在novadocker整个项目里面使用的oslo_config这个独立的模块
修改driver.py, client.py, hostinfo.py, vifs.py模块
from oslo_config import cfg 改为 from oslo.config import cfg
修改 /usr/lib/python2.7/site-packages/nova/compute/hvtype.py此时启动openstack-nova-compute已经正常
在# specific ‘baremetal’ & ‘fake’ then added in.下面增加
DOCKER=’docker’
glance导入docker镜像
# docker pull hipache需要注意的是glance导入后的名字一定要和docker images下显示的名字一模一样,否则创建时会提示无法找到镜像
# docker save hipache | glance image-create --is-public=True --container-format=docker --disk-format=raw --name hipache
启动容器实例
nova boot --image hipache --flavor 1 --nic net-id=342a0eef-e03d-4fd8-af3c-1ed485bee989 docker
1.此时启动容器实例报错失败,从nova-compute.log的日志看异常信息是”attach vif error”,具体是无法使用nova-rootwrap来提权进入namespace创建实例的网络接口
google找到的这个BUG的解决是禁用compute节点的selinux2.继续下一个BUG,日志抛出一个Python异常是没有找到hardware.InstanceInfo模块
进入目录/usr/lib/python2.7/site-packages/nova/virt
查看hardware.py的代码的确没有找到这个类或者函数,在github上找到nova项目的最新代码可以看到是有的.
把这个类的代码复制到本地的hardware.py里面
3.重启启动一个实例后,异常继续保持
异常提示InstanceInfo没有getitem这个内置方法
根据driver.py里面的调用可以发现get_info调用的时候是hardware.InstanceInfo是返回一个字典
删除刚才在hardware.py复制的代码,重写InstanceInfo
def InstanceInfo(state=None, max_mem_kb=0, mem_kb=0, num_cpu=0,cpu_time_ns=0, id=None):
Info={}
Info['state'] = state
Info['max_mem_kb'] = max_mem_kb
Info['self.mem_kb'] = mem_kb
Info['num_cpu'] = num_cpu
Info['cpu_time_ns'] = cpu_time_ns
Info['id'] = id
return Info
此时启动实例正常无报错
[root@openstack-k ~]# nova list参考连接:
+--------------------------------------+---------+--------+------------+-------------+-------------------------------------------+
| ID | Name | Status | Task State | Power State | Networks |
+--------------------------------------+---------+--------+------------+-------------+-------------------------------------------+
| c9d7ef23-f0fe-488d-88b1-3b5650901820 | hipache | ACTIVE | - | Running | admin_private=192.168.0.101, 172.24.4.228 |
+--------------------------------------+---------+--------+------------+-------------+-------------------------------------------+
[root@openstack-k ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
14583d5d6308 hipache "supervisord -n" 5 hours ago Up 5 hours nova-c9d7ef23-f0fe-488d-88b1-3b5650901820
[root@openstack-k ~]#
https://wiki.openstack.org/wiki/Docker原文链接:原文地址
http://docs.docker.com/installation/centos/
https://bugs.launchpad.net/nova-docker/+bug/1480246
https://github.com/openstack/nova/
https://github.com/stackforge/nova-docker
控制Elasticsearch分片和副本的分配
OpenSkill 发表了文章 1 个评论 19832 次浏览 2015-09-15 00:04
为了进行分片和副本的操作,ES需要确定将这些分片和副本放到集群节点的哪个位置,就是需要确定把每个分片和副本分配到哪台服务器/节点上。
一、显式控制分配
生产情景:
比如生产环境有三个索引分别为 man、woman、katoey
希望达到的效果:
man索引放置在一些集群节点上
woman索引又单独放置到集群的另外一些集群节点上
katoey索引希望放置在所有放置man索引和woman索引的集群节点上
这么做是因为katoey索引比其他两个索引小很多,因此我们可以将它和其他两个索引一起分配。
但是基于ES默认算法的处理方法,我们不能确定分片和副本的存放位置,但是ES允许我们对其做相应的控制!
1、指定节点的参数
如上图所示,我们将ES集群划分为两个"空间"。当然你也可以叫做区域,随便命名。我们将左边的三台ES节点服务器放置到zone_one的空间上面,将右边的三台ES节点服务器放到zone_two的空间上。
配置
为了做到我们需要的效果,我们需要将如下属性配置到左边三台ES集群节点服务器的elasticsearch.yml配置文件中
node.zone: zone_one将如下属性配置到右边的三台ES集群节点服务器elasticsearch.yml配置文件中
node.zone: zone_two
索引创建
当所有节点配置文件属性配置完成后,我们就可以根据空间名称,我们就可以创建索引放到指定的空间。
首先我们运行如下命令,来创建man索引:
# curl -XPOST "http://ESnode:9200/man'第一条命令是创建man索引;第二条命令是发送到_settings REST端点,用来指定这个索引的其他配置信息。我们将index.routing.allocation.include.zone属性设置为zone_one值,就是我们所希望的把man索引放置到node.zone属性值为zone_one的ES集群节点服务器上。
# curl -XPUT "http://ESnode:9200/man/_settings' -d '{
"index.routing.allocation.include.zone" : "zone_one"
}'
同样对woman索引我们做类似操作:
# curl -XPOST "http://ESnode:9200/woman'不同的是,这次指定woman索引放置在node.zone属性值为zone_two的ES集群节点服务器上
# curl -XPUT "http://ESnode:9200/woman/_settings' -d '{
"index.routing.allocation.include.zone" : "zone_two"
}'
最后我们需要将katoey索引放置到上面所有的ES集群节点上面,配置设置命令如下:
# curl -XPOST "http://ESnode:9200/katoey"
# curl -XPUT "http://ESnode:9200/katoey/_settings" -d '{
"index.routing.allocation.include.zone" : "zone_one,zone_two"
}'
2、分配时排除节点
跟我们上面操作为索引指定放置节点位置一样,我们也可以在索引分配的时候排除某些节点。参照之前的例子,我们新建一个people索引,但是不希望people索引放置到zone_one的ES集群节点服务器上,我们可以运行如下命令操作:
# curl -XPOST "http://EScode:9200/people"请注意,在这里我们使用的是index.routing.allocation.exclude.zone属性而不是index.routing.allocation.include.zone属性。
# curl -XPUT "http://EScode:9200/people/_settings" -d '{
"index.routing.allocation.exclude.zone" : "zone_one"
}'
使用IP地址进行分配配置
除了在节点的配置中添加一些特殊的属性参数外,我们还可以使用IP地址来指定你将分片和副本分配或者不分配到哪些节点上面。为了做到这点,我们应该使用_ip属性,把zone换成_ip就好了。例如我们希望lucky索引分配到IP地址为10.0.1.110和10.0.1.119的节点上,我们可以运行如下命令设置:
# curl -XPOST "http://ESnode:9200/lucky"
# curl -XPUT "http://ESnode:9200/lucky/_settings" -d '{
"index.routing.allocation.include._ip" "10.0.1.110,10.0.1.119"
}'
二、集群范围内分配
除了索引层面指定分配活着排除分配之外(上面我们所做的都是这两种情况),我们还可以指定集群中所有索引的分配。例如,我们希望将所有的新索引分配到IP地址为10.0.1.112和10.0.1.114的节点上,我们可以运行如下命令设置:
# curl -XPUT "http://ESnode:9200/_cluster/settings" -d '{集群级别的控制后续还会分享transient和persistent属性介绍
"transient" : {
"cluster.routing.allocation.include._ip" "10.0.1.112,10.0.1.114"
}
}'
三、每个节点上分片和副本数量的控制
除了指定分片和副本的分配,我们还可以对一个索引指定每个节点上的最大分片数量。例如我们希望ops索引在每个节点上只有一个分片,我们可以运行如下命令:
# curl -XPUT "http://ESnode:9200/ops/_settings" -d '{这个属性也可以直接配置到elasticsearch.ym配置文件中,或者使用上面命令在活动索引上更新。如果配置不当,导致主分片无法分配的话,集群就会处于red状态。
"index.routing.allocation.total_shards_per_node" : 1
}'
四、手动移动分片和副本
接下来我们介绍一下节点间手动移动分片和副本。可以使用ElasticSearch提供的_cluster/reroute REST端点进行控制,能够进行下面操作:
- []将一个分片从一个节点移动到另外一个节点[/][]取消对分片的分配[/][]强制对分片进行分配[/]
移动分片
假设我们有两个节点:es_node_one和es_node_two,ElasticSearch在es_node_one节点上分配了ops索引的两个分片,我们现在希望将第二个分片移动到es_node_two节点上。可以如下操作实现:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{我们通过move命令的index属性指定移动哪个索引,通过shard属性指定移动哪个分片,最终通过from_node属性指定我们从哪个节点上移动分片,通过to_node属性指定我们希望将分片移动到哪个节点。
"commands" : [ {
"move" : {
"index" : "ops",
"shard" : 1,
"from_node" : "es_node_one",
"to_node" : "es_node_two"
}
}]
}'
取消分配
如果希望取消一个正在进行的分配过程,我们通过运行cancel命令来指定我们希望取消分配的索引、节点以及分片,如下所示:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{运行上面的命令将会取消es_node_one节上ops索引的第0个分片的分配
"commands" : [ {
"cancel" : {
"index" : "ops",
"shard" : 0,
"node" : "es_node_one"
}
} ]
}'
分配分片
除了取消和移动分片和副本之外,我们还可以将一个未分配的分片分配到一个指定的节点上。假设ops索引上有一个编号为0的分片尚未分配,并且我们希望ElasticSearch将其分配到es_node_two上,可以运行如下命令操作:
# curl -XPOST "http://ESnode:9200/_cluster/reroute' -d '{一次HTTP请求包含多个命令
"commands" : [ {
"allocate" : {
"index" : "ops",
"shard" : 0,
"node" : "es_node_two"
}
} ]
}'
我们可以在一次HTTP请求中包含多个命令,例如:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{
"commands" : [
{"move" : {"index" : "ops", "shard" : 1, "from_node" : "es_node_one", "to_node" : "es_node_two"}},
{"cancel" : {"index" : "ops", "shard" : 0, "node" : "es_node_one"}}
]
}'
如何改变docker image的存放路径
OpenSkill 回复了问题 2 人关注 1 个回复 5111 次浏览 2015-09-13 18:09
HDFS高可用方案之QJM
OpenSkill 发表了文章 0 个评论 3576 次浏览 2015-09-12 20:18
在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),如果NameNode上的数据丢失,HDFS上对应的文件数据就无法找回来了。Hadoop在2.0.0之前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode无法转成NameNode,如果NameNode挂了,整个HDFS就会挂掉,无法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2之后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他可以随时切换成为真正的NameNode(一个可转正的高级备胎)。
先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):
然后有HA方案的系统架构:
以下的实验基于4个节点的Hadoop集群。其中每个节点的运行的进程列表如下:
实验环境中,所有节点的运行环境基本相同:
- []Ubuntu14.04 X64[/][]4G内存[/][]OpenJDK-1.7.0[/][]100Mbps以太网[/]
严格按照单节点搭建和集群搭建两个步骤,系统建起来完全没压力。我遇到的问题是刚开始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主机名,然后在log文件里看到各种无法连接。解决方案是修改主机名并在hosts文件里建立映射关系。[list=1]
安装Hadoop系统
hostname {new_hostname} # 修改主机名,只有当前Session有效sudo vi /etc/hostname # 永久修改主机名的方法另外,对于64位的系统,最好重新编译源码。
hdfs-site.xml文件:[list=1]
修改配置文件
dfs.namenode.name.dir /data/hadoop/namenode dfs.datanode.data.dir /data/hadoop/datanode dfs.replication 2 dfs.nameservices mycluster dfs.ha.namenodes.mycluster nn1,nn2 dfs.namenode.rpc-address.mycluster.nn1 hd1:8020 dfs.namenode.rpc-address.mycluster.nn2 hd3:8020 dfs.namenode.http-address.mycluster.nn1 hd1:50070 dfs.namenode.http-address.mycluster.nn2 hd3:50070 dfs.namenode.shared.edits.dir qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster dfs.client.failover.proxy.provider.mycluster org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider dfs.ha.fencing.methods sshfence dfs.ha.fencing.ssh.private-key-files /home/hduser/.ssh/id_rsa dfs.journalnode.edits.dir /data/hadoop/journalnode
- []其中nameservices是集群的命名空间,即使有多个集群,可以共用配置文件,但是要注意某些配置项的顺序。[/][]dfs.ha.namenodes.mycluster中的mycluster是可以任取的,但是要和dfs.nameservices对应。[/][]dfs.namenode.rpc-address.mycluster.nn1参考上一条。[/][]dfs.namenode.shared.edits.dir值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用来指定对应的JN节点,journalId建议使用和nameservices相同的名称。[/][]dfs.client.failover.proxy.provider.mycluster指定激活NameNode的Java类,目前Hadoop内置的只有上面那个。[/][]dfs.ha.fencing.methods是来用来隔离失效的NameNode的方法,有sshfence和Shell两种方式。sshfence需要配置dfs.ha.fencing.ssh.private-key-files私钥文件,以便交互的过程不需要输入密码。[/][]dfs.journalnode.edits.dir是JN保存数据的文件。[/]
fs.defaultFS hdfs://mycluster
- []注意mycluster要和dhfs-site.xml中的dfs.nameservices对应。fs.defaultFS不用端口号。[/]
改好配置文件好,就要将配置文件同步到所有的机器上了。可以用rsync将文件同步到多台机器上。rsync是一个增量同步工具,需要先安装。下面的rsync.sh的功能是将当前目录的所有文件发送到文件或参数对应的机器上。[list=1]
部署
$ cat rsync.sh #! /bin/bashdir=`pwd`pdir=`dirname $dir`send(){ echo "Sending to $2:$1" rsync -avez -e ssh $1 $2:$3}mul_send(){ while read host do send $dir $host $pdir done < $1}[ -f $1 ] && mul_send $1 || send $dir $1 $pdir
将rsync.sh放在etc/hadoop目录下,进入目录运行chmod +x rsync.sh./rsync.sh slaves# or ./rsync.sh hostname发送完文件之后,就是启动系统。步骤如下: 启动JNs.在所有JournalNode上运行
sbin/hadoop-daemon.sh --script hdfs start journalnode启动NameNode. 在原NameNode上运行
bin/hadoop --script hdfs start namenode # NameNode需要已经format。[url=使用上面的rsync.sh文件]/code[/url]将原NameNode(nn1)上的数据复制到第二个NameNode(nn2)。然后在nn2上运行:[code]bin/hdfs namenode -bootstrapStandby启动其他节点在NameNode上运行
sbin/start-dfs.sh
[list=1]
切换NameNode
手动方式
上面的NameNode默认以standby的状态启动,这时因为没有active的NameNode,所以是不能在HDFS读写文件,需要将其中的一个转成active状态。比如将nn1(对应前面的配置)转成Active:
bin/hdfs haadmin -transitionToActive nn1然后在NameNode的web页面上部的括号里的standby变成active。
转成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
自动切换
在当前NameNode不能使用时自动切换到第二个NameNode上,需要借助于ZooKeeper[url=ZK]/url。
ZK的安装过程和Hadoop差不多,就是下载文件、修改配置、复制到所有机器、启动。具体步骤在这里。
配置文件conf/zoo.conf:
tickTime=2000hd2,hd3,hd4是主机名,至少需要三台,这个在一台机挂了整个系统还能用,ZK的数量一般是奇数,为什么为奇数可以参考这里。
dataDir=/data/hadoop/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=hd2:2888:3888
server.2=hd3:2888:3888
server.3=hd4:2888:3888
然后要在hdfs-site.xml上添加配置:
然后就是在NameNode的机器上初始化NameNode在ZK的状态了:
dfs.ha.automatic-failover.enabled
true
ha.zookeeper.quorum
hd2:2181,hd3:2181,hd4:2181
bin/hdfs zkfc -formatZK重启HDFS或手动启动DFSZKFailoverController(ZKFC):
sbin/stop-dfs.sh # 重启hdfs在该HA方案中,每一个NameNode都有一个对应的ZKFC。ZKFC会随NameNode启动。
sbin/start-dfs.sh
sbin/hadoop-daemon.sh start zkfc # 启动ZKFC
测试
在当前NameNode运行jps看NameNode的进程ID,然后kill掉。通过Web页面( http://hdx:50070 ),可以看到standby的NameNode几乎在kill的同时转成active了。
转载地址:原文地址
Docker镜像无法删除
空心菜 回复了问题 2 人关注 1 个回复 5263 次浏览 2015-09-10 11:09
HDFS中Datanode存在大量没有删除的Block磁盘被占满案例分析
OpenSkill 发表了文章 0 个评论 7164 次浏览 2015-09-09 00:09
然后上网搜索了一下为什么,分析如下:
查看对应datanode的数据目录,发现确实有很多的数据块(量非常大,都超过了实际hdfs中的数据块总量)
这时候,猜测应该是有很多需要被删除的数据块没有被删除。猜测可能是NameNode和DataNode之间的通讯出现异常导致。于是查看NameNode和DataNode日志,发现并没有任何异常信息,只是发现NameNode定时对其中的三台机器发出了删除指令
BLOCK[i] ask 192.168.200.8:50010 to delete blk_7080908721303033545_7530145 BLOCK[/i] ask 192.168.200.9:50010 to delete blk_-6550808355677895247_7465333 BLOCK* ask 192.168.200.7:50010 to delete blk_2415291932316966347_7460687
按照网上的方法,通过dfsadmin证实了,确实是有大量的block在等待删除
hadoop dfsadmin -metasave meta.txt然后到logs目录下查看meta.txt文件结果如下:
Metasave: Blocks 572428 waiting deletion from 8 datanodes.显示有几十万的block等待删除
没有办法,只好从源码着手。在FSNameSystem.java文件里面找到了最终问题的所在:
public int computeDatanodeWork() throws IOException {computeInvalidateWork就是用于计算这次需要删除的数据块。但是并不是每次都把所有的节点都处理一遍,而是每次只处理nodesToProcess个节点,而这个数量决定于datanode的总数(heartbeats.size,我这儿是8)和一个系数(INVALIDATE_WORK_PCT_PER_ITERATION,写死的32)。
int workFound = 0;
int blocksToProcess = 0;
int nodesToProcess = 0;
// blocks should not be replicated or removed if safe mode is on
if (isInSafeMode())
return workFound;
synchronized(heartbeats) {
blocksToProcess = (int)(heartbeats.size()
* ReplicationMonitor.REPLICATION_WORK_MULTIPLIER_PER_ITERATION);
nodesToProcess = (int)Math.ceil((double)heartbeats.size()
* ReplicationMonitor.INVALIDATE_WORK_PCT_PER_ITERATION / 100);
}
workFound = computeReplicationWork(blocksToProcess);
// Update FSNamesystemMetrics counters
synchronized (this) {
pendingReplicationBlocksCount = pendingReplications.size();
underReplicatedBlocksCount = neededReplications.size();
scheduledReplicationBlocksCount = workFound;
corruptReplicaBlocksCount = corruptReplicas.size();
}
workFound += computeInvalidateWork(nodesToProcess);
return workFound;
}
也就是说每次只处理
8*32% = 3(这就解释了为啥每次只删除三台数据节点上的数据块。)
再查看节点选择部分:
……发现是通过iterator遍历的,然后悲剧的发现recentInvalidateSets用的是TreeMap,也就是说是有序的……
private Map> recentInvalidateSets =
new TreeMap>();
……
String firstNodeId = recentInvalidateSets.keySet().iterator().next();
……
所以只要这三个节点有数据需要删除,就不会删除到其他节点
这时候,发现这个问题是调整的时候,修改了一个配置项(dfs.replication.interval,默认是3秒,我修改成了30秒)导致的,当时修改的初衷是防止过早出现数据块复制。但是修改这个配置项以后,数据块副本数检查的间隔拉长了,导致30秒内,有几台机器一直有数据块需要删除,从而无法删除其他节点上的数据块,最终导致磁盘空间无法释放。因为INVALIDATE_WORK_PCT_PER_ITERATION是系统写死的,所以只能通过把dfs.replication.interval改回来,暂时解决这个问题。
Docker not support swap limit capabilities
Ansible 回复了问题 2 人关注 1 个回复 4954 次浏览 2015-09-07 01:57