vagrant ssh 进入到虚拟机,df -h 查看默认的 /dev/sda1 是 40G,现在要扩容到 400G

安装 vagrant-disksize

在宿主机安装 vagrant-disksize 插件

1
vagrant plugin install vagrant-disksize

配置 Vagrantfile

编辑 vagrant-lamp 目录下的 Vagrantfile 文件

1
2
3
4
Vagrant.configure("2") do |config|
...
config.disksize.size = "400GB" <- 加上这一句
end

扩容

vagrant-disksize 插件仅仅是调整了虚拟硬盘的大小而没有增加 /dev/sda1 的大小,需要在 Linux 虚拟机中进行分区扩容操作。按照以下步骤进行操作:

  1. 在 Linux 虚拟机中使用 lsblk 命令查看当前磁盘分区情况
1
lsblk

这个命令会显示出当前系统中的磁盘设备及其分区信息。可以看到/dev/sda1 分区的大小。

  1. 停止所有Docker容器,以确保磁盘上没有正在写入的数据。
阅读全文 »

设计 API 授权,或者调用第三方 API 时,经常会接触到:

1
Authorization : Bearer Tokenxxxxxx

有没有疑惑为何不直接写成这样就得了:

1
Authorization : Tokenxxxxxx

这是因为 W3C 的 HTTP 1.0 规范,Authorization 的格式是:

1
Authorization: <type> <authorization-parameters>

所以 Bearer 是授权的类型,常见的授权类型还有:

  • Basic 用于 http-basic 认证;
  • Bearer 常见于 OAuth 和 JWT 授权;
  • Digest MD5 哈希的 http-basic 认证 (已弃用)
  • AWS4-HMAC-SHA256 AWS 授权

视频链接地址:https://www.bilibili.com/video/BV19r4y1w7Nx

一、Golang“调度器”的由来?

(1) 单进程时代不需要调度器

我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU。早期的操作系统每个程序就是一个进程,直到一个程序运行完,才能进行下一个进程,就是“单进程时代”

一切的程序只能串行发生。

早期的单进程操作系统,面临2个问题:

1.单一的执行流程,计算机只能一个任务一个任务处理。

2.进程阻塞所带来的CPU时间浪费。

那么能不能有多个进程来宏观一起来执行多个任务呢?

后来操作系统就具有了最早的并发能力:多进程并发,当一个进程阻塞的时候,切换到另外等待执行的进程,这样就能尽量把CPU利用起来,CPU就不浪费了。

阅读全文 »

通道和阻塞

通道(channel)和协程(goroutine)是实现Go并发程序的两种机制。其中,通道又分为无缓冲通道和有缓冲通道两种,在编写实际的并发程序时,基本都使用异步模式的有缓冲通道。通道又可细分为支持读和写的双向通道,只读的通道,只写的通道三种。

通道阻塞场景

无论是有缓存通道、还是无缓冲通道都存在阻塞的情况。阻塞场景共4个,有缓存和无缓冲各2个。

无缓冲通道的特点是,发送的数据需要被读取后发送才会完成(同步),它阻塞场景是:

  • 通道中无数据,但执行读通道。
  • 通道中无数据,向通道写数据,但无协程读取。

有缓存通道的特点是,有缓存时可以向通道中写入数据后直接返回(异步),它阻塞场景是:

  • 通道缓存无数据,但执行读通道(接收数据)。
  • 通道缓存已经占满,向通道写数据(发送数据),但无协程读。

使用协程、通道和select

Go的select关键字可以让我们操作多个通道,将协程(goroutine),通道(channel)和select结合起来构成了Go的一个强大特性。

阅读全文 »

说明:理解本文的前提是你对Go语言已有一定的基础了解。

什么是指针:即一个指针变量指向一个值的内存地址。

使用值类型和指针类型的区别
首先,我们来看一个计算面积的代码,如下所示。

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
package main

import (
"fmt"
)

type Rect struct { //定义一个结构体
width float64
length float64
}

func (rect Rect) area() float64 { //定义一个方法,按值传递
return rect.width * rect.length
}

func (rect *Rect) area1() float64 { //定义一个方法,按指针传递
rect.width *= 2
rect.length *= 2
return rect.width * rect.length
}

func main() {
var rect = new(Rect) //使用new函数创建一个结构体指针rect,也就是说rect的类型是*Rect
rect.width = 100
rect.length = 200
fmt.Println("Width:", rect.width, "Length:", rect.length,"Area:", rect.area()) //通过结构体指针类型的变量调用area()方法
fmt.Println("Width:", rect.width, "Length:", rect.length,"Area:", rect.area1())
}

在Go语言中,默认是按值传递。当一个变量当作参数传递的时候,会创建一个变量的副本,然后传递给函数或者方法,你可以看到这个副本的地址和变量的地址是不一样的。当变量当做指针被传递的时候,一个新的指针被创建,它指向变量同样的内存地址,所以你可以将这个指针看成原始变量指针的副本。

阅读全文 »

一、最早的Web服务器

最早的Web服务器简单地响应浏览器发来的HTTP静态文件请求,并将存储在服务器上的静态文件(例如: jpg、htm、html)返回给浏览器。如图是处理流程

比如我访问:http://www.example.com/index.html,那么网络服务器就会去对应目录中找到 index.html这个文件,并返回给浏览器。

二、CGI的出现

首先说明:CGI是一种协议

事物总是不断发展,网站也越来越复杂,所以出现动态技术。但是Web服务器并不能直接运行 php/asp 这样的文件,自己不能做,外包给别人吧,但是要与第三做个约定,我给你什么,然后你给我什么,就是我把请求参数发送给你,然后我接收你的处理结果再给客户端。这个约定就是 CGI协议(Common Gateway Interface),协议只是一个“规定、规则”,理论上用什么语言都能实现,比如用 vb/c/perl/php/python 来实现。

在2000年或更早的时候,CGI 比较盛行。那时,Perl 是编写 CGI 的主流语言,以至于一般的 CGI 程序(遵循 CGI 协议的程序)就是 Perl 程序(例如世界上80%的网站所采用的编程语言 php 语言刚开始的版本就是用Perl语言写的)。

CGI 是 “Common Gateway Interface” 的缩写,翻成中文叫“公共网关接口”,它是 web 服务器与外部应用程序(CGI 程序)之间传递信息的接口标准。通过 CGI 接口,web 服务器就能够获取客户端提交的信息,并转交给服务器端的 CGI 程序处理,最后返回结果给客户端。也就是说,CGI 实际上是一个接口标准。我们通常所说的 CGI 是指 CGI 程序,即实现了 CGI 接口标准的程序。只要某种语言具有标准输入、输出和环境变量,如 perl/PHP/C 等,就可以用来编写 CGI 程序。CGI 只是接口协议,根本不是什么语言。

阅读全文 »

日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。作为开发,我们重点需要关注的是二进制日志(binlog)和事务日志(包括redo logundo log),本文接下来会详细介绍这三种日志。

binlog

binlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlogmysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。

逻辑日志:可以简单理解为记录的就是sql语句
物理日志:因为mysql数据最终是保存在数据页中的,物理日志记录的就是数据页变更

binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

binlog使用场景

在实际应用中,binlog的主要使用场景有两个,分别是主从复制数据恢复

  1. 主从复制:在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致。
  2. 数据恢复:通过使用mysqlbinlog工具来恢复数据。

binlog刷盘时机

对于InnoDB存储引擎而言,只有在事务提交时才会记录biglog,此时记录还在内存中,那么biglog是什么时候刷到磁盘中的呢?mysql通过sync_binlog参数控制biglog的刷盘时机,取值范围是0-N

  • 0:不去强制要求,由系统自行判断何时写入磁盘;
  • 1:每次commit的时候都要将binlog写入磁盘;
  • N:每N个事务,才会将binlog写入磁盘。

从上面可以看出,sync_binlog最安全的是设置是1,这也是MySQL 5.7.7之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。

阅读全文 »

Version

PHP version 7.4

问题呈现

最小化分析代码:

1
2
3
4
5
6
7
8
9
$data = ['foo', 'bar'];

foreach ($data as &$item) {
}

foreach ($data as $item) {
}

print_r($data);

输出结果:

1
2
3
4
5
Array
(
[0] => 'foo'
[1] => 'foo'
)

我们可以发现,$data的值莫名奇妙变了,而它只是经过了两个空循环而已,发生了什么?!

先总结一下 PHP 中两条关于引用的两个规则:

  • 给引用变量赋值,实际上是给引用所指向的变量赋值
  • 一个引用变量可以被修改为对另外一个变量的引用

下面我来一行行代码分析产生这个问题的原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$data = ['foo', 'bar'];

// 循环开始,$item 变量不存在,新建一个$item 变量,且是一个引用变量,它不指向任何变量地址
foreach ($data as &$item) {
// loop 1: 执行了 $item = &$data[0];$item 指向 $data[0] 的地址
// loop 2: 执行了 $item = &$data[1];$item 指向 $data[1] 的地址
}
// 提示:这个循环没有改变 $data 的数据,只是 $item 依然指向第二个元素 的地址

// 循环开始,$item 变量存在,不会新建变量
foreach ($data as $item) {
// loop 1: 执行了 $item = $data[0];$item 所指向的变量(即 第二个元素)的值被修改为$data[0](即'foo'),这里已经导致了$data 两个元素都等于 'foo'
// loop 2: 执行了 $item = $data[1];由于$item 指向的是$data[1],实际上相当于执行$data[1] = $data[1],没有任何意义
}
// 最后$data 中的两个元素都是 'foo'

如何避免这个问题1:

1
2
3
4
5
foreach ($data as &$item) {

// 每次 loop 销毁$item (实际上只要在最后一次 loop 销毁即可,因此你可以把 unset 写到 foreach 后面,就是不是很好看)
unset($item);
}

如何避免这个问题2:

不使用引用

Version

mysql version 8.0.13

事务隔离级别概述

mysql 中,InnoDB 所提供的事务符合 ACID 的要求,而事务通过事务日志中的 redo log 和 undo log 满足了原子性、一致性、持久性,事务还会通过锁机制满足隔离性,在 InnoDB 存储引擎中,有不同的隔离级别,它们有着不同的隔离性。

什么是事务的隔离级别?如果只是从概念上理解的话可能比较模糊,咱们直接看看不同隔离级别下的实际表现是什么样子的,再结合理论去理解,就会明了很多。首先,打开两个终端,同时连接到当前数据库,如下图所示,我们对两个回话进行编号,并且以颜色区分,1号会话使用黄色进行标识,2号会话使用红色进行标识。

两个会话使用相同的数据库。

两个会话中同时各自开启一个事务。

由于下面的所有操作会在两个会话中来回切换,所以,为了方便描述,我们为每个操作的顺序进行编号,例如下图中,我们先在会话1的事务1中执行了更新操作,然后在事务1中执行了查询操作,最后又在会话2中的事务2中执行了查询操作,按照操作顺序,为各个操作进行了顺序编号。

阅读全文 »

系统环境介绍

Win 10 2004
WSL2(Ubuntu 20.04)
Docker 19.03.13

启用 Linux 子系统

打开 控制面板 -> 程序 -> 启用或关闭Windows功能。找到适用于Linux的Windows子系统虚拟机平台,勾选这两项之后确定,并重新启动计算机。

切换系统 WSL 默认版本到 2

使用管理员用户打开 Windows PowerShell,运行:

1
wsl --set-default-version 2

注意,有可能会出现如下提示:

WSL 2 需要更新其内核组件。有关信息,请访问 https://aka.ms/wsl2kernel

出现这个提示,说明需要更新 WSL2 的内核。按照提示打开链接。点击下图中的下载链接,下载并安装 WSL2 内核。

阅读全文 »
0%