GeekHour

Linux

Linux:类Unix,同Git作者Linus,符合GPL(General Public License)可使用、修改、再发布。

Linux四部分:

  1. 内核:驱动、内存管理、进程管理、文件系统、网络协议栈…。作用:管理硬件和提供最基本的系统服务
  2. 系统库:libc\ibm\libpthread\libdl\第三方库…。作用:提供常用函数和接口供开发使用。
  3. shell:
  4. 应用程序APP:Nginx MySQL Git Vim

发行版:还有包管理器、GUI、系统工具等,比如Ubuntu(个人用户)、Debian、CentOS、Kali(网络安全和渗透测试)

安装Linux:虚拟机工具(VMware、VirtualBox、Hyper-V(WSL)、Multipass)、Docker、云服务器

Linux根目录:home\root\bin\sbin\usr\opt\etc\lib\dev\mnt\boot\sys\proc\var\temp。

tip:bin\lib 都在usr下

Vim

插入模式:aio 进入插入模式。

命令模式:

  1. 移动:h j k l 左下上右;ctrl + f/b/d/u 下页、上页、下半页、上半页;^ $ 行首、行末。gg G 3g 表示首行、尾行、第三行。:3 表示第三行。

  2. 3yy 复制三行;3dd 删除三行,D 清空本行;3p 表示复制三次粘贴板上的内容。 ctrl + r 表示撤回,u 表示重做。

行末模式:

  1. 查找:/hello | ?hello 表示向下、向上查找。n | N 表示下一个、上一个。/hello\c 表示无视大小写
  2. 替换::2,5s/hello/world/g 表示2,5行,g表示此行全部。:s/hello/world 表示此行第一个替代。:%s/hello/world 表示每行第一个替代。
    1. 退出保存 :wq:set nu/nonu set ic syntax on

~\.vimrc 配置文件,rc表示run commands。

常用命令

# t:time、r:reverse、i:inode
ls -haltri		
echo "hello world" > hello.txt		# > 覆盖、>> 追加
touch hello.txt		# 创建文件、更新文件时间

ln -s hello.txt hello_soft.txt / ln hello.txt hello_hard.txt
# 硬连接:文件; 软连接:文件或目录

# 权限
chmod ugoa+-rwx/777 hello.txt / chmod root:root file

# 创建文件夹、复制、移动
mkdir -p dir1/dir2	
cp -r dir1 dir_copy
mv hello.txt dir/hello_move.txt

date whoami pwd	tree
du			# 目录
df -h		# 磁盘
which ls

# 安装jdk8
apt list | grep jdk / sudo apt install openjdk-8-jdk


# tar -c 压缩, -x 提取
tar -c(z)vf file.tar/file.tar.gz file1 file2 

# curl: client url用于http(s) (S)FTP SMTP。
# -o new_file.txt ; -s 表示silent不显示进度和错误,只显示真正的内容(正文); -f表示fail时不输出信息
curl -OL https://example.com/file.txt	

2

# 其中tty表示Teletypewriter, tty1,tty2表示终端界面; ?表示没有终端相连
ps -ef # e表示所有 f表示信息
# UID PID PPID 


# lsof : list open file
# -u user; -p pid; -i :80/tcp/udp; file 表示打开
lsof 
# FD文件描述符: cwd/rtd/dir/txt/NOFD/mem/pipe/socket/chr/blk
# TYPE: REG(常规文件)DIR(目录)CHR(字符设备)


# 终止指定服务
ps -ef | grep mysql	 # 找到mysqld
kill $(pidof mysqld)	# 这个命令是/usr/bin/
kill $(pidof redis-server)	# 同上

systemctl status/start/stop/restart/reload/enable/disable mysql.service

更新软件

sudo apt update
sudo apt upgrade redis -y	# 如果源地址的版本本身就低

# 需要看对应包的官网
# 命令:软件的源地址添加到/etc/apt/sources.list.d/; 
# ppa:Launchpad Person Package Archive。redis在ppa会有新版本
sudo add-apt-repository ppa:redislabs/redis	
sudo apt update
sudo apt upgrade redis-server -y
redis-server --version

如何在win下传输给linux

scp ./index.js zql@localhost:/home/zql

帮助文档

Log

Shell

脚本的作用:定时处理(比如定时清理、定时备份)、批处理…

Shell种类:sh、bash(默认)、csh、ksh、zsh、powershell。可以cat /etc/shells 查看。

.profile.bashrc:用户打开bash前会使用这两个文件进行初始化环境。配置之后使用. bashrc 或 source .bashrc

/etc/bash.bashrc 下的文件是对所有用户都有效。

环境变量

echo $SHELL			# 默认bash
echo $HOME	
echo $PATH
echo $0		# 表示当前的shell解释器。默认bash
export name=adair	# 在运行的shell中就可以获取

常用的$:

  1. $0、$1、 2 、 2、 2#:表示文件名、第一个参数、第二个参数、参数个数
  2. ∗ 、 *、 @:前者表示作为整体;后者表示按参数传递
  3. ? 、 ?、 ? 、 、 !:表示最后一个命令返回的结果;表示此进程PID;最后一个后台命令的PID

if中的数字比较:eq、ne、lt、le、gt、ge。

if中的字符串比较[[ "$str1" == "$str2" ]]:!=、>、== *、=~、-z、-n

举个例子

#!/bin/bash				# 默认解释器

is_prime() {
    local num=$1		# 局部变量必须使用local,否则为全局变量
    if [ $num -lt 2 ]; then
        return 1
    fi
    for ((i=2; i*i<=num; i++)); do
        if [ $((num % i)) -eq 0 ]; then
            return 1
        fi
    done
    return 0
}

read -p "输入数字:" number

if ! [[ "$number" =~ ^[0-9]+$ ]]; then	# 正则表达式符
    echo "no number"
    exit 1
fi

if is_prime $number; then	# 函数返回0表示OK
    echo "$number 是素数"
else
    echo "$number 不是素数"
fi

猜数字

#!/bin/bash

# 等效 $(($RANDOM%10+1))
number=$(shuf -i 1-10 -n 1)	# 也可以使用反引号
echo "随机数为$number"

while true; do
    echo "输入猜的值"
    read guess
    if [[ $guess -eq $number ]]; then
        echo "对了, 请选择是否继续y/n"
        read choice
        if [[ $choice = "y" ]] || [[ $choice = "Y" ]]; then
            number=$(($RANDOM % 10 + 1))
            echo "随机数为$number"
            continue
        else
            break
        fi

    elif [[ $guess -lt $number ]]; then
        echo "小了"
    else
        echo "大了"
    fi
done

管道:

如果输入bash confirm.sh,则会一直循环输入。可以直接yes | bash confirm.sh

#!/bin/bash

for ((i=0; i<3; i++)); do    
    read -p "输入y|n" flag	# 不会 
    echo "i=$i flag=$flag"
    if [ "$flag" == "y" ]; then
        continue
    fi
done

shell也可以结合:

  1. grep awk sed 等文本处理
  2. 函数和数组等高级特性。
  3. 系统管理和监控

RegEx

基本字符匹配:.、[ ]、[^ ]、|、
字符类:\d、\w、\s、\D、\W、\S。定位符:^、$、\b、\B、
量词:?、+、*、{n}、{n,m}、{n,}。贪婪匹配:ab{3,}、ab{3,}?
旗帜:i、m、s、g、
分组:(abc)、(?:abc)
前瞻:dog(?=cat)、dog(?!cat)。后顾:(?<=cat)dog、(?<!cat)dog

前面的字符都是有特定意义的,如果需要这个字符本身,需要进行转义。但是转义字符同样需要转义\\

基本类型:^$. [1-8B-Yc-x] [^] | \d \w \b \s \大写
量词:? + * {n} {n,m} {n,} {n,}?
前瞻:dog(?=cat) dog(?!cat) 	后顾:(?<=cat)dog (?<!cat)dog
分组:(abc) (?:abc)。\1
旗帜:i\g\s\m

部分解释:

  1. . 匹配除\n 的任意字符,s. 也可匹配\n
  2. ^$ 表示文本开始和结束。m^$ 表示每行开始和结束。
  3. \b :比如\b\d+\b 匹配 %300 而不是 s300

其他版本的RE:

  1. POSIX基本的BR、扩展的ERE。
  2. 其他版本的比如Python、Java、JS等。具体情况看文档。

拓展结合:

  • grep 和 sed 和 awk

Git

版本控制系统:集中式(比如:SVN)、分布式(比如Git)

Git的使用方式:命令行、GUI、IDE插件/扩展。

git配置:

# system 系统配置/etc/gitconfig:对所有用户生效。global 全局配置~/.gitconfig:所有仓库生效。 不带范围.git/config:默认此仓库
git config --global user.name "adair"
git config --global user.email "123@qq.com"
git config --global credential.helper store		# 存储密码,不用git push每次都要输入密码 
git config --global --list		# 查看属性

.gitignore的内容:

  1. 中间文件或者结果文件,class文件\o文件
  2. log\temp
  3. user\password、Token等
.a	# 忽略所有a类型文件
!lib.a	# 不包括lib.a
/TODO	# 忽略根目录下的TODO文件
build/	# 忽略任何目录的bulid文件夹
doc/*.o	# 忽略doc当前目录下o
doc/**/*.class	# 忽略doc所有下的class

不过项目都有相应的模板,不用自己写。https://github.com/github/gitignore

.git/ 文件夹

  1. config:配置的信息,core、user、branch( -a)
  2. refs/ (分支):heads/ (本地分支);remotes/(远程);tags/
  3. index:暂存区指针; HEAD: 版本库中。 指向object/:里面都是对象
  4. logs/ :HEAD(git log的内容);refs/:相应git branch -a其他所引用的内容

创建仓库:

# 本质都是有.git才是仓库。否则就是个普通文件夹
git init	# 把当前文件夹为git仓库
git init local-git  # 创建文件夹local-git为git仓库

git clone url	# 克隆
git clone git@github.com:name/repo.git
git clone git@192.168.8.242:v40_7.1.git

添加和提交

# 工作区、暂存区、本地库。push 远程库

ls		# 	工作区ls
git ls-files 	# 暂存区ls

git status		# 状态:??(Untracked)、M(modifid)、A(added)、D(deleted)、R(renamed)、U(updated)、

修改file		# 返回  git restore file \ git checkout file 
git add file	# 返回 git restore --staged file  \ git reset HEAD(原理) \
git commit -m "message"	# -a -v	
git commit --amend	# 补充提交, 可以-m	

git log		# --online --graph

版本回退

# 回退之前的版本
git reset --soft commmitID	# 指定commitID,且恢复工作区和暂存区
git reset --hard commmitID	# 指定commitID的,不恢复
git reset commmitID	# 指定commitID,且恢复工作区。默认--mixed

# 从之前的版本到当前版本
git reflog		# 查看所有的提交的commitID

# HEAD 当前版本
# HEAD^ HEAD~ 上一个版本
# HEAD~2 上两个版本

内容对比

git diff	# 工作区 vs 暂存区
git diff HEAD # 工作区 vs 本地库
git diff commitID1 commitID2	# 两个版本的比较,
git diff commitID1 commitID2 file.txt	# 只比较file.txt
# 也可以使用HEAD

git diff 分析

zql@adair-pc:~/git-learn/123$ git diff HEAD
diff --git a/m1 b/m1			# a/m1: 新版  b/m1: 旧版		
index 0e6c128..83e9726 100644	# 新版和旧版索引(hash) 100普通文件, 644权限
--- a/m1
+++ b/m1
@@ -1,3 +1,4 @@		# 旧版:1,3行。 新版:1,4行
 123456
 123
 q
+123			# +表示新增的

删除文件

git rm file.txt		# 综合 rm file.txt(工作区) 和 git rm --cached file.txt(暂存区) 
git mv m1.txt m2.txt	# 改名,git status . 出现renamed

分支

git branch	# 查看本地分支; -r:remote; -a:all;
git branch dev	# 创建分支。git branch -d dev	# 删除分支,没有合并则需要D
git checkout/switch dev	# 切换分支。checkout -b,创建并切换

# main、dev合并分支,不冲突
git merge dev	# 当前在main,则合并dev分支。并且自动会让你输入message,表示一次提交commitID。

# main、feat合并分支,冲突
git merge feat	# 此处会把冲突的文件内容合并,重新整理冲突文件。
git commit -am "zql:conflict merge" 	# 需要重新提交,产生commitID
git merge --abort	# 表示终止提交

# rebase
git rebase dev	# 表示以dev为根,把main接到dev上。形成直线历史
git rebase main	# 同理

git merge dev冲突

# 提示冲突,
<<<<<<< HEAD
456
=======
123
>>>>>>> dev


# 修改冲突之后在进行git commit

通过(github.com gitee.com)账户名和密码的方式克隆remote。

ssh配置,远程克隆到本地:

  1. 本地生成公钥密钥。
cd ~/.ssh		# 切换到~/.ssh下
ssh-keygen -t rsa -b 4096	# rsa类型,4096个bit位数
# 输入相应的名称比如demo,密码demo
# 生成demo.pub,密钥demo

vim config		# 增加以下内容
```
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/demo
```
  1. 把公钥复制到GitHub中。ssh -T git@gitee.com 测试

  2. 本地创建一个空仓库,git remote add origin git@github.com:adair-zhang/learn-github.git 关联远程即可。

tip:这样创建空库再关联太慢了,不如clone。

本地推送到远程:

  1. GitHub中创建一个空仓库
  2. 在本地仓库中进行连接GitHub的空仓库
git remote add origin git@github.com:adair-zhang/learn-github.git
git branch -M main # 强制修改当前名(默认为master),修改为main
git push # git push -u origin main 第一次推送到远程。main其实是main(本地):main(远程)缩写


git fetch 		# 默认git fetch origin main,此时并不在最新的commitID。然后合并git merge
git pull 		# 等效fetch + merge。默认是git pull origin main

代码托管平台:

  1. GitHub、gitee、gitlab
  2. 私有化部署:在自己服务器上部署一个gitlab代码托管平台。可以使用Docker进行部署。
# 比如my-repo是本地关联到github上。
git remote add gitlab git@gitlab.com:name/myrepo.git	# 本地再次关联到gitlab上
git remote -v	# 可以查看本地关联远程的情况
git push gitlab main	# 推送到gitlab

git remote add github2 git@github.com:adair-zhang/first-repo.git	# 关联其他仓库
git remote -v # 表示仓库关联的远程信息

git的GUI:GitHub Desktop、SourceTree、GitKraken等

也可以在VS code中进行操作:

  1. windows安装git
  2. 然后可以使用vs code中的git

git本质

image-20230916102952710

常用命令

image-20230916103020915


拓展配置:

  • post-git

git心得:

  • commit之前先review,查看代码是否错误,规范
  • 平时开发test分支,不要在master分支

C语言

丹尼斯创造为了Unix编写。

范围:Unix\Linux\Windows、git\vim、MySQL\Redis、Nginx

静态语言:编译时确定变量类型, C\C++\Java\Rust
动态语言:运行时确定变量类型,Python\JavaScript\Ruby\PHP

编译器:

  1. GCC:GNU Compiler Collection,包含了C、C++、Objective-C、Ada、Go等多种编译器
  2. Clang:编译C、C++、Objective-C、Objective-C++的编译器前端。采用LLVM为后端,在MacOS下使用

安装开发开发环境:MinGW,安装后 gcc -v 测试。

IDE:CLion、Code::Blocks

VS code

安装好MinGW中的gcc。vs code中不提供编译器。

vs code中然后再增加扩展中,Code Runner 就可以直接运行C的源码了

基本语法

数据类型:

  1. 基本数据类型:short、int、long、long long、char、float、double
  2. 派生数据类型:数组、指针、结构体、枚举、共用体、void
#define MAX 100	// 宏定义
int num; 	// 全局变量,静态变量int默认0
int main(){
    int age; 	// 不赋值,则默认内存的随机值
    const double PI = 3.14; // const表示常量
}

tip:sizeof(long)在win中始终是4,linux中sizeof(long)为4(32位系统),为8(64位系统)

goto:

int main() {
    for (size_t i = 0; i < 3; i++) {
        printf("%d\n", i);
        if(i == 1) goto out;
    }
out:
    printf("hello\n");  
}

指针

int main() {
    int a = 300;     
    int *p = &a;
    printf("a = %d\n", a);
    printf("p = %p\n", p);
    printf("*p = %d\n", *p);
    printf("p + 1 = %p\n", p+1);    // 地址+4字节

    int **p2 = &p;      // 指向指针的指针。
    printf("p2 = %p\n", p2);
    printf("*p2 = %p\n", *p2);  // 为p的地址
    printf("**p2 = %d\n", **p2); 
}

数组

int main() {
    int arr[5] = {1, 2, 3, 4}; // 默认初始值为0
    int *p = arr;
    *p = 10;    // 修改a[0] = 10
    printf("*p = %d\n", *p);       // a[0]值
    // +1表示指向下一个元素。sizeof(int)=4,所以加4。如果是double,加8
    p += 1;                 
    printf("*p = %d\n", *p);        // a[1]值

    // 二维数组
    int b[3][4] = {
        {1, 2, 3, 4},
        {1, 2, 3, 5},
        {1, 2, 3, 6}
    };
}

堆栈

int main() {
    // 栈内存:比较小,几M ~ 几十M
    int a = 1;
    int b = 2;
    int c = func(a,b);

    // 堆内存:很大,可以申请使用
    int *p = (int *)malloc(sizeof(int));
    *p = 100;
    printf("*p = %d", *p);
    free(p);    // 释放p所指空间,防止内存溢出
    p = NULL;   // 防止野指针。
}

函数

// Demo1: 函数声明。项目开发中,则会声明函数在头文件,实现函数则文件\库中。
int add(int a, int b);	// 声明。也可以int add(int, int)
//或者,直接把实现体放到前面
int main() { }
int add(int a, int b){
    return a+b;
}

// Demo2: 函数指针。项目开发中,实现一个回调函数,就把函数指针作为参数传递给另外一个函数,在此使用指针来执行此函数,比如事件处理或消息传递。
#include <stdio.h>

int add(int a, int b){
    return a+b;
}
int substract(int a, int b){
    return a-b;
}
typedef int (*Operation)(int, int);
int main() {
    // 等效 int (*p)(int, int) = add;
    Operation p = substract;   
    printf("%d\n", p(3,4));
}

static

void test() {
    static int a = 0;
    a += 1;
    printf("a=%d\n", a);
}
int main() {
    test(); // print a=1
    test(); // print a=2
}

// static修饰全局变量和函数时:表示只能在当前文件使用,用于模块封装,防止命名冲突

string

#include <string.h>	// 引入头文件
int main() {
    // 字符串本身就是字符数组,也可以使用指针表示。
    char a[20] = "hi"; // 等效{'h', 'i', '\0'};
    char *b = "hello"; 
    printf("%s\n", a);
    printf("%s\n", b+1);    // 输出:ello
    // 字符串函数:strcpy\strcmp\.\strncat\strncpy\strncmp
    strcat(a, b);   
    printf("%s\n", a);
}

结构体struct

typedef struct student {
    char name[20];
    int age;
    float score;
}Student;
int main() {
    struct student stu1 = {"Tom", 18, 60.1};    // Student stu1 =...
    strcpy(stu1.name, "Tommy");
    stu1.age = 19;
    printf("%s, %d, %f", stu1.name, stu1.age, stu1.score);    
}

共用体union

union student {
    // 两个变量共用一个地址。
    char name[10];
    int age;
};
int main() {
    union student stu1;    
    stu1.age = 97;
    printf("%s, %d", stu1.name, stu1.age);   // a, 97 
}

枚举enum

enum day {  // 下面的属性默认从0开始
    MON,    
    TUE,
    WED
};
int main() {
    enum day day1 = TUE;    
    printf("%d", day1);   // 1
    /**
     * 亦可
     * enum day {
        MON = 3,    
        TUE,
        WED
       };
     */
}

库引用

// a.h
#ifndef A_H		// 解决库重复引用导致的重复定义问题。
#define A_H
int a = 1;
#endif

// b.h
#include "a.h"

// hello.c
#include <stdio.h>

#include "a.h"
#include "b.h"
int main() {
    printf("hello %d\n", a);	// 如果没有上面的条件编译。报错:重复定义
}

编译链接过程:

  1. 预处理:
    1. 头文件和条件编译、宏定义
    2. 除掉注释
  2. 编译阶段:源文件转为汇编代码
    1. 语法检查、类型检查
    2. 代码优化:常量表达式直接计算出来、删掉无用代码
  3. 汇编阶段:汇编代码转为机器码(目标文件 .o
  4. 链接阶段:把所有目标文件使用的库文件链接起来,形成可执行文件。分为静态链接和动态链接。
    1. 静态链接:会将库默认直接嵌入到可执行文件中,运行时不再依赖外部库。
    2. 动态链接:程序运行时加载库。多个程序可以共享一个动态库,节省资源。

库:已经编译好的文件

  1. 静态库:.a (Linux中)、.lib (win中),并不是只用于静态链接。
  2. 动态库:.so (Linux中)、.dll (win中),并不是只用于动态链接。

有空再看:

特性CC++C#Objective-CObjective-C++
编程范式过程化编程面向对象、过程化面向对象面向对象面向对象 + 泛型编程
内存管理手动管理手动管理自动垃圾回收ARCARC + 手动管理
平台跨平台跨平台Windows、跨平台macOS、iOSmacOS、iOS + 跨平台
运行时静态编译静态编译静态编译动态运行时动态运行时
模板编程支持模板编程支持模板编程
使用场景操作系统、嵌入式应用程序开发、游戏企业应用、Web 开发macOS、iOS 开发混合 C++ 和 Objective-C
典型应用操作系统、硬件驱动高性能应用、游戏Web 应用、游戏开发iOS/macOS 应用开发iOS/macOS 应用开发

C:如果你需要控制硬件或开发底层系统,C 是最合适的选择。

C++:如果你需要高效且灵活的面向对象编程,并且涉及到复杂的数据结构或系统性能要求,C++ 更为合适。

C#:如果你开发 Windows 应用、Web 应用或跨平台应用,C# 是一个非常现代和高效的选择。

Objective-C:如果你在开发 iOS 或 macOS 应用,Objective-C 是一个必备语言,尤其是在 Swift 出现之前。

Objective-C++:如果你需要结合 C++ 的高效性和 Objective-C 的面向对象特性,尤其是在需要同时调用 C++ 库和 Objective-C 库时,可以使用 Objective-C++。


高级特性

  1. 如何编译makefile
  2. gdb调试器
  3. 栈溢出漏洞

编译运行机制

开发环境

常用工具

使用技巧

Makefile

构建工具make中的makfile相当于 maven中 pom.xml ,Node.js(npm) 中 package.json。

安装:

choco install make // win安装: 位置C:\ProgramData\chocolatey\bin\make.exe
sudo apt install make // linux

基本语法规则:

target: soureces
	rules
	...

Demo:

目前有源文件

// message.h
void message();

// message.c
#include <stdio.h>
void message() {
    printf("hello world\n");
}

// hello.c
#include "message.h"
int main() {
    message();
}

makefile

.PHONY: clean all
CFLAGS = -Wall -g -O2
target = hello world
object = hello.o message.o
# source = hello.c message.c

all: hello world
	@echo "all done"

$(target): $(object)
	gcc $(CFLAGS) $(object) -o $@

%.o: %.c
	gcc $(CFLAGS) -c $< -o $@

clean:
	rm -f *.o hello

解释:

.PHONY 表明 make clean/all 后面接的是命令,而不是文件(比如有个clean文件)
CFLAGS 设置编译选项,-Wall所有警告,-g调试,-O2中度优化

$(target): $(object)
	gcc $(CFLAGS) $(object) -o $@
当所需$(object)没有时,向下查找生成目标。

%.o: %.c
	gcc $(CFLAGS) -c $< -o $@
所有的c转为o: message.o 和 hello.o,
message.o: message.c	
	gcc $(CFLAGS) -c message.c -o message.o
	
makefile中自动变量:$@ 表示target; $< 表示源文件第一个参数

CMake

makefile 无需手动编写,CMake自动生成,配置文件为 CMakeLists.txt 文件

sudo apt install cmake 	// linux安装cmake

vs code使用cmake

  1. 创建CMakeLists.txt
# 常用配置。手写
cmake_minimum_required(VERSION 3.10)

project(HelloWorld)

set(SOURCES hello.c message.c)

add_executable(hello ${SOURCES})
  1. 执行 cmake 命令,自动识别CMakeLists.txt,并生成Makefile文件。
  2. 依旧执行命令:make 自动生成可执行文件hello,清理 make clean

Maven

Maven 在配置文件 pom.xml (Project Object Model)

  1. 管理依赖,将依赖jar和依赖的依赖jar的导入项目。手动导入依赖麻烦、可能冲突。
  2. 构建管理:java源文件 转为 class字节码,然后打包成可执行的jar或者war。执行 构建、打包、部署等工作。

Maven仓库:

  1. 本地仓库:~/.m2/repository/。本地没有则会去私服和中央仓库中查找并下载到本地,提高效率。
  2. 私服仓库:公司或组织的仓库,可以私用Nexus构建。非必须的
  3. 中央仓库:Maven官方仓库

安装:windows中,官网下载bin二进制压缩包,配置环境变量 MAVEN_HOME 和 path。mvn -v 查看版本。

# linux中安装
sudo apt install maven	# 自动配置环境变量。
# 如果使用解压包,则.bashrc下
export MAVEN_HOME=../..
export PATH=$MAVEN_HOME/bin:$PATH

配置.\config\settings.xml

<!--配置本地仓库地址-->
<localRepository>D:\environment\apache-maven-3.9.6\mvn_resp</localRepository>

<!--配置中央仓库镜像,由于Maven在国内访问慢-->
<mirror>
    <id>alimaven</id>
    <mirrorOf>central</mirrorOf>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

<!--配置对应jdk,可以不配-->
<profile>
    <id>jdk-1.4</id>

    <activation>
        <jdk>1.4</jdk>
    </activation>

    <repositories>
        <repository>
            <id>jdk14</id>
            <name>Repository for JDK 1.4 builds</name>
            <url>http://www.myhost.com/maven/jdk14</url>
            <layout>default</layout>
            <snapshotPolicy>always</snapshotPolicy>
        </repository>
    </repositories>
</profile>

demo

Linux中创建demo:

# 创建mvn项目
mvn archetype:generate -DgroupId=net.geek -DartifactId=maven-sample -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false

# 编译,target下生成class字节码 
mvn compile

# 打包:maven-sample-1.0-SNAPSHOT.jar
mvn package

# 运行项目 cp:classpath。输入:Hello World!
java -cp target/maven-sample-1.0-SNAPSHOT.jar net.geek.App

IDEA中创建demo

  1. 依然选择maven-archetype-quickstart,然后选择GroupId,ArtifactId。即可创建成功
  2. 可以在IDEA的settings中修改Maven的home和配置

从IDEA中可以看到maven的各种生命周期,各种生命周期都是有对应的插件实现的,插件也就是java类,maven本质上就是通过接口调用这类来实现生命周期,而且default中生命周期有顺序的,直接执行后一个命令,会自动执行之前的命令:

  1. clean
  2. default:validate; compile; test; package; verify; install(将jar安装到本地仓库); deploy(将jar部署到公司的私服仓库);
  3. site:生成网站的信息和文档为静态网站。会生成index.html可以在浏览器中查看

tip:install的位置,比如D:\environment\apache-maven-3.9.6\mvn_resp\net\hour\mvn-exapmle\1.0-SNAPSHOT\mvn-exapmle-1.0-SNAPSHOT.jar。(net\hour包名、mvn-exapmle项目名、1.0-SNAPSHOT版本)

比较常用命令:

  1. mvn clean package
  2. mvn clean install

pom.xml中使用GAV(groupId artifactId version)标定一个jar包,version中snapshot (快照,开发中)和 release(开发完)

<!-- groupId不爆红说明有这个组,下面同理 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.2.1</version>
</dependency>

<!--依赖传递: 直接依赖context,它会引用间接依赖core\aop\beans等-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.2.1</version>
</dependency>

依赖范围:

<dependencies>
    <!--test: 只用于测试单元的源码,不会被正式源码引用,不会被打包-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>

    <!--compile默认:编译和运行都需要-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>6.2.1</version>
        <scope>compile</scope>
    </dependency>

    <!--provided:编译需要,运行不需。比如lombok简化Setter\Getter-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.34</version>
        <scope>provided</scope>
    </dependency>
    <!--servlet运行时Tomcat或其他Web容器会提供,所以也是provided-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>

    <!--runtime: 运行时需要,编译无需,比如jdbc驱动-->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.7.4</version>
        <scope>runtime</scope>
    </dependency>

    <!--system: 只能在本地电脑使用,因为源码放在git中,而git一般忽略jar,
      除非其他环境手动引入这些jar
      最好引入到私服仓库,其他成员只用pom即可-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>system</scope>
        <systemPath>${basedir}/lib/junit-3.8.1.jar</systemPath>
    </dependency>
</dependencies>

父子工程:多个模块的依赖管理

  1. 创建maven-parent项目,同上demo。把此项目src删除。
  2. 在父类项目中,创建多个module,并命名为child-a、child-c、child-d、
  3. 可以在IDEA右侧栏中看到相应模块。
<!--maven-parent 的 pom.xml-->
<groupId>net.geek</groupId>
<artifactId>maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--pom值: 表示父类-->
<packaging>pom</packaging>
<modules>
    <module>child-a</module>
    <module>child-b</module>
    <module>child-c</module>
</modules>


<!--child-a 的 pom.xml-->
<parent>
    <groupId>net.geek</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
<artifactId>child-a</artifactId>
<!--表示jar,还可以war-->
<packaging>jar</packaging>

maven-parent 的 pom.xml:这样dependencies由于无条件继承,父子耦合高

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>6.2.1</spring.version>
</properties>

<!--child-* 无条件继承-->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

降低耦合度:

<!--maven-parent 的 pom.xml:子类不继承-->
<!--properties 可以定义通用的属性,以便后面引用-->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>6.2.1</spring.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>


<!--child-a 的 pom.xml:继承,默认version为父类的-->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
    </dependency>
</dependencies>

依赖冲突:比如A和B,A引入D,B通过引入C再引入D?或者A和B同时引入D?D是不同的版本,到底用那个版本。

  1. maven本身有第一的规则:最短路径优先,先声明优先。
  2. 开发者:通过exclusions标签排除依赖、optional标签标记可选依赖。

spring-jdbc版本此时就会冲突,此时child-a由于路径一样,则先声明优先,使用child-b中的spring-jdbc的版本。

<!--child-a 的 pom.xml,引入child-b和 child-c -->
<dependency>
    <groupId>net.geek</groupId>
    <artifactId>child-b</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>net.geek</groupId>
    <artifactId>child-c</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>


<!--child-b 的 pom.xml-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.2.1</version>
</dependency>


<!--child-c 的 pom.xml-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.2.1</version>
</dependency>

如果开发者想使用child-c中的spring-jdbc版本

// 方式一:修改child-a的pom.xml,exclusions排除
<dependency>
    <groupId>net.geek</groupId>
    <artifactId>child-b</artifactId>
    <version>1.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>net.geek</groupId>
    <artifactId>child-c</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

// 方式二:修改child-b的pom.xml, optional标签为ture表示可选(非必须的	)
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.2.1</version>
    <optional>true</optional>
</dependency>

Nexus

Nexus用于私服仓库。

安装和使用:

  1. win中下载对应压缩包并解压,
  2. 通过./etc/nexus-default.properties知道端口为8081
  3. 开启服务nexus.exe/run ,通过浏览器 localhost:8081 访问。

Nexus网页介绍:

  1. 默认有maven-releases(本地hosts)、maven-snapshots(本地hosts)、maven-central(中央仓库)、maven-public(包含三者)、
  2. 开发者也可创建其他仓库,nexus不仅支持maven2;也支持docker,npm,yum之类的包文件

从Nexus下载:

<!-- ./conf/settings.xml 配置mirror和server -->
<mirror>
    <id>maven-nexus</id>
    <mirrorOf>*</mirrorOf>
    <name>nexus私服</name>
    <url>http://localhost:8081/repository/maven-public/</url>
</mirror>

<server>
    <id>maven-nexus</id>
    <username>admin</username>
    <password>admin</password>
</server>

上传Nexus,即deploy:

<!-- pom.xml-->
<version>1.0.0</version>

<!-- 配置nexus的id和具体仓库的url -->
<distributionManagement>
    <!-- 会根据version值是否有SNAPSHOTS,自动决定是releases还是snapshots仓库 -->
    <repository>
        <id>maven-nexus</id>
        <url>http://localhost:8081/repository/maven-releases/</url>
    </repository>
    <snapshotRepository>
        <id>maven-nexus</id>
        <url>http://localhost:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>

tip:默认不许重复上传正式版本,比如1.0.0,第二次进行deploy就会报错。


import依赖范围

Nginx

最常用的Web服务器。一个Master进程管理多个Work进程。

安装方式:

  1. 包管理器:linux通过apt、win通过choco、mac通过brew
  2. 编译安装:下载对应C语言源码,预编译、编译、安装的方式
  3. 使用Docker:docker pull nginx

安装好之后,执行nginx.exe 即可启动服务,在浏览器中 localhost 即可访问,

nginx -s quit/stop 停止服务

nginx.conf为配置文件,规定了一些work数量,文件类型等。nginx -s reload 修改之后重新加载(signal)

hexo

需要装hexo,前提需安装 Node.js和 git

npm install -g hexo-cli;

hexo init blog;
cd blog;
npm install;	# 安装hexo默认的依赖
hexo g;		# generate 生成静态文件
hexo s;		# server 本地开发服务器,通常在localhost:4000
# 此时只是hexo的服务

# 把hexo生成的blog部署的nginx:把blog/public/* 复制到nginx的html下即可。

反向代理

先安装go:choco install go 默认C:\Program Files\Go\bin

main_8000.go;然后创建内容相同的main_8001.go; main_80001.go;

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!8000")
}

func main() {
    // 设置处理请求的路由
    http.HandleFunc("/", handler)

    // 启动服务器,监听8080端口
    fmt.Println("Server is running on http://localhost:8000")
    if err := http.ListenAndServe(":8000", nil); err != nil {
        fmt.Println("Error starting server:", err)
    }
}

启动服务

go run main_8000.go;	# 其他两个同理

# 浏览器中可以localhost:8000 访问

配置反向代理nginx.conf:通过 localhost/app 即可轮训访问8000\8001\8002,

http{
	...
    upstream backend {
        ip_hash;
        server 127.0.0.1:8000 weight=3;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
    }
    server {
		...;
		
        location /app {
            proxy_pass http://backend;
        }
	}
	...
}

负载均衡:weight=3表示大部分在此服务器;ip_hash表示在一台服务器比如只在8000,解决session互传

HTTPS配置

HTTP + SSL = HTTPS。默认http端口为80,https端口为443。一些主流的云平台可以申请到免费的ssl(Secure Sockets Layer)证书,也可以通过自签名生成证书和密钥,已经被TLS(Transport Layer Security)所取代。

安装openssl命令:choco 。默认C:\Program Files\SSL\bin

cd ssl	# 创建一个ssl文件夹
# 
openssl genpkey -algorithm RSA -out server.key
openssl req -new -key server.key -out server.csr	# 输入对应的信息,比如国家,公司,邮箱...
openssl x509 -req -in server.csr -signkey server.key -out server.crt

nginx.config

# 解决重定向问题	
server {
    listen      80;
    server_name localhost;

    # 重定向到 HTTPS 版本
    return 301 https://localhost$request_uri;
}

server {
    listen 443 ssl;  # 监听 443 端口,并启用 SSL
    server_name localhost;  # 你的域名

    ssl_certificate     D:/environment/nginx-1.27.3/ssl/server.crt;  # 证书文件
    ssl_certificate_key D:/environment/nginx-1.27.3/ssl/server.key;  # 私钥文件

    ssl_protocols TLSv1.2 TLSv1.3;  # 推荐的 SSL/TLS 协议版本
    # ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256';  # 强加密套件
    ssl_prefer_server_ciphers on;  # 强制使用服务器配置的加密算法
    # ssl_dhparam /path/to/dhparam.pem;  # Diffie-Hellman 参数,用于增加安全性,确保生成该文件(见后文)
    ssl_session_cache shared:SSL:10m;  # 缓存会话以提高性能
    ssl_session_timeout 1d;  # 设置 SSL 会话超时
    # listen       80;
    # server_name  localhost;

    #charset koi8-r;
    location /app {
    	proxy_pass http://backend;
    }
}

然后 https://localhost

虚拟机

demo1:

可以在一台服务器部署多个站点,比如一个server 就相当于一个服务器

为了方便表示nginx.conf 的 server 配置在servers/local.conf 中

# nginx.conf 
http {
	...;
	include servers/*.conf;
}


# 新建servers/local.conf,把nginx.conf 中的server拷过来
server{
	
}

demo2:

npm create vite	# 选择Vue和TypeScript
npm install # 安装依赖node_modules/
npm run build	# 生成dist/ 下面有index.html

同样把这个网站部署到nginx上

server {
    listen 5173;
    server_name localhost; 
    location / {
        root D:/environment/nginx-1.27.3/vuedemo/dist;
        index index.html index.htm;
    }
}

然后 https://localhost:5173

MySQL

数据库DB是按照数据结构进行组织、存储、管理数据的仓库,DBMS是数据库管理系统,常见RDBMS有MySQL

安装:

  1. Linux,apt intall mysql-server
  2. win在官网下载安装包
  3. docker pull mysql

windows需要进行一些配置

# 创建文件在项目下 my.init
[mysqld]
basedir=D:\environment\mysql-8.0.33-winx64\
datadir=D:\environment\mysql-8.0.33-winx64\data\
port=3306

# 输入命令
mysqld --initialize		# 初始化mysql,会生成data
mysqld --install		
net start mysql		# 启动mysql服务
mysql -u root -p	# 登陆,密码在data/*.err
alter user 'root'@'localhost' identified with mysql_native_password by 'newpassworld';
flush privileges;

常见数据库

关系型数据库:MySQL、Oracle、PostgreSQL

非关系型数据库NoSQL(No Only):Redis、mongoDB

常用命令

DDL数据库定义语言:操作数据库、表、列等,比如CREATE、DROP、ALTER、TRUNCATE
DML数据库操作语言:增删改,比如INSERT、DELETE、UPDATE、CALL
DQL数据库查询语言:查,比如SELECT
DCL数据库控制语言:访问权限和安全级别,创建用户等,比如GRANT、REVOKE

数据类型:数值、日期和时间、字符串、json、空间类型。

数值:TINYINT、SMALLINT、INT、BIGINT、FLOAT、DOUBLE
日期和时间:DATE、TIME、DATATIME、TIMESTAMP
字符串:CHAR、VARCHAR、TEXT、BLOB、、、

show databases;
use mysql;
show tables;

create database game;
drop database game; 
drop table player;

CREATE TABLE play (
	id INT,
	name VARCHAR(100),
	level INT,
	exp INT,
	gold DECIMAL(10,2)
)
DESC player;		# 表中列的属性

# 修改表格属性
ALTER TABLE play add COLUMN last_data DATETIME;		# 增加列
ALTER TABLE play DROP COLUMN last_data;				# 删除列
ALTER TABLE play RENAME COLUMN name to nick_name;	# 修改列的名字
ALTER TABLE play MODIFY COLUMN name VARCHAR(200);	# 修改列的属性
ALTER TABLE play MODIFY level INT DEFAULT 2;	# 设置默认值

# 改变表格中的数据
INSERT INTO play (id, name, level) VALUES (2, "name2", 2), (3, "name3", 3);	# 插入数据
UPDATE play SET LEVEL=9 WHERE name="wangwu";
UPDATE play SET gold=3, exp=4;
DELETE from play where name="wangwu"






# 查询
SELECT * FROM player WHERE `level` > 10 AND `level` < 20 OR exp > 10 AND exp < 20
SELECT * FROM player WHERE `level` NOT in (1, 3, 5)
SELECT * FROM player WHERE `level` BETWEEN 1 AND 10; 
SELECT * FROM player WHERE email is NOT NULL
SELECT * FROM player WHERE email is NULL	# NULL ≠ 空字符串
SELECT * FROM player WHERE email=''
# 模糊查询
SELECT * FROM player WHERE name LIKE%%SELECT * FROM player WHERE name LIKE ’王_‘
SELECT * FROM player WHERE name REGEXP '王'
SELECT * FROM player WHERE name REGEXP '[王张]' # 等效 '王|张'
SELECT * FROM player WHERE name REGEXP '^王.$'


# 排序
SELECT * FROM player ORDER BY `level`
SELECT * FROM player ORDER BY `level` DESC, exp;

# 函数计算
SELECT COUNT(*) FROM player;
SELECT AVG(`level`) FROM player;
SELECT sex, COUNT(*) FROM player GROUP BY sex;
# 查询:group by分组,having组条件,order by排序
SELECT level, COUNT(*) FROM player 
GROUP BY level 
HAVING 	COUNT(`level`) > 4 
ORDER BY COUNT(level) DESC
# 按姓氏数量排名
SELECT SUBSTR(name, 1, 1), COUNT(SUBSTR(name, 1, 1)) FROM player 
GROUP BY SUBSTR(name, 1, 1)
HAVING COUNT(SUBSTR(name, 1, 1)) >= 5
ORDER BY COUNT(SUBSTR(name, 1, 1)) DESC
LIMIT 1,4		# 从(1,1+4]
# 去重
SELECT DISTINCT sex FROM player;

# 联表,并集Union
SELECT * FROM player WHERE level BETWEEN 1 AND 3
UNION 			# UNION 合并查询并去重; UNION ALL 合并所有的查询
SELECT * FROM player WHERE exp BETWEEN 1 AND 3
# 联表,交集intersect
SELECT * FROM player WHERE level BETWEEN 1 AND 3
intersect
SELECT * FROM player WHERE exp BETWEEN 1 AND 3
# 联表,取except剩下的
SELECT * FROM player WHERE level BETWEEN 1 AND 3;
except
SELECT * FROM player WHERE exp BETWEEN 1 AND 3;
# 子查询:一个select查询的结果作为另一个select的源
SELECT level, ROUND((SELECT AVG(level) FROM player)) as average, 
level - ROUND((SELECT AVG(level) FROM player)) as diff 
FROM player;
# 一个select结果作为另一个表的数据源
CREATE TABLE new_player SELECT * from player WHERE level < 5;
INSERT INTO new_player SELECT * from player WHERE level BETWEEN 6 AND 10;
# 是否存在相应的数据,返回0或1
SELECT EXISTS( SELECT * FROM player WHERE level > 10 )


# 表连接,INNER\LEFT\RIGTH
SELECT * from player
INNER JOIN equip
on player.id = equip.id
# 等效
SELECT * from player, equip	# 笛卡尔积的内容
WHERE player.id = equip.id	# 条件过滤


# index索引
create INDEX email_index on player( email)
SHOW INDEX FROM player
SELECT * from player WHERE email like "%net"
DROP INDEX email_index on player
ALTER TABLE player add INDEX email_index (email)

# view视图
# 创建view
CREATE VIEW top5 		# 如果修改view,ALTER
AS
SELECT * FROM player ORDER BY level DESC LIMIT 5

UPDATE player set gold=94 WHERE id=57	# 修改表,对应view也变化
drop view top5














默认值、非空、Unique、主键约束、外键约束

Redis

商品服务和MySQL进行交互。多个商品服务都可以通过TCP/Socket,通过单线程访问远程Redis,这样就没有进程并发和切换的开销了。Redis就是一个内存中间件,存储DB的Cache,商品服务查询从MySQL中通过Key查询的Value(在java中map,则python中是dictionary)会保存到Redis中,在下次查询直接在Redis中即可,且数据类型多种比如List、Set、ZSet。如果宕机则内存丢失,一种是内存快照dump.rdb;一种是aof,提前写入命令,重写和压缩。所以名字:Remote dictionary server 远程 字典 服务 。

K-V,K为字符串。

使用:CLI(Command Line Interface)、API(Application Program Interface)、GUI

安装:apt、下载安装包

开启服务:

redis-server	# 开启服务
redis-cli		# 开启命令行

字符串

set name adair # del / get 
keys *me

flushall

ttl name
expire name 10
setex name 10 adair	# 创建键,并设置ttl
setnx name zhangsan	# 键不存在则有效

# 16进制存储,看到的也是16进制。redis-cli --raw

List

lpush letter a b c # rpush
lrange letter 0 -1
rpop letter	# 对应lpop
llen letter

ltrim letter 2 4	# 下标[2,4]

Set

sadd course redis mysql # sismember / srem
smembers course 
# Set不可重复添加


# 拓展:交集、并集等
sinter
sunion
sdiff

SortedSet(ZSet)

zadd result 4 c 2 a 3 c 
zrange result 0 -1
zrange result 0 -1 withscores
zscore result b
zrank result b
zrevrank result c
zrem result c

# 自己拓展

hash

hset person name adair
hset person age 18
hget person name
hgetall person
hdel person name
hexists person age

hkeys person;

subscribe public

# 订阅频道
subscribe geekhour;

# 另一个窗口向频道发送内容
public geekhour mysql;

Stream 消息队列,解决:发布订阅的不可持久性,无法记录消息。

# redis 5.0 才有
xadd geekhour * lang sql
xadd geekhour * course docker
xrange geekhour - +
xlen geekhour
xread count 2 block 1000 streams geekhour 1

# 在另一个端口中输入xadd geekhour 4-0 course nginx;
xread count 2 block 10000 streams geekhour $	# 此时接受geekhour的最新的消息

# 创建消费组
xgroup create geekhour group1 0 # 创建从第0个数据开始
xgroup destroy geekhour group1
xinfo groups geekhour

# 读取
xreadgroup group group1 consumer2 count 1 block 0 streams geekhour >
# 在另一个窗口写入
xadd geekhour * key value;






Geospatial

geoadd city 116.4 39.9 beijing 121.4 31.2 shanghai 114.0 22.5 shenzhen 37.0 23.1 guangzhou 120.1 30.2 hangzhou

geopos city beijing
geodist city beijing shanghai 
geodist city beijing shanghai km

geosearch city frommember shanghai byradius 1000 km

HyperLogLog:高效低精度

pfadd course git mvn
pfadd course2 c java
pfmerge result course course2
pfcount result

BitMap:字符串类型的扩展

setbit demo 0 1
setbit demo 1 0
getbit demo 1

set demo "\xF0"

bitpos demo 0 # 第一个0的位置

BitField

bitfield player:1 set u8 #0 1
bitfield player:1 get u8 #0
bitfield player:1 set u32 #1 100
get player:1
bitfield player:1 incrby u32 #1 100

事务:没有关系型数据库的原子性,一个事务中命令失败之后可以继续执行下面的命令

multi # 开启事务
> set k1 v1
> set k2 v2
> exec 	# 执行完成
get k1

持久化:RDB(redis DB)、AOF(Append Only File)

RDB:使用快照,/etc/redis/redis.conf
AOF:写入命令的时候也会写入一个aof文件,重启redis则会重新执行这文件

# /etc/redis/redis.conf
save 3600 1 	# 一小时内修改1次自动快照
appendonly yes	# 开启AOF

# 查看save 保存的地址
save 	# 也可手动快照
config get dir	# 获取配置文件

# 到指定位置,比如/var/lib/redis/dump.rdb
xxd dump.rdb	# 查看文件

如果数据量比较大,save阻塞主进程,bgsave命令会fork一个子进程执行快照,但是创建fork子进程也需要时间,这段时间主进程依然不能执行其他任务

主从复制

单主节点写入,多个从节点读取,单向

# 配置文件 redis.conf,先复制一份redis_6380.conf

port 6380
pidfile /run/redis/redis-server_6380.pid
dbfilename dump_6380.rdb	# 表示save/bgsave 存储的dump
replicaof 127.0.0.1 6379	# 表示父节点的port

# 启动服务
redis-server redis_6380.conf
> info replication	# 查看信息

缺点:主宕机,从还需手动提升为主节点

哨兵模式

# 配置文件 sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 1
# 加载服务
redis-sentinel sentinel.conf

十大数据类型:String、List、Set、SortedSet、Hash、Stream、Geospatial、HyperLogLog、Bitmap、Bitfield、

基本概念

安装配置

常用命令

十大数据类型

事务

数据持久化

主从复制

哨兵模式

MongoDB

C++编写,NoSQL,Document存储

对应MySQL:

  1. 集合Collection == 表Table
  2. 文档Document == 行Row
  3. 字段Field == 列Column
  4. 索引index == 索引index
  5. _id == 主键(primary key)
  6. $lookup == join
  7. $group == group by

安装:MongoDB官网下载对应安装包,Mongosh 安装对应安装包。默认MongoDB中有Compass GUI工具

插件使用mongoDB,vs code扩展增加mongdb for vs,然后连接本地mongodb即可

use game
db.user.insertOne({name: "zhangsan"})
db.user.find()
db.user.find().limit(1)
db.user.insertOne({name: "Tom", age: "10"})
db.user.insertMany([{name: "lisi", age: "18"}, {name: "wangwu", age: "19"}])

# 有待测试
db.user.find().sort({level: 1}).limit(2).skip(1)
db.user.find({level: 3}, {name: 1, email: 0})
db.user.find({level: {$gt: 3}})
db.user.find({level: {$gte: 3, $lte: 5}})
db.user.find($and: [{level: {$gte: 3}}, {level: {$lte: 5}}])
db.user.find({level: {$in: [1-3]}})		# in 反 nin
db.user.find({email: {$exists: true}})	# 就算email: null也要返回相应的用户,因为有email字段

db.user.find({level: {$not: {$eq: 3}})
db.user.find({name: {$regex: /张/, $options: 'i'}})

db.user.countDocuments()
db.user.countDocuments({level: {$gte: 3}})
db.user.findOne({level: {$gte: 3}})
db.user.updateOne({level: 3}, {$set: {money: 100}})

db.user.deleteOne({level: 3})










基本概念

安装配置

常用命令

GUI工具

MongoShell

Docker

Docker用于build run share 应用程序的平台。CS架构,client 和 daemon 之间通过Socket 和 RESTful API进行通信。容器化:应用程序打包成容器,在容器中运行程序。

打包内容:操作系统、运行时环境、库和依赖、应用程序和环境变量、配置文件和启动命令

打包比如说MySQL、Redis、Nginx、Ubuntu之类的环境,比如一个网站:

前端Vue + 后端Springboot + DB:MySQL

需要:Node.js 环境 npm依赖、Java环境、Spring第三方库、安装MySQL、环境变量和启动脚本

还可能需要:Redis缓存、Nginx负载均衡、各种微服务、

如果在开发环境中运行成功,在测试环境不一定成功。

docker持久化:由于docker容器重启之后会丢失之前的数据,docker会将数据映射到宿主机的逻辑卷中

虚拟机:物理机 + Hypervisor + n个虚拟器
Docker:物理机 + Docker + n个容器

安装:下载docker安装即可

# 配置镜像
"registry-mirrors": [
    "https://docker.1panel.live",
    ...
]

demo

流程:

  1. 编写Dockerfile
  2. 创建镜像
  3. 启动容器

创建Dockerfile

FROM node:14-alphine
COPY index.js /index.js
CMD node /index.js

创建镜像 并 启动镜像

docker build -t hello-docker .
docker images
docker run hello-docker

# 比如pull,然后运行up主的镜像
docker pull geekhour/hello-docker
docker run geekhour/hello-docker 	

docker compose

多容器docker、通过docker-compose.yaml配置、一条命令创建并启动所有服务

docker compose up

基本概念

安装配置

常用命令

构建镜像

运行容器

docker compose & Kubernetes

Kubernetes

容器少可以用脚本,上百容器可以使用k8s。Google开源

Pod:k8s调用最小单元;创建一个环境,多个容器共享资源,比如网络、存储、配置。通常一个pod配置一个容器,多个容器比如主容器和辅助容器,sidercar用于服务监控和日志。pod之间通过ip进行访问

Node:一个物理机或者虚拟机
Pod:最小单位,由一或多个容器构成
Service:一系列Pod组成的服务
Ingress:Service的入口
ConfigMap:配置信息
Secret:配置敏感信息
Volumes:存储,防止DB丢失现有的信息
Deployment:多个app形成副本
StatefulSet:保证多个数据库信息同样

demo

本地搭建集群k3s,也可以使用minikube

multipass launch --name k3s --cpus 2 --memory 8G --disk 10G
multipass launch --name worker1 --cpus 2 --memory 8G --disk 10G
multipass launch --name worker2 --cpus 2 --memory 8G --disk 10G

# 进入k3s
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
sudo kubectl get nodes
# 退出到linux
TOKEN=$(multipass exec k3s sudo cat /var/lib/rancher/k3s/server/node-token)
MASTER_IP=$(multipass info k3s | grep IPv4 | awk '{print $2}')
 for f in 1 2; do
     multipass exec worker$f -- bash -c "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=\"https://$MASTER_IP:6443\" K3S_TOKEN=\"$TOKEN\" sh -"
 done
# 再次进入k3s,可以看到集群成功
sudo kubectl get nodes/pod/svr

在线集群网站:https://killercoda.com

kubectl

sudo kubectl run nginx --image=nginx
sudo kubectl get pod

sudo kubectl create deployment nginx-deployment --image=nginx
sudo kubectl get deployment

sudo kubectl get replicaset


开发测试运维架构

基本概念

架构原理

核心组件

资源对象

环境配置

demo

堡垒机

Node.js

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。java在jre环境运行,js在nodejs环境运行

  1. 异步和事件驱动:非阻塞 I/O 模型,适用于大量并发
  2. 单线程
  3. 模块化,内置模块(fs、http、path)

安装:

  1. 下载Node.js安装包到environment\目录下。node -v | npm -v 测试
  2. 目录下创建文件夹node_cache,node_global。默认
npm config set prefix  "...\Nodejs\node_global"
npm config set cache "...\Nodejs\node_cache"
npm config get registry		# 配置国内镜像


npm config get prefix
npm config list
  1. 系统变量,NODE_PATH为…\Nodejs\node_global\node_modules。并在PATH中添加%NODE_PATH%
  2. 用户变量,…\AppData\Roaming\npm修改为…\Nodejs\node_global
  3. 测试:npm install express -g 安装在\node_global\node_modules\express

Multipass

简单轻量安装ubuntu。

# 创建虚拟器
multipass launch --name myubuntu # --cpus 2 --memory 8G --disk 10G
multipass start/shell/stop myubuntu
multipass list/help
multipass exec myubuntu -- ls -l	# 执行命令

# 默认不许ssh,修改
multipass shell myubuntu
sudo apt install net-tools
vim /etc/ssh/sshd_config # PasswordAuthentication yes,PermitRootLogin yes
sudo service ssh restart
passwd
ssh-keygen -t rsa -b 4096
ssh-copy-id ubuntu@192.168.105.10
alias myubuntu='ssh ubuntu@192.168.105.10'




Service种类:

  1. ClusterIP:默认,集群内部
  2. NodePort:节点端口,公开
  3. LoadBalance:服务公开到外部负载均衡器上
  4. ExtralName:将服务映射到外部域名上
  5. Headless:DNS解析和服务发现

问题

Linux安装出现

zql@adair-pc:~$ sudo apt install multipass
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done

No apt package "multipass", but there is a snap with that name.
Try "snap install multipass"

E: Unable to locate package multipass

解决:

# 其一
sudo snap install multipass
# 其二
sudo add-apt-repository ppa:canonical-server/multipass
sudo apt update
sudo apt install multipass

Windows

命令

tasklist | findstr "nginx"	# 查找任务
taskkill /f /t /im nginx.exe	# 终止任务,f强制,t递归子进程,im映像名称

# net命令:网络和系统管理
net stop nginx # 先停止系统的nginx服务,否则停止nginx,也会重新启动

# netstat:查看端口
netstat -ano 	# a:all n:number o:pid

常见问题

端口占用

# 8080 端口被占用
netstat -ano | findstr "8080"	# 查找端口对应的pid(1234)
tasklist | findstr "1234" 	# 根据pid找到任务,
# 终止任务
tasklist /f /t /pid 1234	
tasklist /f /t /im demo.task	

常识

局域网:

  1. 192.168.
  2. 172.16 ~ 172.32
  3. 10.j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值