初见Kafka Stream

kafka stream架构
https://docs.confluent.io/current/streams/architecture.html#parallelism-model

kafka stream应用入门教程
https://kafka.apache.org/21/documentation/streams/tutorial

参数num.stream.threads
The number of threads to execute stream processing.
默认只使用一个线程。

https://docs.confluent.io/current/streams/developer-guide/config-streams.html#streams-developer-guide-optional-configs

多实例部署
https://docs.confluent.io/current/streams/faq.html#streams-faq-scalability-maximum-parallelism

注意

使用官方的例子的时候,可能会出现时间戳的错误,这时候自定义一个类,如下:

1
2
3
4
5
6
7
8
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.streams.processor.TimestampExtractor;
public class DefaultEventTimeExtractor implements TimestampExtractor {
@Override
public long extract(ConsumerRecord<Object, Object> record, long previousTimestamp) {
return System.currentTimeMillis();
}
}

然后在主类中进行如下设置:

1
props.put(StreamsConfig.DEFAULT_TIMESTAMP_EXTRACTOR_CLASS_CONFIG, DefaultEventTimeExtractor.class.getName());

《数据结构与算法之美》学习02

数组和链表

数组需要一块连续的内存空间来存储,对内存的要求比较高。如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。

而链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,所以如果我们申请的是 100MB 大小的链表,根本不会有问题。

最常见的链表结构,它们分别是:单链表、双向链表和循环链表。

如何基于链表实现 LRU 缓存淘汰算法?

思路是这样的:我们维护一个有序单链表,越靠近链表尾部的结点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。

  1. 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。

  2. 如果此数据没有在缓存链表中,又可以分为两种情况:

如果此时缓存未满,则将此结点直接插入到链表的头部;

如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。

回文串

“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。

Hive Metastore服务异常

1
The health test result for HIVEMETASTORE_PAUSE_DURATION has become bad: Average time spent paused was 37.7 second(s) (62.80%) per minute over the previous 5 minute(s). Critical threshold: 60.00%.
1
The health test result for HIVE_HIVEMETASTORES_HEALTHY has become bad: Healthy Hive Metastore Server: 0. Concerning Hive Metastore Server: 0. Total Hive Metastore Server: 1. Percent healthy: 0.00%. Percent healthy or concerning: 0.00%. Critical threshold: 51.00%.

最近每天早晚都会收到这样的hive报警,今天google了一下,看cloudera上有人回答,应该是hive metastore的内存不足引起的,看了一下CDH manager上 Hive Metastore Server的Charts Library下的JVM Heap Memory Usage,发现使用率基本都是98%以上。嗯,应该是分配给hive metastore的内存太小了,从574M调到了2G。这两天观察一下。

凡是CDH PAUSE_DURATION相关的报警,应该都是java heap不够引起的。因为这个时候jvm在做GC,无法做其他响应。

参考 https://webcache.googleusercontent.com/search?q=cache:C3NJR-GjfPkJ:https://community.cloudera.com/t5/Batch-SQL-Apache-Hive/hive-server-2-pause-duration/m-p/57000+&cd=1&hl=zh-CN&ct=clnk&gl=hk 需要翻墙才能看到,并且这是google的缓存

以下是上边参考链接的文字内容:

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
hive server 2 pause duration

sim6
Expert Contributor
7/5/17
Pause DurationSuppress...
Average time spent paused was 46.4 second(s) (77.32%) per minute over the previous 5 minute(s). Critical threshold: 60.00%
 
I have suddenly started getting this issue. It never used to happen before. Have not even changed any configurations. What could be the possible reasons and how to inspect and resolve this?
Labels:
Cloudera Manager
Hive
Add Comment
Kudo 0

mbigelow
Champion
7/5/17
This is a garbage collection (GC) pause. A GC trigger will depend on the type of GC in use for HS2. An obvious trigger that you can detect is that the heap was too full. Go the HiveServer2 role an click Chart Library. It typically defaults to the Process Resources charts, if not go there. You should see the JVM Heap Memory Usage and GC pause charts. If the heap is constantly high (70% or above) then that is the likely reason. In that case the solution could be a simple as increasing the HS2 heap.

Note: the heap will increase as usage increases. So you could just have more concurrent or larger queries being processed by HS2.
Add Comment
Kudo 1

sim6
Expert Contributor
7/6/17
I have increased the heap size. It was set to default of 256 MB which I guess was causing the problem. I will revert if it keeps working alright :) Thanks much for your response .It helped

《数据结构与算法之美》学习01

刚才听了几节极客时间的《数据结构与算法之美》,其中《05 | 数组:为什么很多编程语言中数组都从0开始编号?》一节讲了从0开始编号的原因,并且在课后留了两个问题,1.回顾下标记清除垃圾回收算法,2.二维数组的内存寻址公式是怎样的。看了评论区的内容,大开眼界,非常精彩,通俗易懂的把这两个问题说清楚了,之前看书的时候可能还一点疑惑,现在明白了,评论区真是高手如云。

从0开始编号的原因,主要是以下两个:

从 1 开始编号,每次随机访问数组元素都多了一次减法运算,对于 CPU 来说,就是多了一次减法指令。

数组作为非常基础的数据结构,通过下标随机访问数组元素又是其非常基础的编程操作,效率的优化就要尽可能做到极致。所以为了减少一次减法操作,数组选择了从 0 开始编号,而不是从 1 开始。

说数组起始编号非 0 开始不可。所以我觉得最主要的原因可能是历史原因。

C 语言设计者用 0 开始计数数组下标,之后的 Java、JavaScript 等高级语言都效仿了 C 语言,或者说,为了在一定程度上减少 C 语言程序员学习 Java 的学习成本,因此继续沿用了从 0 开始计数的习惯。实际上,很多语言中数组也并不是从 0 开始计数的,比如 Matlab。甚至还有一些语言支持负数下标,比如 Python。

JVM标记清除算法:

大多数主流虚拟机采用可达性分析算法来判断对象是否存活,在标记阶段,会遍历所有 GC ROOTS,将所有 GC ROOTS 可达的对象标记为存活。只有当标记工作完成后,清理工作才会开始。

不足:1.效率问题。标记和清理效率都不高,但是当知道只有少量垃圾产生时会很高效。2.空间问题。会产生不连续的内存空间碎片。

二维数组内存寻址:

对于 m n 的数组,a [ i ][ j ] (i < m,j < n)的地址为:
address = base_address + ( i
n + j) * type_size

Linux文件删除,但是磁盘空间没有释放

Linux 磁盘空间总是报警,查到到大文件,删除之后,df看到磁盘空间并没有释放。

查找了下发现系统对rm进行了alias ,因为Linux对删除操作没有回收站机制,对rm操作进行了自定义,对删除文件进行移动到/tmp 目录里面。

又对/temp删除 但是还是没有发现磁盘冲击释放

执行

1
lsof | grep deleted

发现有大量刚刚删除文件的进程存在,通过kill -9 关闭进程(或者重启进程) OK
参考 https://www.cnblogs.com/xd502djj/p/6668632.html

Nginx中include其他配置文件

/usr/local/nginx/conf/nginx.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#user  nobody;
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

log_format mylog_format '$remote_addr|$remote_user|$time_local'
'$request|$status|$bytes_sent'
'$http_referer|$http_user_agent|$gzip_ratio'
'#$bytes_sent|$connection|$connection_requests|$msec|$pipe|$request_length|$request_time|$status|$time_iso8601|$time_local';

access_log logs/access.log mylog_format;

server {
listen 80;
location / {
proxy_pass http://127.0.0.1:8181;
}
}

server {
listen 443;
client_max_body_size 5M;
server_name api.dict123.cn;
ssl on;
ssl_certificate cert/1638702783821.pem;
ssl_certificate_key cert/1638702783821.key;
ssl_session_timeout 5m;
ssl_ciphers EBDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:DIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://132.232.74.114:80;
}
}

include /usr/local/nginx/conf/test1.conf;

}

如果test1.conf文件中不指定server_name,在使用nginx -s reload命令的时候,提示

1
nginx: [warn] conflicting server name "" on 0.0.0.0:80, ignored

这个时候需要在test1.conf的配置文件中加上server_name的配置,配置如下:

/usr/local/nginx/conf/test1.conf

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name hohode.com;
location /test1 {
alias /data/pserver/;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
charset utf-8,gbk;
}
}

CDH5 Hive on Spark搭建

Hive On Spark的搭建,参考此文 https://www.jianshu.com/p/f4f058d0b0a4

先使用 hadoop classpath 查询HADOOP_CLASSPATH的路径

在当前用户的.bashrc文件中添加:
export SPARK_DIST_CLASSPATH=$(hadoop classpath)

先将chrome浏览器的语言设置为英语
然后按照下边链接方式更改cdh的配置
https://stackoverflow.com/questions/29800239/how-to-set-up-dynamic-allocation-on-cloudera-5-in-yarn

http://xn--jlq582ax31c.xn--fiqs8s/post/242
按照上边的方式对链接中的参数进行修改

进入hive命令行
然后执行类似sql语句: select count(1) from eqxdb.mall_tag;
如果出现Query Hive on Spark job信息,并且计算结果正确的话,说明配置成功了
或者
hive –hiveconf hive.root.logger=DEBUG,console -e “select count(1) from eqxdb.mall_tag;”