Blog

patience is the key in life


垂直分库

减轻单库的存储压力,采用:“专库专用”的原则,将数据库依照不同的业务模块进行拆分,进行分布式存储

垂直分表

避免单表数据量太大造成的存取速率低下,针对表中不常用的字段和常用的字段进行拆分,提高内存中能够存储的行数据的数量,减少io次数,提高读取速度

水平分库/分表

将一张表以水平切割的方式进行拆分,将拆分后的表分布存储到不同的库中,避免单表数据量过大


漏桶算法

固定桶容量(负载上限)以及固定的出水速率(处理请求),不固定的入水速率(请求量)
优点:实现简单,可以控制限流速率,避免网络拥塞
缺点:无法应对突发的激增流量,可能造成大量请求的丢失

令牌桶算法

按一定速率生成令牌,到来的请求必须有令牌分配才可以被处理,令牌数目到达上限后就不再生成令牌,直至有请求到来消耗之
优点:可以应对激增流量
缺点:令牌产生速率和桶的容量设置不合理,可能会出现问题比如大量的请求被丢弃、系统过载


当客户端发来的请求连续多次失败后,为了减轻服务端的压力,引入了熔断器

熔断器有三种状态

  1. 打开——没有请求能通过
  2. 关闭——所有请求都能通过
  3. 半开——请求可以通过,但要跟踪响应状态来判断服务器此时的状态用以作为是否变更熔断器状态的依据

执行逻辑:
当有连续到来的请求响应失败后,熔断器打开
经过一段时间冷却后,熔断器恢复到半开状态
半开状态下的熔断器依据请求处理的结果来决定变更为哪种状态

放行通过的请求要继续跟踪执行结果,根据执行结果对熔断器中的计数器进行修改


InnoDB

  1. 支持事务
  2. 聚簇索引
  3. 锁的最小颗粒度是行级锁
  4. count语句需要扫描全表

MyISAM

  1. 不支持事务
  2. 非聚簇索引
  3. 锁的最小颗粒度是表级锁
  4. 用一个变量维护行数,所以count语句的时间复杂度为O(1)


测试是否有异常抛出

测试_有异常

1
2
3
4
5
6
7
8
9
10
11
12
package JUnit;

import org.junit.Test;

public class JUnit_04_exception {

@Test(expected = NumberFormatException.class)
public void testA() {
int a = Integer.parseInt("&||!");
}
}

测试结果

测试_无异常

1
2
3
4
5
6
7
8
9
10
11
12
package JUnit;

import org.junit.Test;

public class JUnit_04_exception {

@Test(expected = NumberFormatException.class)
public void testA() {
int a = Integer.parseInt("1");
}
}

测试结果


  1. Before注解

:在标有@Test注解的方法执行前先执行,每一个测试方法的执行都会执行一遍Before注解所在的方法

  1. After注解

: 在标有@Test注解的方法执行后再执行,每一个测试方法执行完都会执行一遍After注解所在的方法

  1. Test注解

: 表明该方法为测试方法,可以直接启动,不用通过main()函数入口启动

  1. BeforeClass注解

: 在测试类加载完,所有方法执行前执行,由于该注解只能存在于静态方法上,所以只执行一次

  1. AfterClass注解

: 在所有方法执行完毕后执行,由于该注解只能存在于静态方法上,所以只执行一次

测试代码

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
29
30
31
32
package JUnit;

import org.junit.*;

public class JUnit_03_sequences {

@After
public void shutDown() {
System.out.println(" after...");
}
@AfterClass
public static void afterClass() {
System.out.println("afterClass...");
}
@BeforeClass
public static void beforeClass() {
System.out.println("beforeClass...");
}
@Before
public void setUp() {
System.out.println(" before...");
}
@Test
public void testA(){
System.out.println(" testA...");
}
@Test
public void testB(){
System.out.println(" testB...");
}
}

测试结果:


  1. new是返回一个指向新分配了内存空间并初始化为零值的对象的指针

  1. make是返回一个新分配了内存并初始化的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
"reflect"
)

func main() {

// make
object := make([]int, 3)
fmt.Println(reflect.TypeOf(object)) // []int
fmt.Println(object) // [0 0 0]

// new
object2 := new(int)
fmt.Println(reflect.TypeOf(object2)) // *int
fmt.Println(object2) // 0xc00000a108
fmt.Println(*object2) // 0
}


  1. 先通过go env命令查看相关变量的值

    1
    go env

  2. 设置GO111MODULE

    1
    go env -w GO111MODULE=on // 启用gomodule
  3. 设置GOPROXY

    1
    go env -w GOPROXY=https://goproxy.cn,direct // 使用国内代理
  4. 在GOPRIVATE中设置私有库地址

    1
    go env -w GOPRIVATE=XXX


注意点:变量命名时大小写问题!

  1. 编码:struct ==》json
  2. 解码:json ==》 struct
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
29
30
31
32
33
34
35
36
37
package main

import (
"encoding/json"
"fmt"
)

// 定义一个结构体
type Music struct {
Name string `json:"名称"` // 字段大小写命名问题!!!
Singer string `json:"歌手"`
}

func main() {

// 创建结构体变量并赋值
music := Music{"关忆北", "宋冬野"}

// 编码:结构体-》json字符串
myMusic, err := json.Marshal(music) // 结构体-》字节数组
if err != nil {
fmt.Println(err)
} else {
fmt.Println(myMusic)
fmt.Println(string(myMusic)) // 字节数组-》json字符串
}

// 解码:json字符串-》结构体
music2 := Music{}
err = json.Unmarshal(myMusic, &music2)
if err != nil {
return
} else {
fmt.Println(music2)
}
}

测试结果


golang中的interface类型本质上是指针

  1. 实现多态

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    package main

    import "fmt"

    // interface本质是一个指针
    type Animal interface {
    Sleep()
    GetType() string
    GetColor() string
    }

    // Cat、Dog 子类实现接口中的全部方法
    type Cat struct {
    Type string
    Color string
    }
    type Dog struct {
    Type string
    Color string
    }

    func (this *Cat) Sleep() {
    fmt.Println("Cat is sleeping")
    }
    func (this *Dog) Sleep() {
    fmt.Println("Dog is sleeping")
    }
    func (this *Cat) GetType() string {
    return this.Type
    }
    func (this *Dog) GetType() string {
    return this.Type
    }
    func (this *Cat) GetColor() string {
    return this.Color
    }
    func (this *Dog) GetColor() string {
    return this.Color
    }

    // 多态-》父类变量(指针)指向子类变量(引用)
    func ShowAnimal(animal Animal) {
    animal.Sleep()
    fmt.Println("Type: ", animal.GetType())
    fmt.Println("Color: ", animal.GetColor())
    }

    func main() {

    // 子类对象
    cat := Cat{
    Type: "Cat",
    Color: "White",
    }
    dog := Dog{
    Type: "Dog",
    Color: "Yellow",
    }

    //
    ShowAnimal(&cat)
    ShowAnimal(&dog)
    }

    测试结果

  2. 万能接口interface{},所有基本数据类型包括struct都实现了它(类似Java中的Object),因此可以用来接参并实现反射

    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
    29
    30
    31
    package main

    import "fmt"

    // 空接口也称为万能接口,基本数据类型如int、string、float、struct等都实现了它
    func myFunc(arg interface{}) {
    fmt.Println("myFunc is used...")
    fmt.Println("arg is ", arg)

    // 断言机制
    value, ok := arg.(int) // 判断接到的参数类型是否为int
    if ok {
    fmt.Println("arg type is int and", "value is ", value)
    } else {
    fmt.Println("arg is not int and", "value is ", value)
    }

    }

    type Man struct {
    name string
    }

    func main() {
    // 引用任意数据类型
    myFunc(1)
    myFunc("111")
    myFunc("1.11")
    myFunc(Man{"cx"})
    }

    测试结果

0%