Kafka 0.8: 多日志文件夹机制
kafka 0.7.2 中对log.dir的定义如下:
log.dir |
none | Specifies the root directory in which all log data is kept. |
在kafka 0.8 中将log.dir 修改为 log.dirs,官方文档说明如下:
| log.dirs | /tmp/kafka-logs |
A comma-separated list of one or more directories in which Kafka data is stored. Each new partition that is created will be placed in the directory which currently has the fewest partitions. |
从0.8开始,支持配置多个日志文件夹,文件夹之间使用逗号隔开即可,这样做在实际项目中有非常大的好处,那就是支持多硬盘。
下面从源码着手来浅析一下多日志文件夹是怎么工作的
1. 首先broker启动时会加载指定的配置文件,并把property对象传入KafkaConfig对象中
object Kafka extends Logging {
try {
val props = Utils.loadProps(args(0))
val serverConfig = new KafkaConfig(props)
2. 在kafkaConfig 中会解析log.dirs字符串,将其通过逗号隔开,形成Set,调用split方法时传入"\\s*,\\s*",表示逗号前后的空格都会被忽略
/* the directories in which the log data is kept */
val logDirs = Utils.parseCsvList(props.getString("log.dirs", props.getString("log.dir", "/tmp/kafka-logs")))
require(logDirs.size > 0)
/**
* Parse a comma separated string into a sequence of strings.
* Whitespace surrounding the comma will be removed.
*/
def parseCsvList(csvList: String): Seq[String] = {
if(csvList == null || csvList.isEmpty)
Seq.empty[String]
else {
csvList.split("\\s*,\\s*").filter(v => !v.equals(""))
}
}
3. 在KafkaServer中生成LogManager对象时传入 [(dir_path_1,File(dir_path_1)), (dir_path_2,File(dir_path_2)) ]
new LogManager(logDirs = config.logDirs.map(new File(_)).toArray,
topicConfigs = configs,
defaultConfig = defaultLogConfig,
cleanerConfig = cleanerConfig,
flushCheckMs = config.logFlushSchedulerIntervalMs,
flushCheckpointMs = config.logFlushOffsetCheckpointIntervalMs,
retentionCheckMs = config.logCleanupIntervalMs,
scheduler = kafkaScheduler,
time = time)
4.LogManager首先对传入的dir进行下列验证:是否存在相同的文件夹、文件夹是否存在(不存在则创建)、是否为可读的文件夹
/**
* Create and check validity of the given directories, specifically:
* <ol>
* <li> Ensure that there are no duplicates in the directory list
* <li> Create each directory if it doesn't exist
* <li> Check that each path is a readable directory
* </ol>
*/
private def createAndValidateLogDirs(dirs: Seq[File]) {
if(dirs.map(_.getCanonicalPath).toSet.size < dirs.size)
throw new KafkaException("Duplicate log directory found: " + logDirs.mkString(", "))
for(dir <- dirs) {
if(!dir.exists) {
info("Log directory '" + dir.getAbsolutePath + "' not found, creating it.")
val created = dir.mkdirs()
if(!created)
throw new KafkaException("Failed to create data directory " + dir.getAbsolutePath)
}
if(!dir.isDirectory || !dir.canRead)
throw new KafkaException(dir.getAbsolutePath + " is not a readable log directory.")
}
}
5. LogManager 对所有的文件夹获取文件锁,防止其他进行对该文件夹进行操作
/**
* Lock all the given directories
*/
private def lockLogDirs(dirs: Seq[File]): Seq[FileLock] = {
dirs.map { dir =>
val lock = new FileLock(new File(dir, LockFile))
if(!lock.tryLock())
throw new KafkaException("Failed to acquire lock on file .lock in " + lock.file.getParentFile.getAbsolutePath +
". A Kafka instance in another process or thread is using this directory.")
lock
}
}
6. 通过文件夹下面的recovery-point-offset-checkpoint 恢复加载每个目录下面的partition文件
/**
* Recover and load all logs in the given data directories
*/
private def loadLogs(dirs: Seq[File]) {
for(dir <- dirs) {
val recoveryPoints = this.recoveryPointCheckpoints(dir).read
/* load the logs */
val subDirs = dir.listFiles()
if(subDirs != null) {
//当kafka退出时,正常关闭的日志文件都会在该日志文件下生成.kafka_cleanshutdown为后缀的文件,该文件的作用是,在下次启动时,此日志文件可以不进行恢复流程
val cleanShutDownFile = new File(dir, Log.CleanShutdownFile)
if(cleanShutDownFile.exists())
info("Found clean shutdown file. Skipping recovery for all logs in data directory '%s'".format(dir.getAbsolutePath))
for(dir <- subDirs) {
if(dir.isDirectory) {
info("Loading log '" + dir.getName + "'")
val topicPartition = Log.parseTopicPartitionName(dir.getName)
val config = topicConfigs.getOrElse(topicPartition.topic, defaultConfig)
val log = new Log(dir,
config,
recoveryPoints.getOrElse(topicPartition, 0L),
scheduler,
time)
val previous = this.logs.put(topicPartition, log)
if(previous != null)
throw new IllegalArgumentException("Duplicate log directories found: %s, %s!".format(log.dir.getAbsolutePath, previous.dir.getAbsolutePath))
}
}
cleanShutDownFile.delete()
}
}
}
7. 当需要创建新的日志文件时,会在日志文件比较少的文件夹下去创建,源码中的注释很详细
/**
* Choose the next directory in which to create a log. Currently this is done
* by calculating the number of partitions in each directory and then choosing the
* data directory with the fewest partitions.
*/
private def nextLogDir(): File = {
if(logDirs.size == 1) {
logDirs(0)
} else {
// count the number of logs in each parent directory (including 0 for empty directories
val logCounts = allLogs.groupBy(_.dir.getParent).mapValues(_.size)
val zeros = logDirs.map(dir => (dir.getPath, 0)).toMap
//下面代码的主要作用是,对没有日志文件的文件夹设置size为0
var dirCounts = (zeros ++ logCounts).toBuffer // choose the directory with the least logs in it
val leastLoaded = dirCounts.sortBy(_._2).head
new File(leastLoaded._1)
}
}
Kafka 0.8: 多日志文件夹机制的更多相关文章
- hololens DEP2220: 无法删除目标计算机“127.0.0.1”上的文件夹
Hololens开发调试的过程中,可能会出现 “DEP2220: 无法删除目标计算机“127.0.0.1”上的文件夹“ 的错误导致无法部署,解决办法是进入项目属性页——调试——启动选项,勾选“卸载并重 ...
- eas之日志文件夹
F:\ThisIs_MyWork\kingdee\eas\server\profiles\server1\logs 服务端的日志文件夹 F:\ThisIs_MyWork\kingdeecusto ...
- oracle 10g/11g 命令对照,日志文件夹对照
oracle 10g/11g 命令对照,日志文件夹对照 oracle 11g 中不再建议使用的命令 Deprecated Command Replacement Commands crs_st ...
- CI3.0控制器下面建文件夹 访问一直404 的解决方法
在单入口文件(框架目录下面的index.php)最下面的require_once BASEPATH.'core/CodeIgniter.php';这行上面设置一个路径,是相对于conrollers文件 ...
- Kafka 入门(二)--数据日志、副本机制和消费策略
一.Kafka 数据日志 1.主题 Topic Topic 是逻辑概念. 主题类似于分类,也可以理解为一个消息的集合.每一条发送到 Kafka 的消息都会带上一个主题信息,表明属于哪个主题. Kafk ...
- IIS下众多网站,如何快速定位某站点日志在哪个文件夹?
windows2008,iis 多站点, 日志.应用程序池都是默认设置, 没有分开………… Logs目录里面有W3SVC43,W3SVC44,W3SVC45,W3SVC46.....等等日志文件夹. ...
- asp 中创建日志打印文件夹
string FilePath = HttpRuntime.BinDirectory.ToString(); string FileName = FilePath + "日志" + ...
- iis7下查看站点日志对应文件夹
原文:iis7下查看站点日志对应文件夹 IIS7下面默认日志文件的存放路径:%SystemDrive%\inetpub\logs\LogFiles 查看方法:点击对应网站 -> 右侧功能视图 - ...
- kafka 0.10.2 cetos6.5 集群部署
安装 zookeeper http://www.cnblogs.com/xiaojf/p/6572351.html安装 scala http://www.cnblogs.com/xiaojf/p/65 ...
随机推荐
- 精通phthon的条件
1. 熟知主流硬件体系(x86, x64)2. 熟知 CPython 的具体实现,如若可能至少通读源码三遍以上3. 熟知每条 Python bytecode 如何被解释执行4. 熟知每条 Python ...
- 【HDOJ】5564 Clarke and digits
DP+快速矩阵幂.注意base矩阵的初始化,不难. /* 5564 */ #include <iostream> #include <string> #include < ...
- inno setup 打包
; -- Example1.iss -- ; Demonstrates copying files and creating an icon. ; SEE THE DOCUMENTATION FOR ...
- python导入模块时的路径疑惑
有一个事儿,以前没注意,今天发现了,记录一下. 假设一个python文件a.py中,有一段代码,是打印当前路径的.当单独执行a.py文件的时候,打印的是a.py的位置. 但是当a.py文件被其他pyt ...
- shell color
shell 输出着色 格式: echo "/033[字背景颜色;字体颜色m字符串/033[控制码" 如果单纯显示字体颜色可以固定控制码位0m. 格式: echo "/03 ...
- HNU 13375 Flowery Trails (spfa最短路)
求最短路径覆盖的全部边权值和. 思路:分别从起点和终点两次求最短路,再比较两个点到起点的距离和他们之间的权值相加和是否等于最短路径. 这题很好 #include <cstring> #in ...
- RTCP
RTCP RTCP协议将控制包周期发送给所有连接者,应用与数据包相同的分发机制.低层协议提供数据与控制包的复用,如使用单独的UDP端口号.RTCP执行下列四大功能: (1) 主要是提供数据发布的质量反 ...
- ACM2032
杨辉三角 Problem Description 还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 ...
- HW4.12
public class Solution { public static void main(String[] args) { int n = 0; while(n * n < 12000) ...
- HW2.24
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...