"仁扬" 发布的文章

一、什么是主从同步?

主从同步,就是将数据冗余备份,主库(Master)将自己库中的数据,同步给从库(Slave)。

从库可以一个,也可以多个,如图所示:

Redis主从同步

二、为什么需要主从同步?

Redis 虽然有 RDB 和 AOF 持久化技术,可以在服务器重启的情况下保证内存中的数据不会丢失(但不意味着数据不丢,重启的时候还是会有不可用的情况)。

但是如果服务器关闭后,再也起不来了(比如硬件故障),那意味着数据是完全丢失的!会对业务产生重大影响。

所以,主从同步的必要性,在于数据的高可用。它可以保证机器故障时,还有其他的服务器可以进行故障转移。

问题来了,多台服务器冗余同一份数据,Redis 是如何保证数据的一致性的?

阅读全文

注意:如果你公司的 VPN 网络是在苹果下使用的,本文可能不适用(苹果系统不支持 PPTP)。

用 Linux 和用 Windows/macOS 不一样,它真的需要用户操心很多东西。比如怎么连接公司的 VPN 网络……

我是折腾了挺久,反正系统自带的 VPN 连接管理界面,不管你怎么配置,就是用不了!!!

最后,我翻了 arch 的官方文档,发现有一个叫 PPTP Client 的东西,配置起来超级简单,敲几下命令就连接上了……

真正连上的那一瞬间,真的很有成就感!趁热记录下来:)

好了, 我们进入正题,首先是安装:

sudo pacman -S pptpclient

然后配置一下连接(起名叫 company):

sudo pptpsetup --create company --server 域名或 IP 地址 --username 账号 --password 密码 --encrypt

可以用以下命令测试一下 company 连接:

sudo pon company debug dump logfd 2 nodetach

会打印一堆调试信息,并最终程序卡住不会退出。连接成功后,你会看到一个 ppp0 的网卡:

ip addr

要用公司 VPN 连接的时候,需要加个路由:

sudo pon company
sudo ip route add default dev ppp0

结束使用时去掉就好了:

sudo ip route del default dev ppp0
sudo poff company

经过以上步骤配置后,就可以使用了。

但我发现特别卡,ping 了一下发现丢包率很高(6%)。

网上搜索了一圈资料,最终确定和 MTU 有关系(默认是 1500),我参考了 macOS 的 1280,设置后一切正常,不再丢包了!

sudo ifconfig ppp0 mtu 1280

MTU 设置太大会被分片,太小影响效率。因此需要设置成一个合理值,保证网络的可靠性的同时,实现传输效率的最大化。

MTU 一般网络设备都是 1500。如果本机的 MTU 比网关大,大的数据包会被拆分传送,会产生大量数据包碎片,增加丢包率,降低网络传输速度。

检查的话,可以使用以下命令:

ping -s 1472 -M do 192.168.1.123

它表示发送 1472+28 字节的数据包,并禁止路由器拆包。

  • 如果正常回复,说明网络最大 MTU 是 1500,与系统默认一致;
  • 如果不正常,说明超过网络限定大小,需要减小探测包大小再次尝试。

注:1500 = 1472 + 8(ICMP 回显请求和应答报文的格式长度)+ 20(IP 头)。

还是挺多命令要敲的,为了方便,我加了两个 alias,大家可以根据实际情况配置:

alias onn_company="sudo pon company && sleep 5 && sudo ip route add default dev ppp0 && sudo ifconfig ppp0 mtu 1280"
alias off_company="sudo ip route del default dev ppp0 && sudo route del -host 1.2.3.4 dev enp2s0 && sudo poff company"
  • sleep 5 使得连接后等一下下,再改路由;不 sleep 的话网络会卡一下,体验不是很好;
  • ifconfig 修改后的 MTU 重启电脑会丢失,但这个不是很重要,我觉得也没必搞成永久生效了;
  • route del -host 1.2.3.4 需要改成你公司的 VPN 的 IP,我发现有时候 del default 不好使,原因不明(可能我连接多次了)。

整体上还是挺方便的,简单几行命令就搞定了。

“记得上次用 Manjaro Linux 的时候,还是上次:)”

三年前,工作都是在 Linux 下完成的——那时候的我还没有苹果电脑。

我算是接触了很多很多发行版,Ubuntu、Debian、Deepin 深度、Linux Mint 薄荷、CentOS、Manjaro……小众的,还有 Puppy Linux、Slitaz……

最喜欢的,还是 Manjaro 啦!软件库非常齐全,更新也快。所以我一般都会安利它哈哈~

不过有时候下载一些软件,你会发现官网只提供 deb 或者 rpm 包。这个时候可以用以下命令,转成 Manjaro 可以安装的包:

一、先检查有没有安装 debtap,有安装可以直接跳到第 3 步:

sudo pacman -Q debtap

二、安装debtap:

sudo pacman -S yaourt
yaourt -S debtap

三、更换源(非常重要,不然炒鸡炒鸡卡):

sudo sed -i "s|http://ftp.debian.org/debian/dists|https://mirrors.ustc.edu.cn/debian/dists|g" /usr/bin/debtap
sudo sed -i "s|http://archive.ubuntu.com/ubuntu/dists|https://mirrors.ustc.edu.cn/ubuntu/dists|g" /usr/bin/debtap

四、更新一下:

sudo debtap -u

五、打包:

sudo debtap xxxx.deb

期间提示你输入包名、License 信息。

  • 包名根据你安装的软件填写就好了,比如飞书,你输入 feishu 回车键即可;
  • License 自己使用随便填一个就好了,比如 GPL。

上述操作完成后会在deb包同级目录生成×.tar.xz文件

六、安装:

sudo pacman -U XXXX.tar.xz

2022年08月07日文章更新:第 6 步打出来的包是 zst 格式的了,命令自行改一下。

笔者目前所在公司存在多套 Redis 集群:

  • A 集群 主 + 从 共 60 个分片,部署在 3 + 3 台物理机上,每台机器各承载 10 个端口
  • 主库 30 个端口在广州,从库 30 个端口在中山
  • B 集群共 72 个端口,部署架构一模一样

上云后,均为广东的某个云厂商的 2 个可用区,不再使用 IDC 数据中心,部署架构一致。

有人提出了一个很耐人寻味的问题:

这个架构有问题,如果两地之间网络故障,必定会出现脑裂!

真的会出现脑裂吗?

不至于吧!网络分区后,理论上广州机房是可用的,中山因为没有主(访问从库将槽位重定向回主库),所以中山机房不可用。所以只有一个机房可写,不会脑裂。

猜想终究是猜想,实践出真知!现在 docker 太方便了,搭一个集群模拟一下就 OK 了~

准备环境:

  • 2 台测试机器,模拟双机房环境
  • 每台机器启动 6 个端口,通过 redis-trib 搭建集群

建立以下文件夹,并准备 docker-compose.yml:

mkdir -p ./data/redis/8001/data && \
mkdir -p ./data/redis/8002/data && \
mkdir -p ./data/redis/8003/data && \
mkdir -p ./data/redis/8004/data && \
mkdir -p ./data/redis/8005/data && \
mkdir -p ./data/redis/8006/data && \
mkdir -p ./data/redis/9001/data && \
mkdir -p ./data/redis/9002/data && \
mkdir -p ./data/redis/9003/data && \
mkdir -p ./data/redis/9004/data && \
mkdir -p ./data/redis/9005/data && \
mkdir -p ./data/redis/9006/data

广州机房 6 个端口:

version: '3'

services:
 redis_gz_1:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8001/data:/data
  environment:
   - REDIS_PORT=8001

 redis_gz_2:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8002/data:/data
  environment:
   - REDIS_PORT=8002

 redis_gz_3:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8003/data:/data
  environment:
   - REDIS_PORT=8003

 redis_gz_4:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8004/data:/data
  environment:
   - REDIS_PORT=8004

 redis_gz_5:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8005/data:/data
  environment:
   - REDIS_PORT=8005

 redis_gz_6:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/8006/data:/data
  environment:
   - REDIS_PORT=8006

中山机房 6 个端口:

version: '3'

services:
 redis_zs_1:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9001/data:/data
  environment:
   - REDIS_PORT=9001

 redis_zs_2:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9002/data:/data
  environment:
   - REDIS_PORT=9002

 redis_zs_3:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9003/data:/data
  environment:
   - REDIS_PORT=9003

 redis_zs_4:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9004/data:/data
  environment:
   - REDIS_PORT=9004

 redis_zs_5:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9005/data:/data
  environment:
   - REDIS_PORT=9005

 redis_zs_6:
  image: publicisworldwide/redis-cluster
  network_mode: host
  volumes:
   - ./data/redis/9006/data:/data
  environment:
   - REDIS_PORT=9006

docker-compose up 启动后,使用以下命令搭建集群:

docker run --rm -it inem0o/redis-trib create --replicas 1 \
10.43.2.6:8001 \
10.43.2.6:8002 \
10.43.2.6:8003 \
10.43.2.6:8004 \
10.43.3.7:9004 \
10.43.2.6:8005 \
10.43.3.7:9005 \
10.43.2.6:8006 \
10.43.3.7:9006 \
10.43.3.7:9001 \
10.43.3.7:9002 \
10.43.3.7:9003

你会发现集群搭起来了!有以下提示信息:

...master:
10.43.2.6:8001
10.43.3.7:9004
10.43.2.6:8002
10.43.3.7:9005
10.43.2.6:8003
10.43.3.7:9006
...
Adding replica 10.43.3.7:9001 to 10.43.2.6:8001
Adding replica 10.43.2.6:8004 to 10.43.3.7:9004
Adding replica 10.43.3.7:9002 to 10.43.2.6:8002
Adding replica 10.43.2.6:8005 to 10.43.3.7:9005
Adding replica 10.43.3.7:9003 to 10.43.2.6:8003
Adding replica 10.43.2.6:8006 to 10.43.3.7:9006
...

此时,集群是 广州、中山 各 3 个 master,不符合我们的场景,需要手工切换一下主从:

# 分别在从库 3 个端口做主从切换 10.43.2.6:9004-9006
redis-cli -h 10.43.2.6 -p 8004 CLUSTER FAILOVER
OK
redis-cli -h 10.43.2.6 -p 8005 CLUSTER FAILOVER
OK
redis-cli -h 10.43.2.6 -p 8006 CLUSTER FAILOVER
OK

3 个端口提主成功,10.43.2.6 此时运行 6 个 master,而 10.43.3.7 运行 6 个 slave 示例。

如何断网?很简单,iptables 无敌!

我们在广州(10.43.2.6)丢掉中山(10.43.3.7)的包就好了:

iptables -I INPUT -s 10.43.3.7 -pudp --dport 18001:18006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -ptcp --dport 18001:18006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -ptcp --dport 8001:8006 -j DROP && \
iptables -I INPUT -s 10.43.3.7 -pudp --dport 8001:8006 -j DROP

执行后,中山一直打印重连主库失败的日志,主库也探测到从库断开了,通过 CLUSTER NODES 命令可以获取各个节点状态。

结论一:A [6Master/0Slave] + B [0Master/6Slave],A 机房可读可写,B 机房不可读不可写(CLUSTERDOWN)

报错信息如下:

10.43.3.7:9006> set a12 2
(error) CLUSTERDOWN The cluster is down

另外,我还测试了主库分布在双机房的情况:

结论二:A [4Master/2Slave] + B [2Master/4Slave],A 机房可读可写,B 机房不可读不可写(CLUSTERDOWN)

结论三:A [3Master/3Slave] + B [3Master/3Slave],AB 机房均不可读不可写(CLUSTERDOWN)

为什么不可读?

因为请求从库它会自动转发(MOVED)到主库,而主库不可用(达不到半数以上节点),所以彻底凉了!

解决办法是不使用偶数节点,极端情况下(master 均等分布两地)会导致整个集群不可用。

实验完,不要忘了删掉规则,恢复网络:

iptables -D INPUT -s 10.43.3.7 -pudp --dport 18001:18006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -ptcp --dport 18001:18006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -ptcp --dport 8001:8006 -j DROP && \
iptables -D INPUT -s 10.43.3.7 -pudp --dport 8001:8006 -j DROP

(完)

最近在开发一个常驻进程、定时任务统一调度系统,以应对开发在进程管理方面遇到的各种复杂问题。

组里开发项目,一般来说是一个人承包整个项目,包括调度器设计,还有后台系统。我还有一部分工作,是队列相关的信息,这个由监控同学负责,到时候我后台聚合他的数据一并展示。

然后我就遇到问题了:

我以前刚入职公司的时候,使用一个开源的后台模板 vue-admin-template 二次开发了一个框架,两三年过去了,因为 nodejs 版本太老有些包下不来,自己升级了 nodejs 后算是解决了问题。

不过呢,我回到家之后想写代码,发现家里电脑和公司电脑环境不一样。因为我新后台系统升级了,旧后台系统咋办?不可能全部都升级 nodejs 的,后台太多了。

这个时候,切换 nodejs 版本显然就很重要了!后来我找到一个包,只需全局安装,就可以自由切换版本,非常好用!

npm install -g n

如果安装不了提示权限问题,可以 sudo 执行。

切换就很方便啦!执行以下命令即可切换到 v16.14.0 版本。

sudo n 16.14.0

一个优秀的产品,真的是简洁为美,用起来是那么的自然。而且,它包名就只有一个字母。

还有其他的用法,就不详细介绍了(好像也用不到),有兴趣可以去官网看看。