0%

time 命令用于统计给定命令所花费的时间。

语法

1
time [-f 参数] 命令

当测试一个程序或比较不同算法时,执行时间是非常重要的,一个好的算法应该是用时最短的。所有类UNIX系统都包含time命令,使用这个命令可以统计时间消耗。例如:

1
2
3
4
5
6
$ time ls
......

real 0m0.016s
user 0m0.002s
sys 0m0.000s
阅读全文 »

前面我有写过一篇文章来详细介绍JVM中的各种GC,如果你还不了解,可以看这篇文章JVM 垃圾回收器。本篇文章以及后面几篇文章,将对每种GC产生的日志进行详细的解析,主要是由于写成一篇文章的话,篇幅太长,所以分成几篇文章来写。这篇文章主要介绍Serial垃圾回收器的日志解析。

阅读全文 »

最近在看机器学习方面内容,所以需要写一些代码来跑机器学习中一些简单的算法。很多算法都用到numpy这个库。但是对立面axis轴这个名词一直不懂。本篇文章就是来解释这个名词是什么意思。

要想理解这个名词,我们先看一些例子,看懂例子之后,这个名词就比较好理解。

阅读全文 »

我在使用hexo构建自己的博客时遇到过这样的一种情况。使用hexo init命令创建一个静态网页目录,然后使用git来管理这个目录。如果这时需要替换themes,一般都是克隆主题对应的的仓库到themes目录下面,这时就会出现一个仓库里面包含另外一个子仓库,在git里面,称这为子模块。但是我们改了主题的配置文件,去提交,会返现主题对应的目录是空的。

首先有一种最简单的方法,就是讲子模块下面的.git目录给删除,那么这个仓库就是一个普通的目录,但是这个对以后升级不方便。

下面我们通过实例来讲解如何优雅的解决这个问题。

我创建的目录结构如下

Xnip2019-04-14_00-30-14

阅读全文 »

在nginx中,负载均衡策略主要由以下几种,轮询、加权轮询、ip_hash、least_conn、fair和url_hash。下面将分别介绍每一种。

阅读全文 »

ngx_http_upstream_module模块用于定义服务器组,可以在proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass以及memcached_pass指令中引用。
示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;

server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}

server {
location / {
proxy_pass http://backend;
}
}
阅读全文 »

ngx_http_rewrite_module模块用于使用pcre正则表达式更改请求URI、返回重定向和有条件地选择配置。此模块主要有下面几个指令:break,if,return,rewriteset指令,这些指令按照以下顺序被执行:

  1. 首先按照顺序执行server上下文中的rewrite模块指令。
  2. 循环执行以下指令
    1. 依据请求的URI,匹配定义对应的location
    2. 按照顺序执行匹配到的location中的rewrite模块指令
    3. 如果请求被重写,将进入下一次的循环,但是循环的次数不能超过10次。

指令讲解

下面分别看看上面的每个指令:

break

停止执行 ngx_http_rewrite_module 的指令集,但是其他模块指令是不受影响的。

1
2
3
Syntax:	break;
Default: —
Context: server, location, if

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 8080;
# 此处 break 会停止执行 server 块的 return 指令(return 指令属于rewrite模块)
# 如果把它注释掉 则所有请求进来都返回 ok
break;
return 200 "ok";
location = /testbreak {
break;
return 200 $request_uri;
proxy_pass http://127.0.0.1:8080/other;
}
location / {
return 200 $request_uri;
}
}

发送请求和得到的结果如下:

1
2
curl 127.0.0.1:8080/testbreak
/other

可以看到 返回 /other 而不是 /testbreak,说明 proxy_pass 指令还是被执行了,也就是说 其他模块的指令是不会被 break 中断执行的(proxy_pass是ngx_http_proxy_module的指令)

if

依据指定的条件决定是否执行 if 块语句中的内容。里面可以设置其他模块的指令,但是必须是if指令所在上下文中存在的指令。

1
2
3
Syntax:	if (condition) { ... }
Default: —
Context: server, location

if 中的几种 判断条件

  1. 一个变量名,如果变量 $variable 的值为空字符串或者字符串”0”,则为false
  2. 变量与一个字符串的比较相等为(=) 不相等为(!=)
  3. 变量与一个正则表达式的模式匹配 操作符可以是(~ 区分大小写的正则匹配, ~*不区分大小写的正则匹配, !~``!~*,前面两者的非)
  4. 检测文件是否存在 使用 -f(存在) 和 !-f(不存在)
  5. 检测路径是否存在 使用 -d(存在) 和 !-d(不存在) 后面判断可以是字符串也可是变量
  6. 检测文件、路径、或者链接文件是否存在 使用 -e(存在) 和 !-e(不存在) 后面判断可以是字符串也可是变量
  7. 检测文件是否为可执行文件 使用 -x(可执行) 和 !-x(不可执行) 后面判断可以是字符串也可是变量

注意 上面 第1,2,3条被判断的必须是变量, 4, 5, 6, 7则可以是变量也可是字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
set $variable "0"; 
if ($variable) {
# 不会执行,因为 "0" 为 false
break;
}

# 使用变量与正则表达式匹配 没有问题
if ( $http_host ~ "^star\.igrow\.cn$" ) {
break;
}

# 字符串与正则表达式匹配 报错
if ( "star" ~ "^star\.igrow\.cn$" ) {
break;
}
# 检查文件是否存在 字符串与变量均可
if ( !-f "/data.log" ) {
break;
}

if ( !-f $filename ) {
break;
}

return

停止处理并将指定的code码返回给客户端。在不发送响应头的情况下关闭连接则设置code码为444(这个是nginx特有的,不一定适用于其他的服务器)。

从0.8.42版开始,可以指定重定向URL(code码为301、302、303、307和308)或响应正文文本(不是前面的重定向或者444code码)。响应正文文本和重定向URL可以包含变量。在特殊情况下,可以将重定向URL指定为此服务器的本地URI,在这种情况下,重定向的完整URL是根据请求方案($scheme)和重定向指令中的server_name_in_redirect和port_in_redirect来形成。

此外,可以只设置URl参数,不过这样的指令返回的code码都是302.可以将代码为302。这样的参数以“http://”、“https://”或“$scheme”字符串开头。URL可以包含变量。

在版本0.7.51之前可以使用以下code码:204、400、402-406、408、410、411、413、416和500-504。

直到版本1.1.16和1.0.13,code码307才被视为重定向。

直到版本1.13.0,code码308才被视为重定向。

1
2
3
4
5
Syntax:	return code [text];
return code URL;
return URL;
Default: —
Context: server, location, if

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# return code [text]; 返回 ok 给客户端
location = /ok {
return 200 "ok";
}

# return code URL; 临时重定向到 百度
location = /redirect {
return 302 http://www.baidu.com;
}

# return URL; 和上面一样 默认也是临时重定向
location = /redirect {
return http://www.baidu.com;
}

rewrite

1
2
3
Syntax:	rewrite regex replacement [flag];
Default: —
Context: server, location, if

如果指定的正则表达式与请求URI匹配,URI将会替换成replacement字符串。rewrite指令按照它们在配置文件中出现的顺序依次执行。可以使用flag终止指令的进一步处理。如果替换字符串以“http://”、 “https://” 或“$scheme”开头,则停止处理并将重定向返回到客户端。

这里先看俩个例子,然后在来说rewrite的四个flag

第一种情况 重写的字符串 带http://

1
2
3
4
5
6
location / {
# 当匹配 正则表达式 /test1/(.*)时 请求将被临时重定向到 http://www.$1.com
# 相当于flag 写为 redirect
rewrite /test1/(.*) http://www.$1.com;
return 200 "ok";
}

在浏览器中输入

1
127.0.0.1:8080/test1/baidu

则临时重定向到 www.baidu.com,后面的 return 指令将没有机会执行.

第二种情况 重写的字符串 不带http://

1
2
3
4
location / {
rewrite /test1/(.*) www.$1.com;
return 200 "ok";
}

发送请求和结果如下

1
2
curl 127.0.0.1:8080/test1/baidu
ok

此处没有带http:// 所以只是简单的重写。请求的 uri 由 /test1/baidu 重写为 www.baidu.com。因为会顺序执行 rewrite指令所以下一步执行return指令响应了ok

rewrite 的四个 flag

  1. last
    停止处理当前的ngx_http_rewrite_module的指令集,并开始搜索与更改后的URI相匹配的location;
  2. break
    停止处理当前的ngx_http_rewrite_module指令集,就像上面说的break指令一样;
  3. redirect
    返回302临时重定向。
  4. permanent
    返回301永久重定向。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 没有rewrite 后面没有任何 flag 时就顺序执行 
# 当 location 中没有 rewrite 模块指令可被执行时 就重写发起新一轮location匹配
location / {
# 顺序执行如下两条rewrite指令
rewrite ^/test1 /test2;
rewrite ^/test2 /test3; # 此处发起新一轮location匹配 uri为/test3
}

location = /test2 {
return 200 "/test2";
}

location = /test3 {
return 200 "/test3";
}

发送请求和结果如下:

1
2
curl 127.0.0.1:8080/test1
/test3

从上面可以看出,在第一个location中,将地址重写成/test3,也就是符合我们说的,如果没有flag时,就顺序执行,然后执行到最后一个时,就去搜索location,返回对应的结果。

last 与 break 的区别

last和break一样它们都会终止此location中其他它rewrite模块指令的执行,但是last立即发起新一轮的location 匹配,而break不会。

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location / {
rewrite ^/test1 /test2;
rewrite ^/test2 /test3 last; # 此处发起新一轮location匹配 uri为/test3
rewrite ^/test3 /test4;
proxy_pass http://www.baidu.com;
}

location = /test2 {
return 200 "/test2";
}

location = /test3 {
return 200 "/test3";
}
location = /test4 {
return 200 "/test4";
}

发送请求和结果如下:

1
2
curl 127.0.0.1:8080/test1
/test3

这个结果符合我们的预期,发送了一个新的请求。

当如果将上面的location / 改成如下代码

1
2
3
4
5
6
7
8
9
10
location / {
rewrite ^/test1 /test2;
# 此处不会发起新一轮location匹配;当是会终止执行后续rewrite模块指令
# 重写后的uri为 /more/index.html
rewrite ^/test2 /more/index.html break;
rewrite /more/index\.html /test4; # 这条指令会被忽略

# 因为proxy_pass 不是rewrite模块的指令 所以它不会被 break终止
proxy_pass https://www.baidu.com;
}

浏览器输入127.0.0.1:8080/test1,代理到百度产品大全页面https://www.baidu.com/more/index.html;也就是请求地址重写。但是不会重新发送新一轮的请求。类如上面如果美欧proxy_pass指令,使用同样的请求将返回404。

但是,如果这些指令放在location为/download/下,最后一个标志应该替换为break,否则nginx将进行10次循环并返回500个错误:

1
2
3
4
5
location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}

rewrite 后的请求参数

如果替换字符串replacement包含新的请求参数,则在它们之后附加先前的请求参数。如果你不想要之前的参数,则在替换字符串 replacement 的末尾放置一个问号,避免附加它们。

1
2
# 由于最后加了个 ?,原来的请求参数将不会被追加到rewrite之后的url后面 
rewrite ^/users/(.*)$ /show?user=$1? last;

rewrite_log

1
2
3
Syntax:	rewrite_log on | off;
Default: rewrite_log off;
Context: http, server, location, if

开启或者关闭 rewrite模块指令执行的日志,如果开启,则重写将记录下notice 等级的日志到nginxerror_log中,默认为关闭 off

set

1
2
3
Syntax:	set $variable value;
Default: —
Context: server, location, if

设置指定变量的值。变量的值可以包含文本,变量或者是它们的组合形式。

1
2
3
4
5
6
location / {
set $var1 "host is ";
set $var2 $host;
set $var3 " uri is $request_uri";
return 200 "response ok $var1$var2$var3";
}

uninitialized_variable_warn

1
2
3
Syntax:	uninitialized_variable_warn on | off;
Default: uninitialized_variable_warn on;
Context: http, server, location, if

控制是否记录有关未初始化变量的警告。默认开启

参考

  1. 搞懂nginx的rewrite模块
  2. Module ngx_http_rewrite_module

本篇文章主要先介绍几种数据库和缓存双写一致性的方案并分析其中的优缺点,最后讲解一下网上经常出现的一些关于这方面的名词。

更新策略

首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用。在读取缓存方面,都是按照下图的流程来进行业务操作。

o_getkeyflow

阅读全文 »

先说一下,你们可能看到我的面经也会觉得很惊奇,为什么其他面经里面出现的问题,我这里几乎都没出现,而且面试流程也走的这么快。下面就看一下我的阿里春招面试奇葩之旅。

阿里一面 2019年03月28日

  1. 你是怎么学习java
  2. 你看过什么比较经典的java方面的书
  3. 你觉得java中有什么类你很喜欢
  4. java中的锁
  5. 自定义无锁队列,不能使用CAS
  6. JVM内存划分
  7. 能不能自定义java.lang.String:考察java类加载机制
  8. top k问题
  9. 有什么想问他的,紧接着后面问了我一个你面试过了腾讯吗:我回答:不知道。这个很失水准。后面仔细想想,主要是自己当时因为最后一个topk问题没回答出来,脑子正处于蒙的阶段。

    总结

  10. 开放性问题,就把自己知道的全部讲出来,只要他不打断你,你还有的说就讲。另外要给他一个你在学习过程中是怎样看待这个问题,怎样解决这个问题的。不要只是简单的罗列。
  11. 千万要保持清醒,不然就被套路了。

阿里二面 2019年03月29日

  1. 自我介绍
  2. 你是怎样学习java
  3. 在学习java中遇到的困难
  4. 你有没有在学习java中遇到瓶颈:我主要说的是学习java web中遇到配置问题,然后描述了一下自己学习的经历,说刚开始很痛苦,也不知道如何解决,经过一次次的解决终于找到如何解决问题的方法,也知道出现了问题怎么去google搜。后面自己在遇到问题的时候,简单的一眼就可以看出来,复杂的就按照先分析问题,然后按照分析出来的思路一步步的解决,如果思路有问题,在查找解决思路的过程中及时调整。
  5. 你觉得你取得的最大成就是什么
  6. 在参加阿里比赛的过程中遇到的最大困难是什么:我回答的是自己转变思路很难,以前都是在命令编程模式下写程序,忽然转到异步模式下,很不适应。
  7. 事务:这个问题很宽,没有具体说什么事务,我就办自己知道的mysql事务全部说给他听。其实后来想想还可以讲讲分布式事务,毕竟我也稍微懂点。
  8. 你有什想问我的

总结

自己在回答问题的时候想到哪就说道哪,没有一个具体明确的思路,所以面试完需要自己整理自己学过的知识点,然后形成一个体系。

阿里三面 交叉面 2019年04月1日

  1. 自我介绍:我主要介绍了一下阿里天池中间件大赛的项目,然后在中间也分析了自己如何解决问题,如何选择框架,以及自己如何去拓展这些问题,从中学习到的知识点。我觉得这个思路其实挺好的,因为面试官一直说很不错。
  2. FOTA项目介绍:这个是一个简单的前后端分离的web后端管理系统,然后向他介绍一下。他问这个项目的原因是因为觉得我前一个项目已经被阿里的面试官都问过了,就不想在问那个项目。在介绍的时候分析了问什么前后端分离,选java原因,选择springboot的原因等等。
  3. 你是怎样理解springboot中约定由于配置:讲了一下自己学习java web的经历,然后说了配置的难点,然后说了一下这些约定的好处。然后说了一下自己的理解,只有先熟悉了整个框架如何使用才能很好的去分析流程很原理。
  4. bean的声明周期:我说知道的几种,以及他其实如何实现的。
  5. spring创建bean的流程:简单的说了整个流程
  6. beanFactoryPost,FactoryBean,BeanPostProessor等等的作用
  7. 如何设计一个秒杀系统:这里还是没有整理好,想到哪就说到哪。其实应该按照从请求的入口到访问数据库的流程来整理。我的回答是先做页面静态化,这些全部交给nginx来做。接着说将这部分系统分离出来,以免影响其他功能的访问。然后将商品数量放到redis中,使得数据的访问尽量都到redis中,而不会到mysql中。避免缓存被击穿。这一点我觉的我对redis不怎么熟,也就每太仔细说。然后说了一下用队列来防止redis中的数据成为热点数据,从而降低访问量。接着提供限流和降级,防止系统出现崩溃。
  8. 快速排序
  9. 俩数之和问题

阿里四面 终面

  1. 介绍一下自己:这里主要是介绍自己经历
  2. 介绍一下项目中的关键点
  3. 你最近在学习什么新技术

总结

这一面总体不是很好,首先自己是跑到一个安静的地点接的电话,当时气喘吁吁。因此自己在面试的时候最好处于一个很好的状态,不要像我这样。然后就面试,因为没怎么准备自我介绍,所以比较蒙。另外这一面就是总结面,没什么技术问题,主要是聊聊你的学习情况,所以最好多看看面经,准备这些比较长问到的问题。

下面记录的是我面腾讯TEG事业群的经历

腾讯一面 2019年03月13日

  1. 自我介绍:我主要的是介绍我的项目,因为是很突然的接到电话,当时也没准备自我介绍,就直接将简历上面的项目介绍了一遍。但是自我的感觉介绍不是太好,因为我自己都觉得讲的不是很清楚。所以如果你要参加面试前,最好先写一个简单的自我介绍,如果是项目介绍,最好先介绍下背景,然后在介绍整个项目。这样面试官相对好理解写。不过最好不要把项目介绍的太仔细,要留下一些点让面试官自己来提问。这个度需要自己把握,。

  2. tcp三次握手:就是简单的问了一下这个问题,面试官没有问为什么需要三次握手。可能是我在回答这个问题的时候讲了自己遇到的一个”connection by peer reset“异常,然后描述了一下自己是怎么解决这个问题的。

  3. java 垃圾回:这个几乎只要是面java的都会问,所以需要好好整理

  4. java中的锁:这个主要问的是Synchronize和lock的区别,以及怎么的选择。

  5. 限流:我主要说了一个根据访问的量来进行限流,后面面试官说可以通过信号量来限流。

  6. raft:这个主要是考分布式相关的问题,然后我说只记得一点,把自己记得的讲了出来。

  7. mapreduce:这个也是在问分布式相关的问题,但是还是忘记了,然后把自己记得的讲了出来。

后面就是面试官问我还有什么想问他的,问了一下具体部门,他们是做中间件和大数据相关的组。

一面总结

  1. 面试官主要对我的一个项目比较感兴趣,主要也在问我这个项目。不过其中有一些点没有讲的很好,比如我在项目中用到了负载均衡,但是我没有仔细的看过负载均衡实现的方法,就简单的回答了一下。所以你写在简历上的项目一点要仔细的整理。

  2. 以前自己看过很多的论文,但是都没有仔细整理,这次面试也凸显出来,所以自己看过的知识点一定要好好整理。知道不代表懂。

  3. 尽量不要紧张,因为这是我第一次面大公司所以比较紧张。不过这个也没有什么好办法,尽量多面点就不会紧张。

  4. 和面试管尽量不要保持他问你答的状态,最好是处于一种聊天的状态。这次面试前面就是因为他问我搭所以比较紧张,在面试一会之后就转入了一种在聊天的状态,紧张感也就没有了。

腾讯二面 2019年03月27日

  1. 项目介绍:和上面一样

  2. 自定义协议:如和自定义协议,也是项目中的一个问题,我当时回答的是:协议定义是非常难的一个问题,要考虑很多的方面,比如完整性和尽量减少跟数据无关的协议头的长度。然后我只是简单的将自己在项目中使用了自定义协议,主要是因为我发现在这个项目里面数据传输几乎都是一样的,所以就自定义了一个协议,但是这个自定义的协议非常的粗糙。如果不是比赛的话,我不会这样做,因为要提升性能才这样做的。但是在真正的生产环境中要考虑适配和兼容性这些问题,最好还是使用通用性协议

  3. 线程,线程是如何调度,Java线程是如何调度

  4. 你觉得你项目有什么难点

  5. 快速排序:这个问题当时没回答好,因为我吧快排和希尔排序弄混,所以就和面试官分别介绍了这俩个排序,然后总结了一下为什么快排相对来说比较好。主要胜在平均性能。

二面总结

其实问题不是太难,但是自己在回答的过程中思路不是太清晰,所以自我感觉回答的不是太好。另外一些基础的问题没有弄好。所以下来需要整理。

这个面试完了之后,也是在周五下午,进行了最后一轮的HR面试。至此我的腾讯实习面试之路走完。另外我的二面其实在前一周也可以结束,但是因为自己手机调整成了静音,没有接到电话,所以空等了一周,拖到了这周面试。所以在面试过程中手机千万不要调成静音。