枫叶居

桃李春风一杯酒,江湖夜雨十年灯

0%

Huffman编码

注意: 原创技术博客,转载请注明原文地址

Huffman编码简介

依然记得初次接触Huffman编码,是在大一的《计算机组成原理》课程上,老师采用Huffman编码实现了一种CPU(虚拟机字节码同理)变长指令集。当时感觉特别神奇,后来又在《数据结构》课程上接触到了Huffman Tree(霍夫曼树),算是对Huffman编码有了一个比较全面的认识。

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Huffman编码Python实现。"""


class Node(object):

def __init__(self, score, value=None, lchild=None, rchild=None):
self.score = score
self.value = value
self.lchild = lchild
self.rchild = rchild
self.bit = 0


def generate_huffman_tree(sequence):

char2frequency = dict()
for c in sequence:
char2frequency.setdefault(c, 0)
char2frequency[c] += 1

def _cmp(a, b):
delta = a.score - b.score
if delta != 0:
return sequence.index(a.value) - sequence.index(b.value)
return delta

queue = [Node(char2frequency[x], x) for x in set(sequence)]
queue.sort(cmp=_cmp)

while len(queue) > 1:
lchild, rchild = queue.pop(), queue.pop()
lchild.bit, rchild.bit = 0, 1
parent_node = Node(
lchild.score+rchild.score, lchild=lchild, rchild=rchild)
queue.insert(0, parent_node)
queue.sort(key=lambda o: o.score)

return queue[0]


def generate_check_list(node):

stack = []
check_list = dict()
while node is not None or stack:
while node is not None:
stack.append(node)
node = node.lchild
if stack:
node = stack.pop()
if node.value is not None:
sequence = [x.bit for x in stack]
sequence.append(node.bit)
check_list[node.value] = int(''.join(map(str, sequence)), 2)
node = node.rchild
return check_list


if __name__ == '__main__':
tree = generate_huffman_tree('shootsheetjobwork')
check_list = generate_check_list(tree)
print check_list

MySQL前缀索引

注意: 本文的所有优化仅针对InnoDB存储引擎。

MySQL索引可以加快查询速度,但是索引并不是越多越好,索引虽然可以加快数据的查询速度,但是索引文件本身需要占用存储空间,数据的插入,删除,和修改也需要索引保持同步,据一线有经验的DBA介绍,索引列占表所有列的30%是比较合理的。

查看表存在的索引

1
show index from `table`;

查看索引占用磁盘空间大小

MySQLinformation_schema数据库TABLES官方手册

1
select concat(round(sum(INDEX_LENGTH/(1024*1024)), 2), 'MB') as 'Total Index Size' from `information_schema`.`TABLES` where `table_schema` = 'order' and `table_name` = 'order_base';

注意: 以下两种情况,不建议建立索引。

  • 表记录数比较少 —— InnoDB辅助索引叶子节点存储的不是记录的物理地址,而是主键值,使用辅助索引查找数据总是需要第二次查找主键索引,在表记录较少的情况下,建立索引反而会降低查询性能,所以直接全表扫描就好了,具体基准需根据业务场景而定。
  • 索引的选择性比较低 —— 索引的选择性指不重复的索引值与表记录数的比值,值域为(0, 1]。索引选择性越高越好,可以通俗的理解为,选择性高的索引在查询时往往可以筛选出比较多的记录,所以访问表的次数较少,索引的有效率比较高。例如存在基本表table,我们要在表tablecolumn列上建立一个索引,我们使用如下SQL语句计算该索引的选择性:
1
select count(distinct `column`) / select count(*) from `table`;

前缀索引

前缀索引是一种与索引选择性相关联的索引优化技术,顾名思义,使用列的前缀代替整个列作为Key,当前缀长度合理时,既可以做到前缀索引的选择性接近全列索引,同时因为索引Key变短而减少索引文件的大小和维护开销。

想象一下存在如下业务场景,一张存放订单信息的基本表order,订单号长度为24位(如:61700123215824),表结构如下:

id order_id
1 61700123215824
2 61500280698102
3 61500280756582

首先计算一下,全列索引选择性:

1
select round(count(distinct `order_id`) / count(*), 2) from `order`;

结果为1.00,选择前缀长度为5,看一下索引的选择性:

1
select round(count(distinct left(`order_id`, 5)) / count(*), 2) from `order`;

结果为0.00,5个字符长度的前缀,看来不行,我们增加到10,看一下索引的选择性:

1
select round(count(distinct left(`order_id`, 10)) / count(*), 2) from `order`;

结果为0.63,差强人意,我们继续以5位单位递增,看一下索引的选择性:

1
select round(count(distinct left(`order_id`, 15)) / count(*), 2) from `order`;

由于round的四舍五入,结果为1.00,那前缀能不能更少一些,在公司的业务系统内试了一下,前缀长度为11时,索引选择性为0.9999,四舍五入为1。通过夹逼的方法(😆默默的想起高数的夹逼定理),找到了最佳的索引前缀长度为11,接下来我们创建前缀索引:

创建前缀索引

1
alter table `order` add index `idx_order_id`(`order_id`(11));

注意: 前缀索引的缺点

  • 前缀索引不能用于order by与group by操作。
  • 前缀索引不能用于covering index —— 显而易见,前缀索引并未包含order_id列的全部信息,所以并不能用于covering index。

快速将开发分支代码合并至测试分支。

1
export DEV=dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function merge_dev() {
if [ -z ${DEV} ]; then
if [ -z $1 ]; then
DEV="dev"
else
DEV=$1
fi
fi
BRANCH=$(git rev-parse --abbrev-ref HEAD)
git push origin ${BRANCH}
git checkout ${DEV} \
&& git pull origin ${DEV} \
&& git merge ${BRANCH} -m "merge code automatically" \
&& git push origin ${DEV} \
&& git checkout ${BRANCH}
}

统计工程代码行数

1
find ./ -name "*.py" -exec wc -l {} \;|awk 'BEGIN{total=0}{print $1"\t"$2; $total+=$1}END{print "total lines: "$total}'

显示代码行最多的文件

1
find ./ -name "*.py" | xargs -n 1 wc -l|sort -nr

显示处于TIME_WAITSOCKET个数

1
netstat -n|awk '/^tcp/{a[$6]++}END{for (j in a) print a[j], j}'|sort -nr|head -n 10

简介

转载说明:本文章为作者原创,转载请标注原文地址

Bash Shell快捷键默认为Emacs编辑模式,与Emacs编辑器快捷键兼容,可通过set -o vi切换至vi编辑模式,通过set -o emacs切换回默认的Emacs编辑模式,本文所列快捷键均为Emacs模式下快捷键。

特别注意:

本人工作中一直使用Emacs编辑模式,Emacs编辑模式下的Alt键默认非Meta键(Emacs中使用频率很高的组合键),需要在终端中打开该项设置。

1.移动命令

  • Ctrl + a: 移动到命令行行首
  • Ctrl + e: 移动到命令行行尾
  • Ctrl + f: 向前移动一个字符
  • Ctrl + b: 向后移动一个字符
  • Alt + f: 向前移动一个单词
  • Alt + b: 向后移动一个单词

2.删除命令

  • Ctrl + u: 删除命令行行首至光标处的所有字符
  • Ctrl + k: 删除光标处至命令行行尾的所有字符
  • Ctrl + d: 删除光标处的字符
  • Ctrl + h: 删除光标前的字符
  • Ctrl + w: 删除光标处至单词词首的所有字符
  • Alt + d: 删除光标处至单词词尾的所有字符

3.编辑命令

  • Ctrl + y: 粘贴至光标后
  • Ctrl + x Ctrl + u: 撤销上次编辑操作
  • Ctrl + x Ctrl + e: 启动编辑器编辑命令(注:可编辑字符较多的命令)

4.搜索历史命令

  • Ctrl + r: 向后搜索历史命令(注:Ctrl + r可按多次,向后搜索历史命令
  • Ctrl + g: 退出搜索模式
  • Ctrl + p: 上一条命令
  • Ctrl + n: 下一条命令

5.控制命令

  • Ctrl + l: 清屏(注:相当于clear命令)
  • Ctrl + c: 终止命令
  • Ctrl + z: 挂起命令

6.!命令

  • !!: 执行上一条命令(注:执行$ls,后执行$!!,则会执行$ls
  • !: 执行最近执行的以开头的命令

参考文档

[1]: Bash官方手册

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
show variables like '%innodb_old_blocks_pct%'; -- 37%
show variables like '%innodb_buffer_pool_size%'; -- 显示InnoDB存储引擎BufferPool大小,134217728 = 128Mb
-- 热点数据
show variables like '%innodb_old_blocks_time%'; -- 1000ms, 位于midpoint处的数据在等待多长时间之后才会放入new热点数据。
show engine innodb status; -- 显示innodb引擎的状态
-- Modified db pages 指的是Flush list里面的DirtyPage
-- buffer pool hit rate
select pool_id, hit_rate, pages_made_young from `information_schema`.nnodb_buffer_pool_stats; --
select *from `information_schema`.innodb_buffer_page_lru; -- 查看innodb BufferPool中LRU list中具体Page信息。
select *from `information_schema`.innodb_buffer_page_lru where oldest_modification > 0; -- 查看DirtyPage
show variables like '%innodb_log_buffer_size%'; -- redo log buffer大小,默认为8MB,该缓冲区不需要太大,因为会被刷新至日志文件。

show variables like '%innodb_fast_shutdown%'; -- SharpCheckpoint在Database关闭时将所有DirtyPage Flush回Disk,这是默认的工作方式。
-- FuzzyCheckpoint 进行部分页的刷新
show engine innodb status;

show variables like 'datadir'; -- datadir代表数据库所在目录
show master status; -- 显示master节点信息
show variables like 'binlog_cache_size'; -- binlo_cache_size mysql会为每一个Session开启一个binlog_cache,默认为32kB大小。
show global status like 'binlog_cache%'; -- Binlog_cache_use -> 缓存使用次数,Binlog_cache_disk_use -> 磁盘使用次数。

show variables like 'sync_binlog'; -- 二进制日志并不是在每次写的时候同步到磁盘(用户可以理解为缓冲写),因此数据所在操作系统挂机时,可能会有一部分数据没有写入二进制文件
-- sync_binlog = [N],表示每写多少次就同步至磁盘sync_binlog = 1表示采用同步写磁盘的方式来写二进制日志。
show variables like 'innodb_support_xa'; -- 让mysql支持xa事务
show variables like 'binlog_format'; -- 指定binlog格式
set @@session.binlog_format = 'ROW'; -- 修改会话级别binlog_format
select @@session.binlog_format; -- ROW

show variables like 'socket'; -- mysqld监听的unix socket文件
show variables like 'pid_file'; -- mysqld的pid文件路径

show variables like 'innodb_data_file_path'; -- ibdata1:12M:autoextend 格式innodb_data_file_path=datafile_spec1[; datafile_spec2]...
show variables like 'innodb_file_per_table'; -- 为每个基于innodb存储引擎的表产生一个独立的表空间,命名规则为:

-- innodb默认ib_logfile0, ib_logfile1是重做日志(redo log file)
show variables like 'innodb_log_file_size'; -- innodb redo log file size默认为512GB
show variables like 'innodb_log_files_in_group'; -- redo log group日志文件数量
show variables like 'innodb_log_group_home_dir';
show variables like 'innodb_mirrored_log_groups';

show variables like 'innodb_flush_log_at_trx_commit'; -- 有效值为:0,1,2。0 - 当提交事务时,并不将事务的重做日志写入磁盘上的日志文件,而是等待主线程每秒的刷新。
-- 1 - 表示在执行commit时将重做日志缓冲同步写到磁盘,即伴有fsync的调用, 2 - 表示将重做日志写入磁盘,即写到文件系统的缓存中。

show variables like '%partition%';
show plugins;

-- mysql数据库支持以下几种类型的分区。range分区,list分区,hash分区,key分区。
-- range分区:行数据基于属于一个给定连续区间的列值被放入分区。
-- list
-- hash
-- key

-- innodb_file_pe_table
-- 表空间
-- ①数据②索引③插入缓冲Bitmap页

-- system ls /;

1.Thrift简介

转载说明:本文章为作者原创,转载请标注原文地址

Thrift由Facebook开发,解决了由不同语言编写的服务之间的调用问题。2009年Facebook将Thrift贡献给Apache基金会,成为一个开源项目。Thrift为典型的C/S架构,采用IDL(Interface Description Language),定义接口。

Thrift提供了命令行工具thrift,根据指定的IDL定义文件,生成不同语言的代码。因Thrift的依赖比较多,所以建议读者,采用自己开发平台的包管理工具进行安装。本人平时在macOS下进行开发工作,采用brew install thrift,便可自动完成了thrift的安装。

2.Thrift IDL介绍

Thrift IDL的语法比较接近C++,熟悉C++的读者,可以迅速掌握Thrift IDL的语法。由于IDL语法上比较接近C++,所以Thrift IDL比较偏向于静态语言,Python、Ruby等动态语言开发者在使用IDL定义接口时需要特别注意。

Thrift IDL支持C/C++风格的“//”,“/*,*/”注释,也支持Python风格的”#”注释。

1.基本数据类型

  • bool: A boolean value, true or false(注:布尔值)
  • byte: A signed byte(注:有符号字节
  • i16: A 16-bit signed integer(注:16位有符号数
  • i32: A 32-bit signed integer(注:32位有符号数
  • i64: A 64-bit signed integer(注:64位有符号数
  • double: A 64-bit floating point number(注:64位浮点数
  • string: An encoding-agnostic text or binary string(注:编码无关的字符串
  • void: Void (注:无返回值

2.复合类型

1.struct

struct——结构体类型,类似于C/C++中的结构体类型,将不同类型的数据聚合到一块儿。(注:描述面向对象语言中的类)。

1
2
3
4
5
6
7
8
struct User {
1: i32 id,
2: string user_name,
3: required bool is_admin,
4: optional string nick_name,
5: optional string sex = "male",
20: optional string city,
}

注意:

  1. optional关键字标识该字段为可选的。
  2. required关键字标识该字段为必填的。
  3. 定义中的序号,不可重复,但不是必须连续的。

2.enum

enum枚举类型

1
2
3
4
5
enum UserType {
BLOCKED = 0,
NORMAL = 1,
ADMIN = 2,
}

3.容器类型

容器类型比较类似于C++ STL中的容器类型,Thrift提供了三种容器类型:list,map,set。

  • list<T>: 由元素T组成的有序列表,Thrift将该容器类型编译为,C++ STL中的vector,Java中ArrayList,Python中list等等…
  • set<T>: 无序的集合,Thrift将该容器类型编译为,C++ STL中的set,Java中的HashSet,Python中set等等…
  • map<T1, T2>: k-v映射,Thrift将该容器类型编译为,C++ STL中的map,Java中的HashMap,Python中的dict等等…

4.自定义类型

Thrift支持C/C++风格的,typedef关键字,用于声明自定义类型。

1
typedef i32 Integer

5.异常

Thrift支持自定义异常,语法同struct类型的定义相似,如下所示:

1
2
3
exception NotFound {
1: string message,
}

注:在编写服务端代码时,仅仅在代码中抛出异常,是不够的,需要在定义接口时,指明该接口可能抛出的异常

6.服务

Thrift IDL中的Service,与Java中的Interface有异曲同工之妙。Thrift定义服务的语法如下:

1
2
3
4
5
service <name> {
<returntype> <name>(<arguments>)
[throws (<exceptions>)]
...
}

定义一个获取用户的Service示例如下:

1
2
3
4
5
service UserService {
User query_user(1: i32 user_id) throws (
1: NotFound not_found),
User add_user(1: User user);
}

注:service中接口定义之间的分割符号,可以是”,“,也可以是”;“。

7.命名空间

Thrift支持C++风格的命明空间,等同于Java、Python中的package的概念。Thrift定义命名空间的语法如下:

1
2
3
namespace cpp com.example.project
namespace java com.example.project
namespace py com.example.project

3.Thrift使用方法

示例文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// filename: user.thrift
namespace py thrift.rpc.user

enum Sex {
FEMALE = 0,
MALE = 1,
}

struct User {
1: string user_name,
2: Sex sex,
3: required i32 age,
4: optional string city,
}

exception NotFound {
1: string message,
}

service UserService {
User query_user(1: i32 id) throws (
1: NotFound not_found),
}

在Shell里面输入如下命令,生成Python代码:

1
thrift -out py --gen py:new_style,utf8strings,coding=utf-8

--gen参数,指定待目标语言,冒号后以都好分割的为thrift为该语言提供的选项。

-out参数,指定thrift生成代码的存放路径(**注:仅有一个-**)

更详细的用法,可通过thrift --help获取。

参考资料

[1]Thrift官方手册

[2]Thrift:The Missing Guide

[3]Thrift官方示例

转载说明:本文章为作者原创,转载请标注原文地址

公司最近上线了“订单管理系统”,系统内有比较多的分页展示逻辑,所以我单独拿出了点时间,对MySQL的分页做了总结。

提到MySQL分页,我们通常会首先考虑,使用偏移量offset+limit的办法实现。下面以实现目标:
查询订单表order,并按订单创建时间create_time,降序排序,每页50条记录
,为例进行说明。首先我们想到的sql语句如下:

1
select *from `order` order by `create_time` desc limit 0, 50;

多次执行该操作,随着页数增加(即:偏移量增大),该查询语句的性能随之下降,耗时比较明显。当并发量上来时,这对MySQL数据库的压力是致命的。以翻页至200页为例,MySQL会查询200 * 50条记录,最后只返回50条记录,前面的200 * (50 - 1)条记录,将会被丢弃。

因为订单的属性很多,所以并无法为每一列建立索引(当然为每一列都建立索引,是简单粗暴的)。优化此类分页查询的一个最简单的办法,尽可能使用索引覆盖扫描,而不是查询所有列,然后在关联返回所需要的列。优化后的SQL语句如下所示:

1
select *from `order` inner join (select id from `order` order by `create_time` limit desc 10000, 50) as `tmp` using(`id);

这里MySQL扫描了尽可能少的页面,获取需要访问的记录后,然后再去关联查询,获取了所需的列,该种用法还存在若干类似的变种。

最后,也是我们确定的技术选型。推荐的用法,前端每次查询都传入上次查询记录的max_id,或者min_id传递给我们,然后根据id的索引去优化该操作。(注:只有id列的单调性与目标列的单调性一致时可采用该方案)产品设计上,我们不返回具体的页数,只提供了当前页,前后10页跳页的功能,解决了该问题。

向后翻页

1
select *from `order` order by `create_time` desc where `id` < min_id limit 50;

向前跳页

1
2
select *from `order` order by `create_time` desc where
`id` < min_id limit 450, 50;

向前翻页

1
select *from `order` order by `create_time` desc where `id` > max_id limit 50;

向后跳页

1
select *from `order` order by `create_time` desc where `id` > max_id limit 450, 50;

当数据库,采用分库分表,或者中间件时的分页操作,较为复杂,需要根据具体情况确定,本次不做陈述。

介绍

转载说明:本文章为作者原创,转载请标注原文地址

本人是一个vim党,平时的开发工作都是在vim下完成的,但是…vim的官方手册就达2000多页,所以本人将平时遇到的一些比较有趣的插件与配置记录在配置文件中,一是方便他人借阅,分享一些实用的技巧,另一方面也是自我的慢慢积累。

实用技巧

1.显示代码中的Tab字符

Python2.7版本,代码缩进是不允许空格与制表符Tab混合使用的,否则会抛出IndentationError异常,这困扰过很多初学者,明明看着缩进都对,但是就是报错。

  • 使用正则表达式替换
  • 开启list选项,查看Tab字符与空格,:set list。
1
2
set lcs=tab:>-,trail:-
map <silent> <C-l> :let &list=&list==1?0:1<CR> "也可通过:set list显示

2.在代码中插入表达式值

在开发工作中,经常需要输入一些常量值,因为数值比较大,不太容易计算的原因,很多同学直接输入了常量表达式。比如,存在时间戳t = int(time.time()),现在需要获取该时间戳24小时前的时间戳,可以这样写:

1
_t = int(time.time()) - 24 * 3600

对于Python这种解释性语言来说,这种开销就落到了运行时,所以在vim中插入表达式值这个技巧显得比较实用。
在插入模式下(注意是插入模式),按下,然后键入=,=后面输入需要计算的表达式,摁下Enter便可以计算出该表达式的值。

3.未配置插件,注释代码块

有时候需要在服务器上修改一些配置,或者脚本,而服务器的vim未配置,没有代码注释插件,该怎么达到目的呢?这时,可以按下进入列选择模式,选中需要注释代码的前几列,可通过o或O调整选择块的范围,然后按下I,输入注释符,Python中为’#’,然后按下,便可大功告成(注意:按下A则在块后面添加)。

4.快速关闭文件

大多数同学退出vim,都是在命令行下输入,:wq,退出,因为键位的缘故,个人感觉这样不是很方便,好在vim提供了更加便捷的方式。
关闭文件时,只需在普通模式下,输入ZZ,(即左侧shift+z,z按下两次),效果等同于:x命令,文件内容有改动,保存修改并退出,更改文件修改时间,如果文件未有改动则退出,不更改文件修改时间。

想要丢弃对文件的更改,大多数同学都是用,:q!,强制退出的。在vim中也可以在普通模式下输入ZQ,强制退出。

5.强制保存文件

注意:此用法需要当前用户,在sudoer文件中授权。

在工作中经常遇到,root用户的vim未进行任何配置,而用普通用户去编辑的时候,保存却没有权限的尴尬。下面的vim命令可以,调用sudo进行修改保存,非常实用。

1
:w !sudo tee %

6.快速选择代码段落

常见选择方式:v - 选择字符,V - 行选择, - 列选择。

大多数同学,进行多行代码选择时会用V开启行选择,然后通过j,k,o选择,代码块,或者是g跳转等,这样子虽然速度不慢,但是还是不够优雅。

vim中有个段落的概念(paragraphs),大家可以通过:tab help paragraphs,查看paragraphs的描述,或者该博客
在开发工作中,我习惯将不同小功能,用空格划分为不同段落(Python开发中,这也是Pep8建议的),然后用段落移动命令,在段落间移动,用vip命令选择整个段落,很方便。

命令 效果
]] foo
[[ bar
) 向前移动一条一语句(forward)
( 向后移动一条语句(backward)
{ 向前移动至下一段落
} 向后移动至下一段落
vap 选择一个段落
vip 选择一个段落

7.设置vim分词

在vim中,用w,b,e,ge,等可以在单词之前移动,这种移动方式,大大方便了我们的编程,但是也有一些不尽如人意的地方,比如,下面的函数foo,有a,b,c三个参数,想要把光标从a移动至b,则需要输入2w,(vim将逗号,作为一个单词),这样子不是很方便(用习惯的同学除外),vim有个iskeyword选项,定义了“单词”的组成字符,可以将“,”,“.”,做为单词的一部分,下次移动的时候直接按下w便可从参数a,移动至参数b。(个人习惯,不喜勿喷^_^)

1
2
3
4
5
6
7
def foo(a, b, c):
pass

class Demo(object):
pass
d = Demo()
d.__name__
1
2
:set iskeyword+=\,
:set iskeyword+=\.

1
:set iskeyword+=\,\.

转载说明:本文章为作者原创,转载请标注原文地址

1.获取当前Shell脚本文件所在目录

1
PREFIX=$(cd `dirname $0`; pwd)

2.SSH开启密钥登录

1
ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

3.SSH端口转发

1
nohup  /usr/bin/ssh -N -L 0.0.0.0:8000:10.10.10.10:12000 sa.demo.com &

4.iOS证书转换

1
openssl pkcs12 -in demo.p12 -out demo.pem -nodes

5.统计代码行数

1
ls *.py|xargs -n 1 wc -l|awk 'BEGIN{total=0}{$total+=$1}END{print "total lines:\t"$total}'

Kafka常见操作命令行集锦

导出变量定义: $ZK_HOSTS定义在~/.bashrc中的导出变量,为Zookeeper集群地址

查看Kafka Cluster中的topic

1
./bin/kafka-topics.sh --list --zookeeper $ZK_HOSTS

查看Kafka某个topic的信息

1
./bin/kafka-topics.sh --describe --topic benchmark --zookeeper $ZK_HOSTS

新建一个1个partition的topic readbench

1
2
3
4
5
6
./bin/kafka-topics.sh --create --topic readbench --partitions 1 --replication-factor 1 --zookeeper $ZK_HOSTS```

> 新建一个1分区,复制因子为1的topic

```bash
./bin/kafka-topics.sh --create --topic name --partitions 1 --replication-factor 1 --zookeeper $ZK_HOSTS

新建一个5分区,复制因子为1的topic

1
./bin/kafka-topics.sh --create --topic name --partitions 5 --replication-factor 1 --zookeeper $ZK_HOSTS

以group_name为消费组消费名称为name的topic中的数据

1
./bin/kafka-console-consumer.sh --topic name --partition 0 --consumer-property group.id=group_name --from-beginning --bootstrap-server 10.95.134.86:9092,10.95.134.86:9093,10.95.134.86:9094

往topic name中生产数据

1
bin/kafka-console-producer.sh --broker-list 10.95.134.86:9092,10.95.134.86:9093,10.95.134.86:9094 --sync --topic name

物理删除kafka中的一个topic(kafka默认是逻辑删除)

1
./bin/kafka-topics.sh --delete --topic name --zookeeper $ZK_HOSTS
  • 删除掉Zookeeper集群中name标识的topic
1
./bin/zkCli.sh rmr /brokers/topics/name

Kafka中为topic增加partition(不能够删除partition,仅支持增加)

1
./bin/kafka-topics.sh --alter --topic name --zookeeper $ZK_HOSTS --partitions 3

Kafka中为topic更新配置参数

1
./bin/kafka-topics.sh --alter --topic readbench --zookeeper $ZK_HOSTS --config cleanup.policy=delete

Kafka集群中添加新的broker时,需要将一些topic的存储压力分散到新的broker上去,这时需要kafka reassign工具,分三步操作

  • 1、指定待迁移的topic,以json格式存放在topic-to-move.json文件中。
1
2
3
4
5
6
7
8
9
cat >> topics-to-move.json << EOF
{
"topics": [
{"topic": "name1"},
{"topic": "name2"},
],
"version": 1
}
EOF
  • 2、生成移动脚本
1
./bin/kafka-reassign-partitions.sh --zookeeper $ZK_HOSTS --topics-to-move-json-file topic-to-move.json --broker-list "1,2" --generate

将输出信息中的Proposed partition reassignment configuration一栏下的json字符串保存为reassign.json文件。

1
echo '{"version":1,"partitions":[{"topic":"readbench","partition":0,"replicas":[3]}]}' >> reassign.json
  • 3、执行迁移脚本
1
./bin/kafka-reassign-partitions.sh --zookeeper $ZK_HOSTS --reassignment-json-file reassign.json --execute
  • 4、查看迁移进度
1
/bin/kafka-reassign-partitions.sh --zookeeper $ZK_HOSTS --reassignment-json-file reassign.json --verify