我们不能失去信仰

我们在这个世界上不停地奔跑...

0%

今天突然几个接口报错了。仔细一看是报如下错误:

**UnicodeDecodeError: 'gbk' codec can't decode bytes in position 8-9: illegal multibyte sequence**

一看到这个错误立马就想到了 Python2 的编码问题,但是好好的系统看了 GIT 提交记录也没人改过编码方面的代码,接口都是封装好的,突然出现这种情况直接使用 Python2 的字符处理方法可能是处理不了的。

再看了下,是数据在返回前,要进行 json 序列化,就在序列化这一步报错了。

1
site-packages/simplejson/encoder.py

然后就想看看到底是哪些地方序列化失败了,由于数据量非常庞大,这个报错也不会具体指明是哪个数据,所以我就只能使用二分法来调试,最终找到了问题所在,其中某个对象有个name字段,这个name字段出现了乱码。

但是好端端的怎么可能出现乱码呢,顺着猜想打开数据库,desc 了一下表,果不其然,由于 name 字段在代码里没有限制长度,再加上 Python2 直接使用切片是会截断中文造成乱码的,最终存储到数据库里的数据的最后一位就是一个乱码字符,然后在返回的时候json序列化就报错了。

下面我们来看下 Python2 中对中文字符的一些不同:

1
2
3
4
5
6
7
>>> a = '我是谁'
>>> len(a)
9
>>> len(a.decode('utf-8'))
3
>>>
>>> a.decode('utf8')[0:2].encode('utf8')

如果要正确切割中文字符串,应该先 decode 后,再进行切割。

还有就是写代码一定要对输入进行校验。

以下讨论都基于 MySQL 的 InnoDB 存储引擎上。

结论: 只要 redo log 和 binlog 保证持久化到磁盘,就能确保 MySQL 异常重启后,数据可以恢复。

崩溃恢复逻辑

  • 如果 redo log 里面的事务时完整的,也就是已经有了 commit 标识,则直接提交
  • 如果 redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整,如果是则提交,否则回滚事务

这里恢复逻辑是都依赖了 redo log 的两阶段提交中的 prepare 和 commit 。

阅读全文 »

家里需要连接有线网络的设备越来越多了,三台 Linux 服务器,一台树莓派设备,但是路由器上面只有三个网口,如果再买一台路由器走桥接又得多增加一个设备,多一个耗电设备,还好,其中有台 Linux 主机有两个网口,就想着应该可以设置桥接,路由器连接这台服务器,然后这台服务器的另一个网口给树莓派使用。

流程

  • 安装 brctl 工具

    sudo apt install bridge-utils

  • 使用 brctl 工具创建网桥

    sudo brctl addbr br0

  • 将两个网口都添加到网桥上,我这里的网卡名并不是 eth0、eth1 而是 enp1s0 和 enp2s0 ,在执行下面的命令的时候确认好你的网口名,可以通过 ifconfig 命令查看。

    阅读全文 »

最近本来是准备在黑群晖上面创建一个盘拿来做苹果电脑的 Time Machine 备份的,设置好了后,发现网速极慢,猜想可能是由于我 SSH 上去改了网络配置的原因。这样的事情已经发生了不止两三次了,有几次系统直接崩了,实在是难受,并且慢慢就失去了黑群晖的兴趣,系统偶尔不太稳定,自己的需求大多数时候必须要手动 SSH 上去改配置才能实现。思来想去,我为什么不直接装一台 Linux 呢,说干就干,下了 Ubuntu 最新的 20.xx 版本,先刷入 U 盘,然后改 Bios,因为我这个是蜗牛星际主机,不改 Bios 原来的设置可能会导致开机引导不识别硬盘,然后就是装系统了。

阅读全文 »

前言:

由于 UE4 像素流官方提供的服务基本都需要在 Windows 环境上面运行。考虑到具备高性能 GPU 的服务器性价比又太低,正好手上有台 Windows 机器,但是又没有公网IP,如何让其支持公网访问成了一个问题。

如果能利用上现有的 Linux 公网服务器及手中的 Windows 就最好不过了。

  1. 本地内网 Windows 机器跑像素流及“信令和Web服务器”
  2. 使用 Linux 搭建支持信令服务器的网络打洞/中继服务及Web服务器的转发服务,以支持外网访问。

信令和Web服务器: 这个词是官方的叫法,其实它实际上只表示一个组件,这个组件同时包含了信令服务器和Web服务器,他们分别有不同的用途,我们也需要分别对其进行网络穿透支持。

需要解决的问题:

  1. UE4 像素流使用到了 WebRTC(网页即时通信),在移动运营商的网络中如4G网络,一般是不支持用户通过 WebRTC 协议直接与服务器建立连接,需要自建 STUN/TURN 服务,通过中继服务器进行网络中继解决信令服务器的网络问题及在内网访问问题。
  2. 信令和Web服务器,官方只提供了 Windows 版本,即无法部署到 Linux 服务器。
  3. 内网穿透解决 Web服务器公网访问问题

搭建教程

阅读全文 »

前言

以下内容均在 MySQLInnoDB 存储引擎下完成

主键自增取值策略

  • 如果插入数据时 Id 字段指定为 0、Null 或未指定值,那么就把这个表当前的 AUTO_INCREMENT 值填充到自增字段中。

tips:AUTO_INCREMENT 的值表示下一个插入行的自增值。

  • 如果插入数据时 Id 字段指定了具体的值,就直接使用语句里指定的值。根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是X,当前的自增值是Y:
  1. 如果 X < Y, 那么这个表的自增值不变。

  2. 如果 X >= Y,就需要把当前自增值修改为新的自增值。新的自增值生成算法是: 从 auto_increment_offset 开始,以 auto_increment_increment 为步长,持续叠加,直到找到第一个大于X的值,作为新的自增值。

    补充: auto_increment_offsetauto_increment_increment 是两个系统参数,分别用来表示自增的初始值和步长,默认都是1。

备注:在一些场景下,使用的就不全是默认值。比如,双 M 的主备架构里要求双写的时候,我们就可能会设置成 auto_increment_increment=2,让一个库的自增 Id 都是奇数,另一个库的自增 Id 都是偶数,避免两个库生成的主键发生冲突。

阅读全文 »

数据库是如何实现隔离级别(InnoDB)

事务隔离性,本质上解决事务的读写冲突。

  • 事务的四个特性ACID

    原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)

  • 事务的隔离级别

    事务的隔离级别分为 未提交读提交读可重复读串行化

  • 隔离级别的实现

    阅读全文 »

线性排序算法的复杂度低,如桶排序、计数排序、基数排序。但是它们对排序的数据都有比较苛刻的要求,应用不是非常广泛。如果数据特征比较符合这些排序算法的要求,应用这些算法,会非常高效,线性时间复杂度可以达到O(n)。

桶排序和计数排序的排序思想是非常相似的,都是针对范围不大的数据,将数据划分为不同的桶来实现排序。基数排序要求数据可以划分成高低位,位之间有递进关系。比较两个数,我们只需要比较高位,高位相同的再比较地位。而且每一位的数据范围不能太大,因为基数排序算法需要借助桶排序或者计数排序来完成每一位的排序工作。

线性排序算啊的时间复杂度比较低,适用场景比较特殊。所以如果要写一个通用的排序函数,不能选择线性排序算法。

如果对小规模数据进行排序,可以选择时间复杂度是O(n方)的算法;如果对大规模数据进行排序,时间复杂度是 O(nlogn)的算法更加高效。所以,为了兼顾任意规模数据的排序,一般都会首选时间复杂度是O(nlogn)的排序算法来实现排序函数。

Java中使用堆排序实现排序函数,C语言中使用快速排序实现排序函数。但是使用归并排序的却不多,即使归并排序最坏的情况时间复杂度都是O(nlogn),但是它并不是原地排序算法,它的空间复杂度为O(n)。

优化快速排序

阅读全文 »