ARTS计划2020/45

2020年第45周。本周ARTS计划继续。

Algorithm-加一

LeetCode第66题目,简单等级,考察数组

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

例如 输入[1,2,3] 输出[1,2,4] 输入 [1,2,9] 输出 [1,3,0] 输入[9,9] 输出[1,0,0]

这里面需要多考虑的点在于必须考虑进位,有可能会出现99999变成100000的情况,数组需要扩充。

实现逻辑不难,凭借脑袋想就ok,以下是我凭借直觉写的

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
public int[] plusOne(int[] digits) {
int length = digits.length;
// 是非9结尾,直接返回
if (digits[length - 1] < 9) {
digits[length-1] += 1;
return digits;
}
digits[length - 1] = 0;
// 进位标识符
int jinwei = 1;
for (int i = length - 2; i >= 0; i--) {
if (digits[i] < 9) {
digits[i] = digits[i] + jinwei;
return digits;
}
digits[i] = 0;
jinwei = 1;
}
// 进位进满了,要加一位,数组拷贝
if (digits[0] == 0) {
int[] result = new int[length+1];
System.arraycopy(digits, 0, result, 1, length);
return result;
} else {
return digits;
}
}

编译肯定过,也肯定效率ok,但是我上面犯了两个错误 1. 个位和其它位没什么区别,写完才发现完全可以合并。2. 没有必要进行数组拷贝,因为最后的情况肯定输出是1+n个零。

看人家写的多简练:

1
2
3
4
5
6
7
8
9
10
11
12
public int[] plusOne(int[] digits) {
for (int i = digits.length - 1; i >= 0; i--) {
digits[i]++;
digits[i] = digits[i] % 10;
if (digits[i] != 0) {
return digits;
}
}
digits = new int[digits.length + 1];
digits[0] = 1;
return digits;
}

我的代码和他的一模一样,但是他的比我看起来好太多了,简洁明了。后来我修改自己的代码大概如此:

1
2
3
4
5
6
7
8
9
10
11
12
13
public int[] plusOne(int[] digits) {
int length = digits.length;
for (int i = length - 1; i >= 0; i--) {
if (digits[i] < 9) {
digits[i] = digits[i] + 1;
return digits;
}
digits[i] = 0;
}
int[] result = new int[length+1];
result[0] = 1;
return result;
}

Review-美国大选

本周没有专门去阅读什么专业的文档,阅读英文的东西主要是特朗普&拜登的大选相关的一些新闻,因为国内的更新有问题,我就去看了下google上的东西,结果各家媒体的报导也都不一样,挺分裂的。

其实我还了nginx的一点文档,和Tips重了。nginx的负载均衡

Tips-nginx的带粘性复杂均衡

本周学了nginx通过head或者cookies进行分流转发。

背景 公司整了个开源的office online,在线编辑ppt,但是会出现几台机器之间跳转的情况,于是乎就出现了好几台机器都去加载同一个ppt,作为储备放在自己机器上打开这个ppt文档,一是造成资源浪费,二是客户路由变更的时候会出现重新加载资源的情况,体验比较差。

方法一 iphash

用户的出口ip作为hash,只要出口ip不变,访问的机器就不会变,配置也超简单

1
2
3
4
5
upstream  test-server {
ip_hash;
server localhost:8888;
server localhost:9999;
}

这里主要是比较nginx的iphash策略和根据参数转发的区别,结果iphash的实验一直做不出来,后来查看原因,在nginx的官网看到了这样的一句话:

The first three octets of the client IPv4 address, or the entire IPv6 address, are used as a hashing key.

这就很逗了,我电脑、手机连在同一个局域网下,都是192.168.1.0/255这个网段的,那肯定都会流转到一个机器上,负载不了,除非有个192.168.2.0/255的机器才有可能出现负载,也就是说会出现很大比例的分布不均的情况,可见根据iphash做事情,有挺大的局限性的。

方法二 cookies

我在网上看到了另外一种根据header或者cookies的办法进行分流转发,我试一下。

1
2
3
4
5
upstream test-server {
hash $cookie_jsessionid;
server localhost:8888;
server localhost:9999;
}

这种就是直接用一个叫做jsessionid的cookie来做了hash。也挺简单,只要jsessionid分布是均匀的,那么就是负载就会是均匀的。

但是有的场景仅用了cookies,比如美国有些州会有隐私法律规定网站默认不可以设置和获取用户cookies。或者更直接的Android、iOS这些终端的APP就完全不支持cookies,这种情况下就要用别的方法。

方法三 header或者参数

在Cookies不可用的情况下,大多都会有token的应用,那我们可以在head的token里做文章。

1
2
3
4
5
upstream test-server {
hash $https_my_token;
server localhost:8888;
server localhost:9999;
}

这里的header是有条件的,必须是小写,不能驼峰,如果要分割单词,可以使用“-”减号,nginx会自己转成“_”下划线

这个其实有其他的应用场景,比如APP灰度发布,可以让APP带上最新的版本号来请求

1
2
3
4
5
6
7
8
9
10
11
12
server {  
listen 8008;
charset utf-8;
underscores_in_headers on;
location / {
if ($http_app_version > 4050) {
proxy_pass http://new_server;
} else {
proxy_pass http://old_server;
}
}
}

underscores_in_headers表示了需要获取用户自定义的header。

总的来说方法二和方法三都属于同一个Tips范畴,他俩是同一个方法,都是通用性hash的方法,更优的写法是采用一致性hash,写法如下:

1
2
3
4
5
upstream test-server {
hash $https_my_token consistent;
server localhost:8888;
server localhost:9999;
}

这样的话就可以一致性hash,无需担心丢失节点后的大量故障节点转移的问题。

方法四 sticky

最后我在nginx官方文档里看到了最好的一个方案,sticky模块就可以完全满足我这次的要求,既不需要设置header,也不用cookies,也不用iphash这种不均匀的,这是nginx自带的一种粘性方案,但是默认不安装,要自己下源码装一下。配置如下

1
2
3
4
5
6
7
upstream test-server {
sticky;
#或者
# sticky cookie my_cookie expires=1h domain=.example.com path=/;
server localhost:8888;
server localhost:9999;
}

就这样就可以了,新接口访问的时候会生成一个名为router的cookie到浏览器端,下次带着cookies访问的时候找上一个访问的节点。虽然还是依赖于cookies,但是简单可配,完全满足我的要求,一个sticky就搞定了,前后端完全不用动,很好。

Share-关于回忆和幻想

本周我要分享的主题是 不要陷入对于过去的回忆 和 对未来的幻想。

人能把握的就是现在,唯一能够做的就是现在,但过去的事情会指导我们方式方法,未来的目标会指导我们方向,所以不可能不对过往回忆,不可能不对未来幻想,我想说的是不要陷入它。

没有人能够主宰当下,反正我不能,我只能去施加一些影响,让现在的事情朝着我想要的方向发展。已经发生的事情在脑中是可以被主宰的,没有发生的事情在脑中也是可以被主宰的,所以就会有人陷入到大脑的这种奖励机制,想着想着还会发出痴痴的笑,脑中坏的事情可以被尝试补偿,好的事情可以被尝试增强,奖励机制一次又一次的蒙骗自己,这样就造成了越发的回忆越发的幻想。最终时常陷进去了,对过去的回忆会扩大对现在的感觉,要么让人过于满足现在,要么让人过于对现在失望,失去理性人的判断;对未来的幻想也会导致对现在的错误判断,无法脚踏实地的做好现在。最终浪费掉超多的精力和时间,也不愿再面对现在的事情。

对过去的回忆也不是都回忆好事,对未来的幻想也不是都幻想好未来,很多时候却是对过去的后悔,对未来的恐惧。比如想到自己没拼了命的上高中,没正确选择大学专业,想到自己到35岁还在一线干着增删改查CRUD。这种比回忆好的幻想好的还没用,一种是没用的后悔,一种是放大的恐惧。后悔是没有用的,反思才有。

其实这一切的主要来源都是对现在的不满足,期望是一切痛苦的根源。但是人要是活得没有盼头,那就没意思了,无论怎样都会有点盼头。

对于回忆和幻想这个事,我的做法是尽可能让自己忙碌在现在,不去多想这些,偶尔想一下,一旦意识到不对,马上停下来。慎独,古代的君子用慎独来要求自己,没人监督的时候也要有自己的品行。而我理解的慎独就包括一个人独处的时候,可以做任何放松,但不要陷入那种完全的讨好自我的情况,大脑修改后的回忆和大脑放大后幻想便是讨好的一种。

姜文说彭于晏非常自律,他的灵魂站在高处审视自己的肉体。其实大家喜欢彭于晏一样的肌肉是因为彭于晏的脸,如果范伟脸不变的情况下,肉体和彭于晏一样,叫范伟老婆的女孩也没多少哈哈哈哈哈。

fanwei_pengyuyan

话虽这么说,但是我也想做个更加自律的人。