我们用 Go 写两个遍历两层 slice 的算法。
var items = make([][]int32, 1000)
func init() {
for i := 0; i < 1000; i++ {
items[i] = make([]int32, 1000)
for j := 0; j < 1000; j++ {
items[i][j] = rand.Int31n(2)
}
}
}
// 横向遍历
func sumRows() int {
var sum = 0
for
什么是基准测试
基准测试是测量一个程序在固定工作负载下的性能。我们通常会用来对比对同一个问题不同解决方案的性能,从而帮助我们做决定选择哪个方案更合理。
Go 的基准测试
Go 基准测试规则如下:
必须放在以 _test.go 结尾的文件中。
函数名必须以 Benchmark 开头
函数必须接受一个参数 *testing.B
没有返回值
基准测试受机器状态等因素的影响每次跑的结果很难保持完全一致,但是基本会在一个很小的范围内波动。
写一个简单的基准测试如下
import "testing"
func sum() int {
sum := 0
for i := 1; i &l
首先我们知道什么是流(stream),流物理设备的输入输出、存储设备上的文件的输入输出都映射到逻辑上的数据流,这是用来消除设备直接差异而抽象的一个概念。
通常情况下每个程序在启动的时候都会定义3个流:stderr、stdout、stderr,分别用来输入、输出、诊断和错误信息的输出,通常他们会被连接到用户终端(tty(4)),但是也可以修改到其他的文件和设备(重定向)。这取决于双亲进程的选择和设置。
Linux的本质是一切皆是文件,输入输出设备也是使用文件的形式存在和管理的,内核启动的时候默认会打开三个I/O设备文件:stdin、stdout、stderr,分别得到的描述符是0,1,2,并且他
我们在应用调试或者线上业务中经常会用到日志功能,而 Go 语言内置了 log 模块。
log 模块的使用
先来看下 log 模块的基本使用:
package main
import (
"log"
)
func main() {
log.Println("hello log.Println")
log.Printf("hello %s", "log.Printf")
}
我们运行一下可以看到如下输出:
> $ go run main.go
2018/10/29 10:45:39 hello log.Println
2018/10/29 10:45:39 hel
冒泡排序是最基本的排序算法,它的复杂度为O(n²)。
它的实现原理非常简单,就是从头遍历数组,如果第 i 个数比第 i + 1 个数大,那么就交换他们,这样遍历第一次就会让最大的数放到数组末尾,第二遍会把第二大的数放到数组倒数第二的位置,依次类推……
冒泡排序过程图形表示如下:
那么我们可以实现最基本的冒泡排序如下:
func BubbleSort1(list []int) {
n := len(list)
for i := 0; i < n; i++ {
for j := 0; j < n-1; j++ {
if list
整数类型
MySQL 包含以下几种整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT,分别使用8,16,24,32,64位存储空间。他们可以存储的范围为-2^(n-1)到2^(n-1)-1,其中 n 是存储空间位数。
整数类型有可选的 UNSIGNED 属性,表示不允许负数,这大致可以使正数的上限提升一倍,2^n - 1。有符号和无符号的使用相同的存储空间,并且具有相同的性能。
MySQL 可以为正数指定宽度,例如INT(11),对大多数应用没有意义,它不会限制值得合法范围,只是规定了 MySQL 的一些交互工具用来展示字符的个数而已。对于存储和计算来说 IN
MySQL支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要。不管存储哪种数据类型,下面几个简单的原则都有助于做出更好的选择。
更小的通常更好
一般情况下,尽可能使用可以正确存储数据的最小数据类型。更小的数据类型通常更快,因为他们占用的更少的磁盘、内存和CPU缓存,处理时需要的CPU周期更少。
简单最好
简单的数据类型的操作通常需要更少的CPU周期。例如整数比字符操作代价更低,因为字符集和校对规则使字符串比较比整型更复杂。
两个实际使用中的例子,一个是使用MySQL内置的类型而不是字符串存储时间,另一个是使用整型而不是字符串存储IP。
尽量避免NULL
很多表都包含可为 NULL
在面试过程中只要涉及到 Redis,一定会问到 Redis是多进程还是多线程?为什么单线程还可以有这么高的性能?
Redis为什么是单线程的
Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器的内存的大小和网络的带宽,而且单线程的性能已经非常高了,就没有必要使用多线程了,所以 Redis 是单进程单线程的。
提示:
如果我们运行的服务器是多核服务器,为了充分利用多核优势我们可以在单台服务器起多个 Redis 服务,或者架设 主从复制、哨兵模式、集群模式等多机方案。
Redis 服务运行时只是处理客户端请求是单进程单线程的,但是服务运行时会有其他进
缓存系统在现在的后台服务中是必不可少的,但缓存系统有很多方面的问题需要我们注意。
缓存穿透
缓存穿透是指当查询一个值不在缓存中的时候,系统会去底层数据库查询,当有大量的流量都命中了缓存中不存在的key那么缓存的存在就起不到作用,底层DB可能会挂掉。如果存在缓存穿透那么这就是漏洞。
解决方案
把查询结果为空的情况我们同样缓存起来,可以把缓存时间设置的稍微短点,当数据更新的时候记得更新缓存数据。
把所有可能存在的数据,哈希到一个 bitmap ,查询的时候使用该 bitmap 过滤不存在的key。
缓存雪崩
缓存雪崩是指缓存系统中的数据在同一时间过期,导致短时间内所有流量都打到底层存储,底层存
HTTPS是建立在安全信道之上的HTTP,使用了传输层加密的方式,而加密的方式就是TLS/SSL,TLS的前身是SSL,因为SSL这一术语比较常用所以我们仍然把证书叫做SSL,其实现在的证书都是TSL的。
TLS/SSL发展历史
1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
1996年,SSL 3.0版问世,得到大规模应用。
1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版。
2006年和2008