Demo

文章头部frot-matter编写参考

所有样式来源于:https://volantis.js.org/v5/tag-plugins/

text

下划线 的文本;带 着重号 的文本;带 波浪线 的文本;带 删除线 的文本

键盘样式的文本: + D

密码样式的文本:这里没有验证码

demo

(LeetCode系列)刷题记

饶大文章汇总

饶大文章汇总

Go语言

深度解密系列

Go语言其他

汇总

gin+docker部署Golang应用

使用gin编写Go的后端程序,然后使用docker打包成镜像并在我们的阿里云ECS上进行部署

编写Go后端程序

项目目录如下:

1
2
3
4
go-web
├── go.mod
├── main.go
├── Dockerfile

main.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import (
"github.com/gin-gonic/gin"
"net/http"
"time"
)

/**
* @Author: yirufeng
* @Date: 2021/7/10 9:04 下午
* @Desc:
**/

type User struct {
Username string `json:"username"`
}

func main() {
engine := gin.Default()

engine.GET("/", func(c *gin.Context) {
startTime := time.Now()

c.JSON(http.StatusOK, gin.H{
"method": http.MethodGet,
"elapsedTime/ms": time.Since(startTime).Milliseconds(),
})
})

engine.POST("/", func(c *gin.Context) {
startTime := time.Now()

var u User
err := c.BindJSON(&u)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"error": err.Error(),
})
return
}

c.JSON(http.StatusOK, gin.H{
"method": http.MethodPost,
"elapsedTime/ms": time.Since(startTime).Milliseconds(),
"username": u.Username,
})
})

engine.Run(":8081")
}
go

go微服务环境搭建

本环境基于Macos搭建,运行的go版本是1.14.11,由于原先使用的1.15.5依赖包对应版本不存在或冲突修改后无法解决,所以只能修改go版本

沈逸老师go-micro搭建环境

搭建成功使用命令:

  1. go get github.com/micro/go-micro/v2
  2. go get github.com/micro/go-plugins/registry/consul/v2

参考:https://segmentfault.com/a/1190000023529475

搭建过程中遇到的问题:

1
2
3
4
5
6
7
8
9
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
../../../../../go/pkg/mod/github.com/coreos/etcd@v3.3.25+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:114:78: undefined: resolver.BuildOption
../../../../../go/pkg/mod/github.com/coreos/etcd@v3.3.25+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:182:31: undefined: resolver.ResolveNowOption
# github.com/coreos/etcd/clientv3/balancer/picker
../../../../../go/pkg/mod/github.com/coreos/etcd@v3.3.25+incompatible/clientv3/balancer/picker/err.go:37:44: undefined: balancer.PickOptions
../../../../../go/pkg/mod/github.com/coreos/etcd@v3.3.25+incompatible/clientv3/balancer/picker/roundrobin_balanced.go:55:54: undefined: balancer.PickOptions
# github.com/micro/go-micro/transport/quic
../../../../../go/pkg/mod/github.com/micro/go-micro@v1.18.0/transport/quic/quic.go:54:12: q.s.Close undefined (type quic.Session has no field or method Close)
../../../../../go/pkg/mod/github.com/micro/go-micro@v1.18.0/transport/quic/quic.go:121:3: unknown field 'IdleTimeout' in struct literal of type quic.Config

解决办法:go.mod文件夹中加上下面两句话

1
2
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
replace github.com/lucas-clemente/quic-go => github.com/lucas-clemente/quic-go v0.14.1

参考:

  1. https://github.com/etcd-io/etcd/issues/12124#issuecomment-674368288
  2. https://github.com/etcd-io/etcd/issues/11931
  3. https://www.codenong.com/cs109250534/
  4. 推荐:https://studygolang.com/articles/32791

遇到的问题2:panic: qtls.ConnectionState not compatible with tls.ConnectionState

最后以上的问题都采用一种策略,删除原有go版本并且下载go1.14.11版本得到了解决,之后执行命令go get -u github.com/micro/go-micro
就是go的版本不要使用go1.15

consul集群搭建

参考博主文章

租房网搭建环境:

前言

如果网速很慢,经常io timeout,可以执行如下两条命令:

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

安装protoc

  1. 下载可执行文件
  2. 下载完成后,解压到~/Library,并修改文件夹名字为proto,并进入终端配置系统环境变量:export PATH=$PATH:$GOPATH/bin:$HOME/Library/protoc/bin
  3. 采用命令protoc --verison进行验证。配置成功,会有类似输出:libprotoc 3.11.2

安装protoc-gen-go

  1. go get -u github.com/golang/protobuf/protoc-gen-go
  2. 进入到目录:cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go
  3. 执行go build,生成可执行文件protoc-gen-go
  4. 将我们的可执行文件复制到$GOPATH/bin下:cp protoc-gen-go $GOPATH/bin

安装protoc-gen-micro

如果实在get不下来我们可以直接clone代码下来,然后go build

  1. go get github.com/micro/protoc-gen-micro
  2. 进入到$GOPATH/src/github.com/micro/protoc-gen-micro目录下,进行go build,生成可执行文件protoc-gen-micro
  3. 将我们的可执行文件复制到$GOPATH/bin下:cp protoc-gen-micro $GOPATH/bin

测试:在goland中新建一个项目,并且编写一个proto文件夹,编写demo.proto文件并填入如下内容

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
syntax = "proto3";

package myproto;

option go_package = "./";


//客户端发送给服务端的
message HelloRequest {
string name = 1;
}

//服务端返回给客户端的
message HelloResponse {
string msg = 1;
}


//客户端向服务端发送的请求
message NameRequest {
string name = 1;
}

//服务端返回给客户端的响应
message NameResponse {
string msg = 1;
}



//定义服务
service HelloService {
//函数的传入和传出就是我们自己要定义的消息类型
//一个打招呼的函数
rpc SayHello (HelloRequest) returns (HelloResponse) {}
//一个说名字的函数
rpc SayName (NameRequest) returns (NameResponse) {}
}

进入到proto文件所在的目录,执行protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. *.proto
当前目录下生成两个文件:demo.pb.go和demo.pb.micro.go

安装go-micro

执行命令:go get github.com/micro/go-micro/v2@latest

安装micro

方式一:

执行命令:go get github.com/micro/micro/v2@latest

通过该方法安装的micro默认使用的服务发现组件是mdns,没有集成Consul、Etcd等第三方的组件。我们后面需要使用Consul,所以此时需要自己手动编译安装。

方式二:

  1. git clone https://github.com/micro/micro.git
  2. 进入到clone后的文件夹,新建plugins.go文件,键入如下内容:
    1
    2
    3
    4
    5
    package main

    import (
    _ "github.com/micro/go-plugins/registry/consul/v2"
    )
  3. 最后,重新编译安装:go install
  4. 完成后,执行如下命令检查micro是否安装成功:micro --version。如果有类似输出说明安装成功:
    1
    micro version 2.0.0

方法三:直接下载二进制文件

  1. 点击下载地址进行下载
  2. 将我们的micro可执行程序移动到/usr/local/bin/

微服务项目实战

微服务基础 微服务,微服务架构,微服务框架 微服务:应该使用这种方法而设计的一个应用,也就是设计出来的一个应用微服务架构:一种设计方法微服务框架(比如我们后面用到的micro):将复杂的系统使用组件化的方式进行拆分,并且使用轻量级通讯方式进行整合的一种设计方法。微服务是通过这种架构设计方法拆分出来的一个独立的组件化的小应用。注意:这...

排序算法总结

基础排序算法

点击查看代码

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

/**
* @Author: yirufeng
* @Date: 2021/4/13 8:28 下午
* @Desc: 选择排序

时间复杂度:假设数组中有n个数字
大循环需要遍历n-2趟,然后每一个大循环中,
我们都需要从开始的数字一直到最后选出最小的数字(时间复杂度:O(n)),然后填充到当期那还没有排好序的起始位置

最后总的时间复杂度:O(n^2),
空间复杂度:O(1)。
稳定的排序算法(因为两个相等的数字前面那个一定是排序的时候第一个会被放置到前面的)
**/

func SelectedSort(nums []int) {
selectedSort(nums)
}

func selectedSort(nums []int) {
var min int
for i := 0; i < len(nums)-1; i++ {
//每次从nums[i]开始起
min = i
//依次与后面比对来选择最小的
for j := i + 1; j < len(nums); j++ {
if nums[min] > nums[j] {
min = j
}
}
//交换nums[min]与nums[i]
nums[i], nums[min] = nums[min], nums[i]
}
}

选择排序

选择排序总结:

  1. 时间复杂度:O(n^2)
  2. 空间复杂度:O(1)。
  3. 不稳定的排序算法(比如A 80 B 80 C 70 这三个卷子从小到大排序,最后将会变成CBA,但是稳定的应该是CAB)

三个版本的冒泡排序:

  1. 最基本的
  2. 如果某次冒泡的时候没有交换元素,那么说明这一趟以及后面的元素都是有序的,之后后面我们就不再需要进行冒泡,可以直接退出
  3. 在第二种改进的基础上再使用一个变量,表示我们最后交换的位置,下次遍历到这个位置就可以了

点击查看代码

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
65
66
67
68
69
70
71
72
73
74
75
76
77
package basic_sort

/**
* @Author: yirufeng
* @Date: 2021/4/13 8:28 下午
* @Desc:

有好几个版本:
1. 最基本的
2. 如果某次冒泡的时候没有交换元素,那么说明这一趟以及后面的元素都是有序的,之后后面我们就不再需要进行冒泡,可以直接退出
3. 在第二种改进的基础上再使用一个变量,表示我们最后交换的位置,下次遍历到这个位置就可以了
**/

func BubbleSort(nums []int) {
bubbleSortV2(nums)
}

//最基本的
func bubbleSortV1(nums []int) {
for i := 1; i < len(nums); i++ { //冒泡的次数
for j := 0; j < len(nums)-i; j++ {
//如果前面比后面大就交换
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1], nums[j]
}
}
}
}

//如果某次冒泡的时候没有交换元素,那么说明这一趟以及后面的元素都是有序的,之后后面我们就不再需要进行冒泡,可以直接退出
func bubbleSortV2(nums []int) {
//表示某一趟是否有元素交换
flag := true
for i := 1; i < len(nums); i++ { //冒泡的次数
flag = true
for j := 0; j < len(nums)-i; j++ {

//如果前面比后面大就交换
if nums[j] > nums[j+1] {
flag, nums[j], nums[j+1] = false, nums[j+1], nums[j]
}
}
//如果没有元素交换,说明已经有序,直接退出即可
if flag {
break
}
}
}

//在第二种改进的基础上再使用一个变量,表示我们最后交换的位置,下次遍历到这个位置就可以了
//使用一个变量记录最后发生交换的位置,说明该位置之后都是有序的
func bubbleSortV3(nums []int) {
//表示某一趟是否有元素交换
flag := true
//表示最后发生交换的位置
//注意点1:这里必须再额外使用临时变量,因为如果只是用一个变量lastSwapPos的话,
//lastSwapPos的值会一直改变,因此如果一旦变小,我们的for循环就会推出
lastSwapPos := len(nums) - 1 //注意点2:初始值赋值是len(nums) - 1
for i := 1; i < len(nums); i++ { //冒泡的次数
lastSwapPosTemp := len(nums) - i //注意点3:初始值赋值是len(nums) - i
flag = true
//下次遍历的时候遍历到我们上次最后发生交换的位置就可以了
for j := 0; j < lastSwapPos; j++ {
//如果前面比后面大就交换
if nums[j] > nums[j+1] {
flag, nums[j], nums[j+1], lastSwapPosTemp = false, nums[j+1], nums[j], j //注意点4:这里lastSwapPosTemp应该赋值j,因为j与j+1比较过了,所以就认为j之后是已经有序的了
}
}
//如果没有元素交换,说明已经有序,直接退出即可
if flag {
break
}

lastSwapPos = lastSwapPosTemp
}
}

冒泡排序

冒泡排序总结:

  1. 时间复杂度:O(n^2),最好是O(n)
  2. 空间复杂度:O(1)。
  3. 稳定

点击查看代码

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 basic_sort

/**
* @Author: yirufeng
* @Date: 2021/4/13 8:28 下午
* @Desc:

时间复杂度:O(n^2)
空间复杂度:O(1)
稳定的:因为是到前面找到一个小于等于自己的后面那个位置
**/

func InsertSort(nums []int) {
insertSort(nums)
}

func insertSort(nums []int) {
var j int
//第一个元素已经有序,只需要插入后面的元素即可
for i := 1; i < len(nums); i++ {
//当前要插入的元素目前位于i位置
cur := nums[i]
//从后往前找,直到前面元素小于当前元素就停,并且遍历的过程中不断将前面的元素移动到后面
for j = i - 1; j >= 0 && nums[j] > cur; j-- {
nums[j+1] = nums[j]
}
//此时j指向的元素就是前面那个小于或者等于当前元素的位置
//但是我们应该在j+1位置插入
nums[j+1] = cur
}
}

直接插入排序总结

直接插入排序总结:

  1. 时间复杂度:O(n^2),
  2. 空间复杂度:O(1)。
  3. 稳定的:因为是到前面找到一个小于等于自己的后面那个位置

进阶排序算法

点击查看代码

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
65
66
67
68
69
70
71
package advanced_sort

import (
"algos/模板/排序/util"
"fmt"
"sort"
)

/**
* @Author: yirufeng
* @Date: 2021/4/14 3:31 下午
* @Desc: 归并排序
**/

func MergeSort(nums []int) {
mergeSort(nums, 0, len(nums)-1)
}

func mergeSort(nums []int, l, r int) {
if l == r {
return
}

//找到中间点,一分为二
mid := l + (r-l)>>1
//划分成左右两个有序的空间
mergeSort(nums, l, mid)
mergeSort(nums, mid+1, r)
//将左右两部分以mid为划分轴进行合并
merge(nums, l, mid, r)

}

//合并nums[l:mid+1] 与 nums[mid+1:r+1]两部分内容
func merge(nums []int, l, mid, r int) {
i, j := l, mid+1
cur := 0
//注意点1:这里必须借助一个数组,否则我们前面可能还没有被排序的结果会被我们后半部分的内容覆盖掉,导致前面就没有内容
help := make([]int, r-l+1)
for i <= mid && j <= r {
if nums[i] < nums[j] {
help[cur], cur, i = nums[i], cur+1, i+1
} else {
help[cur], cur, j = nums[j], cur+1, j+1
}
}

for i <= mid {
help[cur], cur, i = nums[i], cur+1, i+1
}
for j <= r {
help[cur], cur, j = nums[j], cur+1, j+1
}

//最后记得我们的help数组中的内容要放回到我们的原来的数组中
for i := 0; i < len(help); i++ {
nums[l+i] = help[i]
}
}

func main() {
nums := util.GenerateRandomNums(0, 100, 30)
fmt.Println(nums)
temp := make([]int, 30)
copy(temp, nums)
sort.Ints(temp)
MergeSort(nums)
fmt.Println(temp)
fmt.Println(nums)
}

归并排序

  1. 时间复杂度:O(nlogN) 最好最坏都是O(NlogN)
  2. 空间复杂度:O(n)。需要一个辅助空间
  3. 是否稳定:稳定的(因为一旦两个数相等我们就不比较,并且每次都是前半部分与后半部分进行比较,所以前面同样的内容与后面同样的内容的相对位置不会改变)

点击查看代码

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package main

import (
"algos/模板/排序/util"
"fmt"
"log"
"sort"
)

/**
* @Author: yirufeng
* @Date: 2021/4/14 3:29 下午
* @Desc: 从小到大的堆排序(需要建立一个大顶堆)

从小到大排序需要建立一个大顶堆,因为我们建立好大顶堆之后,每次从堆头开始排除元素,然后都会将堆头放到目前数组的最后位置,最后位置会不断缩小,
因此我们最后的位置就是一个不断往前移动的过程,从而就是说我们得到的整个数组是从小到大的
**/

func HeapSort(nums []int) {
heapSort(nums)
}

func heapSort(nums []int) {
if nums == nil || len(nums) < 2 {
return
}

for i := 0; i < len(nums); i++ {
heapPush(nums, i)
}

log.Println("建堆完成--------------->", nums)
heapSize := len(nums)

//之后不断吐出元素
for heapSize > 0 {
nums[0], nums[heapSize-1] = nums[heapSize-1], nums[0]
heapSize--
heapify(nums, heapSize)
}
}

//表示当前要加入的是nums中的索引为index的元素
func heapPush(nums []int, index int) {
for (index-1)>>1 >= 0 && nums[index] > nums[(index-1)>>1] {
nums[index], nums[(index-1)>>1], index = nums[(index-1)>>1], nums[index], (index-1)>>1
}
}

//length 表示堆的元素个数
func heapify(nums []int, length int) {
index := 0
// (index << 1 + 1) < length 说明是有左子树的
for (index<<1 + 1) < length { //思路:每次找到左右孩子中更大的与父进行交换
left := index<<1 + 1
//如果有右子树并且右子树比左子树大
if left+1 < length && nums[left+1] > nums[left] {
left++
}
//如果当前节点比左右孩子中大的大,就不交换
if nums[left] <= nums[index] {
break
}
//如果当前节点比左右孩子中大的小,交换当前节点与左右孩子中较大的
//同时让index变为left
nums[left], nums[index], index = nums[index], nums[left], left
}
}

func main() {
nums := util.GenerateRandomNums(0, 100, 50)
temp := make([]int, 50)
copy(temp, nums)
sort.Ints(temp)
fmt.Println(temp)
HeapSort(nums)
fmt.Println(nums)
}

点击查看代码

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package main

import (
"algos/模板/排序/util"
"fmt"
"sort"
)

/**
* @Author: yirufeng
* @Date: 2021/4/15 2:20 下午
* @Desc: 从大到小的排序,需要建立一个小顶堆
**/

func HeapSort(nums []int) {
heapSort(nums)
}

func heapSort(nums []int) {

//如果nums为空或者元素个数小于两个,可以直接退出
if nums == nil || len(nums) < 2 {
return
}

//此时我们需要不断将元素加入我们的堆中
for i := 1; i < len(nums); i++ {
heapInsert(nums, i)
}

//获取堆的大小
heapSize := len(nums)

//此时我们不断将堆里面的元素弹出放到应该放置的位置
for heapSize > 0 {
//将堆的最后一个元素与堆顶交换
nums[0], nums[heapSize-1] = nums[heapSize-1], nums[0]
//堆的元素个数减去1
heapSize--
//开始从堆顶从上往下开始调整堆
heapAdjustFromTopToBottom(nums, heapSize-1) // 从下到上的堆调整
}
}

//第二个参数表示插入的元素位于nums的位置
func heapInsert(nums []int, index int) {
//不断比较当前插入的位置的元素与父节点的大小,如果比父节点小就交换
for (index-1)>>1 >= 0 && nums[(index-1)>>1] > nums[index] {
nums[index], nums[(index-1)>>1], index = nums[(index-1)>>1], nums[index], (index-1)>>1
}
}

//第二个参数表示当前堆的元素个数
func heapAdjustFromTopToBottom(nums []int, length int) {
index := 0
for index<<1+1 < length {
left := index<<1 + 1

//如果有右孩子并且右比左小
if left+1 < length && nums[left+1] < nums[left] {
left++
}

//当前节点小于等于两个孩子较小的
if nums[index] <= nums[left] {
break
}
nums[index], nums[left], index = nums[left], nums[index], left
}
}

func main() {
nums := util.GenerateRandomNums(0, 100, 50)
temp := make([]int, 50)
copy(temp, nums)
sort.Ints(temp)
fmt.Println(temp)
HeapSort(nums)
fmt.Println(nums)
}

点击查看代码

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 (
"algos/模板/排序/util"
"fmt"
"math/rand"
"sort"
)

/**
* @Author: yirufeng
* @Date: 2021/4/14 3:31 下午
* @Desc: 从小到大的快速排序
**/

func QuickSort(nums []int) {
quickSort(nums, 0, len(nums)-1)
}

//表示对[l,r]的元素进行快排
func quickSort(nums []int, l, r int) {
if l < r {
//在[l,r]区间内生成一个随机数作为划分
index := rand.Intn(r-l+1) + l
//每次都把我们随机选择的元素交换到最后
nums[index], nums[r] = nums[r], nums[index]
//进行划分,得到两个相等的区间
less, more := partition(nums, l, r)
//继续对小于和大于的两个区间进行快速排序
quickSort(nums, l, less-1)
quickSort(nums, more+1, r)
}
}

//返回两个结果是等于我们随机数的区间的左端点和右端点
func partition(nums []int, l, r int) (int, int) { //使用nums[r]作为一个划分
less, more := l-1, r
num := nums[r]
cur := l
for cur < more {
if nums[cur] < num {
nums[less+1], nums[cur], less, cur = nums[cur], nums[less+1], less+1, cur+1
} else if nums[cur] > num {
nums[more-1], nums[cur], more = nums[less+1], nums[more-1], more-1
} else if nums[cur] == num {
more++
}
}
nums[more], nums[r] = nums[r], nums[more]
//每次随机择一个划分点
return less + 1, more - 1
}

func main() {
nums := util.GenerateRandomNums(0, 100, 10)
fmt.Println(nums)
temp := make([]int, 10)
copy(temp, nums)
sort.Ints(temp)
fmt.Println(temp)
QuickSort(nums)
fmt.Println(nums)
}

快速排序

思路:采用荷兰国旗的问题进行划分,每次可以划分为3个区间,分别是小于,等于以及大于的区间。

  1. 时间复杂度:O(nlogN) 最好是O(nlogN) 最坏是O(n^2)
  2. 空间复杂度:O(n)。
  3. 是否稳定:不稳定

!!!

mysql中的索引

查看代码测试 索引参考参考了解索引(索引概念)索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B数及其变种B+数。更通俗的说,索引就相当于目录...

parallel安装的虚拟机登录root

打开terminal

  1. 执行sudo passwd
  2. 出现Password:,键入自己当前用户的密码
  3. 出现Enter new UNIX password:这个是root的密码
  4. 出现Retype new UNIX password:重复root的密码

之后就可以使用su命令以及刚才设置的root用户密码切换到root用户

tools

网易微课堂之中间件学习

分布式消息中间件 查看内容 总览分布式消息中间件设计篇amqamq入门amq支持的消息协议讲解ActiveMQ高可用集群方案持久化原理及事务机制rabbitmqrabbitmq入门以及内部消息分发机制课程目录AMQP协议RabbitMQ简介RabbitMQ基本概念RabbitMQ安装运行RabbitMQ基本配置RabbitMQ管理界...

1 / 10