Ubuntu 更换阿里云软件源

1. 备份

1
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

2.修改

1
sudo vim /etc/apt/sources.list

将 source.list 文件内容替换成下面的

1
2
3
4
5
6
7
8
9
10
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse

3. 更新

1
sudo apt-get update

Ubuntu 更换阿里云软件源-阿里云开发者社区

默认源

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
# deb cdrom:[Ubuntu 18.04.3 LTS _Bionic Beaver_ - Release amd64 (20190805)]/ bionic main restricted

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://us.archive.ubuntu.com/ubuntu/ bionic main restricted
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates main restricted
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://us.archive.ubuntu.com/ubuntu/ bionic universe
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic universe
deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates universe
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://us.archive.ubuntu.com/ubuntu/ bionic multiverse
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic multiverse
deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates multiverse
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://us.archive.ubuntu.com/ubuntu/ bionic-backports main restricted universe multiverse
# deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu bionic partner
# deb-src http://archive.canonical.com/ubuntu bionic partner

deb http://security.ubuntu.com/ubuntu bionic-security main restricted
# deb-src http://security.ubuntu.com/ubuntu bionic-security main restricted
deb http://security.ubuntu.com/ubuntu bionic-security universe
# deb-src http://security.ubuntu.com/ubuntu bionic-security universe
deb http://security.ubuntu.com/ubuntu bionic-security multiverse
# deb-src http://security.ubuntu.com/ubuntu bionic-security multiverse

Ubuntu18.04 中默认的软件源 sources.list_谷永普的博客-CSDN 博客

1
2
3
4
5
6
7
8
9
10
11
12
13
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse

Ubuntu18.04 更换官方默认更新源 sources.list - SpringCore - 博客园

终端显示乱码

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
1. 配置locale-gen
终端执行

sudo locale-gen zh_CN.UTF-8

配置完后检查中文显示是否正常,若仍然不正常执行第二步

2. 配置语言环境变量
复制以下命令,终端执行

export LANG=en_US.UTF-8
export LANGUAGE=
export LC_CTYPE="en_US.UTF-8"
export LC_NUMERIC=zh_CN.UTF-8
export LC_TIME=zh_CN.UTF-8
export LC_COLLATE="en_US.UTF-8"
export LC_MONETARY=zh_CN.UTF-8
export LC_MESSAGES="en_US.UTF-8"
export LC_PAPER=zh_CN.UTF-8
export LC_NAME=zh_CN.UTF-8
export LC_ADDRESS=zh_CN.UTF-8
export LC_TELEPHONE=zh_CN.UTF-8
export LC_MEASUREMENT=zh_CN.UTF-8
export LC_IDENTIFICATION=zh_CN.UTF-8
export LC_ALL=

到第二步问题一般都解决了
若仍然不正常,可以重启试试
————————————————
原文链接:https://blog.csdn.net/weixin_39198406/article/details/82177944

问题描述

K 选择问题:给出 N 个数,找出其中第 K 小的元素。

方法 1

暴力法:
时间复杂度:O(K x N)

方法 2

二分法:
时间复杂度:O(N)

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* K选择问题:给出N个数,找出其中第K小的元素。
*/
public class K {
public static void main(String[] args) {
// 1 2 3 4 5 6 7 8 9
test(getList1());

System.out.println("-----");

// 7 8 11 22 33 44 55 66 99
test(getList2());

}

private static void test(List<Integer> list) {
System.out.printf("第%s小的元素是%s%n", 3, getNumK(list, 3));
System.out.printf("第%s小的元素是%s%n", 2, getNumK(list, 2));
System.out.printf("第%s小的元素是%s%n", 1, getNumK(list, 1));
System.out.printf("第%s小的元素是%s%n", 5, getNumK(list, 5));
System.out.printf("第%s小的元素是%s%n", 8, getNumK(list, 8));
System.out.printf("第%s小的元素是%s%n", 9, getNumK(list, 9));
}

private static List<Integer> getList1() {
return Arrays.asList(3, 7, 1, 2, 8, 9, 4, 5, 6);
}

private static List<Integer> getList2() {
return Arrays.asList(33, 7, 11, 22, 8, 99, 44, 55, 66);
}

/**
* 二分法:找一个枢轴,比枢轴小的放到s1,比枢轴大的放到s2,
* 如果: k == s1.size+1,说明枢轴就是要找的元素(+1表示枢轴所在的位置)
* 如果: k < s1.size+1,说明要找的元素在s1中
* 否则:要找的元素在 s2 中(注意要将枢轴元素加回到s2中,因为有可能正好是这个枢轴元素)
*
* @param list 列表
* @param k 第k小
* @return 返回第k小的元素
*/
private static Integer getNumK(List<Integer> list, int k) {
if (list.isEmpty()) {
return null;
}

if (list.size() < k) {
return null;
}

if (list.size() == 1 && k == 1) {
return list.get(0);
}

List<Integer> s1 = new ArrayList<>();
List<Integer> s2 = new ArrayList<>();

int p = list.get(0);
for (int i = 1; i < list.size(); i++) {
final Integer a = list.get(i);
if (a < p) {
s1.add(a);
} else {
s2.add(a);
}
}


if (k == s1.size() + 1) {
return p;
}

if (k < s1.size() + 1) {
return getNumK(s1, k);
} else {
s1.add(p);
return getNumK(s2, k - s1.size());
}

}
}
//~ output:
/*
第3小的元素是3
第2小的元素是2
第1小的元素是1
第5小的元素是5
第8小的元素是8
第9小的元素是9
-----
第3小的元素是11
第2小的元素是8
第1小的元素是7
第5小的元素是33
第8小的元素是66
第9小的元素是99
*/

mybatisplus saveOrUpdate DuplicateKeyException 问题

使用了 atlas 代理后,在 update 的时候,如果更新的内容不变,返回为 0 问题
mybatis 在这种情况下默认返回 1。(可以通过 jdbc 参数useAffectedRows来自定义)

mybatis-plus-extension-3.0.1.jar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ServiceImpl.java
@Override
public boolean saveOrUpdate(T entity) {
if (null != entity) {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
if (StringUtils.checkValNull(idVal)) {
return save(entity);
} else {
/*
* 更新成功直接返回,失败执行插入逻辑
*/
return updateById(entity) || save(entity);
}
} else {
throw ExceptionUtils.mpe("Error: Can not execute. Could not find @TableId.");
}
}
return false;
}

在 mybatis-plus-extension-3.0.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '657-CHECK_IN_EXTRA_AWARD-ACCUMULATIVE' for key 'unique_id_type'
### The error may involve com.lyloou.springmybatisplus.mapper.CheckInExtraAwardMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO check_in_extra_award ( id, type_key, award_type_enum, award_rule_enum ) VALUES ( ?, ?, ?, ? )
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '657-CHECK_IN_EXTRA_AWARD-ACCUMULATIVE' for key 'unique_id_type'
; ]; Duplicate entry '657-CHECK_IN_EXTRA_AWARD-ACCUMULATIVE' for key 'unique_id_type'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '657-CHECK_IN_EXTRA_AWARD-ACCUMULATIVE' for key 'unique_id_type'

at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:242)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
at com.sun.proxy.$Proxy59.insert(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278)
at com.baomidou.mybatisplus.core.override.PageMapperMethod.execute(PageMapperMethod.java:68)
at com.baomidou.mybatisplus.core.override.PageMapperProxy.invoke(PageMapperProxy.java:64)
at com.sun.proxy.$Proxy62.insert(Unknown Source)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.save(ServiceImpl.java:99)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.saveOrUpdate(ServiceImpl.java:159)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl$$FastClassBySpringCGLIB$$76535273.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
at com.lyloou.springmybatisplus.service.CheckInExtraAwardBaseService$$EnhancerBySpringCGLIB$$22ac1ad5.saveOrUpdate(<generated>)
at com.lyloou.springmybatisplus.SpringMybatisplusApplicationTests.contextLoads(SpringMybatisplusApplicationTests.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '657-CHECK_IN_EXTRA_AWARD-ACCUMULATIVE' for key 'unique_id_type'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3976)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3912)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:493)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
at com.sun.proxy.$Proxy69.execute(Unknown Source)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
... 42 more

2021-06-29 16:10:38.356 INFO 92996 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1a245833: startup date [Tue Jun 29 16:10:35 CST 2021]; root of context hierarchy
2021-06-29 16:10:38.360 INFO 92996 --- [ Thread-2] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed

Process finished with exit code -1

解决办法:

  1. 升级 mybatis-plus 版本

在 mybatis-plus 新版本,已经换了实现。
mybatis-plus-extension-3.3.1.tmp.jar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ServiceImpl.java
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveOrUpdate(T entity) {
if (null == entity) {
return false;
} else {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
}
}
  1. 不使用 atlas
    github 上有人提过这个问题,目前还没有人解答:
    连接 atlas update 成功后返回结果为 0 · Issue #191 · Qihoo360/Atlas

本以为可以通过配置来满足需求(返回匹配行数,而不是影响行数),找到了 useAffectedRows
可是这个参数,对于 atlas 不可用。

扩展

Mysql 连接参数 useAffectedRows 详解_简简单单 Onlinezuozuo-CSDN 博客_useaffectedrows

useAffectedRows=true 时, update 返回值为受影响行数;
useAffectedRows=false 时(默认), update 返回值为 where 条件匹配的行数.

2. ddl-auto

ddl-auto
自己手动测试下呗

img

ddl-auto 可取的值

1)spring.jpa.hibernate.ddl-auto=create
Hibernate: drop table if exists auth_user
Hibernate: create table auth_user (id bigint not null, account varchar(32), name varchar(32), pwd varchar(64), primary key (id)) engine=InnoDB
Hibernate 删掉已经存在表, 并重建表,恐怖!!!

  1. spring.jpa.hibernate.ddl-auto=create-drop

Hibernate: drop table if exists auth_user
Hibernate: drop table if exists cardo
Hibernate: create table auth_user (id bigint not null, account varchar(32), name varchar(32), pwd varchar(64), primary key (id)) engine=InnoDB
Hibernate: create table cardo (id bigint not null, brand_id integer, brand_name varchar(16), primary key (id)) engine=InnoDB

Hibernate: drop table if exists auth_user
Hibernate: drop table if exists cardo

  1. spring.jpa.hibernate.ddl-auto=update
    Hibernate: create table auth_user (id bigint not null, account varchar(32), name varchar(32), pwd varchar(64), primary key (id)) engine=InnoDB
    Hibernate: create table cardo (id bigint not null, brand_id integer, brand_name varchar(16), primary key (id)) engine=InnoDB

给 entity 类添加一个字段 others, 表也会自动同步添加一个字段 others.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Entity
@Table(name = "AUTH_USER")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDO {
@Id
private Long id;
@Column(length = 32)
private String name;
@Column(length = 32)
private String account;
@Column(length = 64)
private String pwd;
@Column(length = 255)
private String others;

}

添加个字段 others
Hibernate: alter table auth_user add column others varchar(255)
给表添加了字段 others.

表添加一个字段, 对 entity 类有啥影响?
没有任何影响.
Hibernate: insert into auth_user (account, name, others, pwd, id) values (?, ?, ?, ?, ?)

不会校验 entity 中字段类型和表中对应的字段的类型是否匹配。

  1. spring.jpa.hibernate.ddl-auto=validate

当表中字段 others 是 varchar 类型, 实体类 entity 的 others 是 Integer 类型,
类型不匹配报错:

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [others] in table [auth_user]; found [varchar (Types#VARCHAR)], but expecting [integer (Types#INTEGER)]

  1. spring.jpa.hibernate.ddl-auto=none
    禁止 ddl

  2. ddl-auto 不能同时指定多个属性, 只能在 create, create-drop, update, validate, none 中选择一个属性

  3. 总结:
    一般选择 validate/update/none
    绝对不能选 create, create-drop

update 能帮助建表。

如果希望实体类发生改动而数据库表做出相应的更改且不破坏数据库现有的数据,要将 spring.jpa.hibernate.ddl-auto 属性值设置为 update

这里还有一点,就算把 ddl-auto 设置成 update 值,也不能识别对表结构的所有更改,往往只能识别出增加的字段,比如修改字段名,修改字段类型或者删除一个字段都是不能够识别的。

ddl-auto:create —-每次运行该程序,没有表格会新建表格,表内有数据会清空;
ddl-auto:create-drop —-每次程序结束的时候会清空表
ddl-auto:update —- 每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
ddl-auto: validate —- 运行程序会校验数据与数据库的字段类型是否相同,不同会报错。

作者:BenjaminCool
链接:https://www.jianshu.com/p/bc509369b3a3
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

实战

环境介绍

环境&软件 版本
虚拟机 virtualbox 6.1
服务器 ubuntu 18.04
数据库 mysql 5.7.32

服务架构图

机器名称 IP 角色 权限和作用
master1 192.168.56.15 数据库 master 可读写、主库
slave1 192.168.56.16 数据库 Slave 只读、从库
slave2 192.168.56.17 数据库 Slave 只读、从库
master2 192.168.56.25 数据库 master 可读写、主库
slave3 192.168.56.26 数据库 Slave 只读、从库
slave4 192.168.56.27 数据库 Slave 只读、从库

bin_log 配置 & relay_log 配置

vi /etc/mysql/mysql.conf.d/mysqld.cnf

修改 uuid

show variables like ‘%server_uuid%’;

通过 select @@datadir 找到 msyql 的数据目录在哪,在这个目录下会有一个 auto.cnf 的文件,修改里面的内容,然后重启即可解决。
vi /var/lib/mysql/auto.cnf
service mysql restart

开启同步配置

1
2
3
4
5
6
7
8
9
10
-- 在master上运行,记录下file名称和position
show master status;
change master to master_host='192.168.56.15',master_port=3306,master_user='root',master_password='root',master_log_file='mysql-bin.000018',master_log_pos=1731;

change master to master_host='192.168.56.25',master_port=3306,master_user='root',master_password='root',master_log_file='mysql-bin.000024',master_log_pos=154;

start slave; -- 开启从模式

show slave status; -- 查看slave状态
stop slave; -- 关闭从模式

题目

https://gitee.com/lagouedu/alltestfile/raw/master/MySQL/MySQL%E4%B8%8B%E4%BD%9C%E4%B8%9A.pdf

作业资料说明:
1、提供资料:说明文档,代码,验证及讲解视频。
2、讲解内容包含:题目分析、实现思路、环境介绍。
3、说明文档包含:
l  环境介绍涉及的各个软件的版本
l  介绍各个机器对应角色&作用&ip地址

4、效果视频验证:
l  集群环境
* 6台
* 主master1负责写,从slave1 slave2负责读
* 主master2负责写,从slave3 slave4负责读

l  代码
* 主要类&方法&参数&返回值及代码行标注注释
* 基于user_id对c_order表进⾏数据分⽚
* 基于master1和master2主从集群实现读写分离

l  运行效果
* 项目各个类作用介绍,重点代码进行介绍,启动
* 演示基于user_id对c_order表进⾏数据分⽚,基于master1和master2主从集群实现读写分离
* 添加数据,通过Navicat展示数据分片成功,通过代码控制台真实sql展示数据分别在master1和master2进行写入
* 查询数据,通过代码控制台真实sql展示数据是通过4个从节点查询的

验证资料

作业讲解视频地址

解答

环境介绍
|环境&软件| 版本|
|—|—|
|虚拟机 virtualbox|6.1|
|服务器 ubuntu | 18.04|
|数据库 mysql | 5.7.32|

服务架构图

机器名称 IP 角色 权限和作用
master1 192.168.56.15 数据库 master 可读写、主库
slave1 192.168.56.16 数据库 Slave 只读、从库
slave2 192.168.56.17 数据库 Slave 只读、从库
master2 192.168.56.25 数据库 master 可读写、主库
slave3 192.168.56.26 数据库 Slave 只读、从库
slave4 192.168.56.27 数据库 Slave 只读、从库

配置

pom

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lyloou</groupId>
<artifactId>practice-mysql</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>practice-mysql</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>11</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>

数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- c_order_0 c_order_1
CREATE TABLE `c_order_0` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`is_del` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否被删除',
`user_id` int(11) NOT NULL COMMENT '用户id',
`company_id` int(11) NOT NULL COMMENT '公司id',
`publish_user_id` int(11) NOT NULL COMMENT 'B端⽤户id',
`position_id` int(11) NOT NULL COMMENT '职位ID',
`resume_type` int(2) NOT NULL DEFAULT '0' COMMENT '简历类型:0附件 1在线',
`status` varchar(256) NOT NULL COMMENT '投递状态投递状态WAIT-待处理理 AUTO_FILTER-⾃自动过滤 PREPARE_CONTACT-待沟通 REFUSE-拒绝ARRANGE_INTERVIEW-通知⾯面试',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '处理理时间',
PRIMARY KEY (`id`),
KEY `index_userId_positionId` (`user_id`,`position_id`),
KEY `idx_userId_operateTime` (`user_id`,`update_time`)
) ENGINE=InnoDB AUTO_INCREMENT=551043954997460994 DEFAULT CHARSET=utf8mb4;

sharding jdbc 配置

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
# 显示sql语句
spring.shardingsphere.props.sql.show=true

#数据源
spring.shardingsphere.datasource.names=master1,slave1,slave2,master2,slave3,slave4

spring.shardingsphere.datasource.master1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master1.jdbc-url=jdbc:mysql://192.168.56.15:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.master1.username=root
spring.shardingsphere.datasource.master1.password=root

spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.56.16:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=root

spring.shardingsphere.datasource.slave2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://192.168.56.17:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.slave2.username=root
spring.shardingsphere.datasource.slave2.password=root

spring.shardingsphere.datasource.master2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master2.jdbc-url=jdbc:mysql://192.168.56.25:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.master2.username=root
spring.shardingsphere.datasource.master2.password=root

spring.shardingsphere.datasource.slave3.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave3.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave3.jdbc-url=jdbc:mysql://192.168.56.26:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.slave3.username=root
spring.shardingsphere.datasource.slave3.password=root

spring.shardingsphere.datasource.slave4.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave4.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave4.jdbc-url=jdbc:mysql://192.168.56.27:3306/lagou?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.slave4.username=root
spring.shardingsphere.datasource.slave4.password=root

#分库分表
spring.shardingsphere.sharding.tables.c_order.database-strategy.inline.sharding-column=company_id
spring.shardingsphere.sharding.tables.c_order.database-strategy.inline.algorithm-expression=master$->{company_id%2 + 1}
spring.shardingsphere.sharding.tables.c_order.actual-data-nodes=master$->{1..2}.c_order_$->{0..1}
spring.shardingsphere.sharding.tables.c_order.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.c_order.table-strategy.inline.algorithm-expression=c_order_$->{user_id % 2}
spring.shardingsphere.sharding.tables.c_order.key-generator.column=id
spring.shardingsphere.sharding.tables.c_order.key-generator.type=SNOWFLAKE

#读写分离
spring.shardingsphere.sharding.master-slave-rules.master1.master-data-source-name=master1
spring.shardingsphere.sharding.master-slave-rules.master1.slave-data-source-names=slave1, slave2
spring.shardingsphere.sharding.master-slave-rules.master2.master-data-source-name=master2
spring.shardingsphere.sharding.master-slave-rules.master2.slave-data-source-names=slave3, slave4

测试
测试添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
@Repeat(value = 100)
public void testAdd() {
Random random = new Random();
final int companyId = random.nextInt(10);
final int userId = random.nextInt(100);
final Date now = new Date();
final COrder cOrder = new COrder();
cOrder.setIsDel(false);
cOrder.setUserId(userId);
cOrder.setCompanyId(companyId);
cOrder.setPublishUserId(10);
cOrder.setPositionId(100);
cOrder.setResumeType(userId % 2);
cOrder.setStatus("AUTO_FILTER");
cOrder.setCreateTime(now);
cOrder.setUpdateTime(now);
cOrderRepository.save(cOrder);
}

image-20201230150829936

测试查询

1
2
3
4
5
@Test
public void testFind() {
final List<COrder> allByUserId = cOrderRepository.findAllByUserId(24);
System.out.println(allByUserId);
}

image-20201230151141903

需求,将一个表的内容同步到另一个表中,
只同步从某个时间段到现在有更新的记录;

解决思路是:

  • 如果可以修改表结构,可以加一个 【sync_status(同步状态)】 字段:同步完成后,修改下这个记录;有修改时恢复这个记录;

  • 如果无法修改表结构,但是可以通过【update_time(修改时间)】字段来过滤,数据量太多可以分批处理

    1. 建立一个任务配置表(t_job_config),在这个配置表中,保存上次的同步信息(如:同步名称,同步时间,同步到了哪个 id,等等)
    2. 根据名称,从表中获取任务配置,如果没有就为这个名称新建立一条记录;开始时间为 null
    3. 记录下当前时间;作为结束时间
    4. 取一个最大条数 MAX;从数据库中根据修改时间和 id 获取记录,对这批数据做处理;
      记录不为空,取上次获得的最后一条 id 做为下次查询的开始 id,如下面代码所示
    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    @Component
    @Slf4j
    public class SyncStudentJob {
    private static volatile boolean isSync = false;
    @Autowired
    StudentService studentService;

    @Autowired
    JobConfigService jobConfigService;

    @Scheduled(cron = "0/10 * * * * *")
    public void syncStudent() {
    if (isSync) {
    log.info("上次还没同步完成");
    return;
    }

    try {
    isSync = true;
    final long t1 = System.currentTimeMillis();
    log.info("【Job syncStudent】, 开始同步");
    AtomicLong count = doSyncStudent();
    final long t2 = System.currentTimeMillis();
    log.info("【Job syncStudent】, 完成全部同步,耗时:{}ms,数量:{} ", (t2 - t1) / 1000, count.get());
    } finally {
    isSync = false;
    }
    }

    private AtomicLong doSyncStudent() {
    AtomicLong count = new AtomicLong();
    final int max = 500;
    final JobConfigEntity jobConfig = getOrCreateJobConfig();
    Objects.requireNonNull(jobConfig, "获取或创建jobConfig失败");

    final LocalDateTime endTime = LocalDateTime.now();
    final LocalDateTime lastUpdateTime = getLastUpdateTime(jobConfig);
    String lastUpdateId = getLastUpdateId(jobConfig);
    List<StudentEntity> list;

    do {
    final long start = System.currentTimeMillis();
    list = studentService.lambdaQuery()
    .gt(lastUpdateTime != null, StudentEntity::getGmtModified, lastUpdateTime)
    .lt(StudentEntity::getGmtModified, endTime)
    .gt(StudentEntity::getId, lastUpdateId)
    .orderByAsc(StudentEntity::getId)
    .last(String.format("limit %s", max))
    .list();
    if (list.isEmpty()) {
    break;
    }

    doList(list);
    count.addAndGet(list.size());

    final StudentEntity lastStudent = list.get(list.size() - 1);
    lastUpdateId = String.valueOf(lastStudent.getId());
    updateJobConfig(jobConfig, lastUpdateTime, lastUpdateId);

    final long end = System.currentTimeMillis();
    log.info("【Job syncStudent】, 完成一组同步,耗时:{}ms,数量:{} ", (end - start) / 1000, count.get());
    } while (list.size() >= max);

    // 更新成新的时间
    updateJobConfig(jobConfig, endTime, null);
    return count;
    }

    private void updateJobConfig(JobConfigEntity configEntity, LocalDateTime lastUpdateTime, String lastUpdateId) {
    jobConfigService.lambdaUpdate()
    .set(JobConfigEntity::getLastUpdateTime, lastUpdateTime)
    .set(JobConfigEntity::getLastUpdateId, lastUpdateId)
    .eq(JobConfigEntity::getId, configEntity.getId())
    .update();
    }

    private void doList(List<StudentEntity> list) {
    log.info("(<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
    log.info(list.toString());
    try {
    TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException ignored) {
    }
    log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>)");
    }

    private LocalDateTime getLastUpdateTime(JobConfigEntity jobConfig) {
    return jobConfig.getLastUpdateTime();
    }

    private String getLastUpdateId(JobConfigEntity jobConfig) {
    final String lastUpdateId = jobConfig.getLastUpdateId();
    if (Strings.isEmpty(lastUpdateId)) {
    return "0";
    }
    return lastUpdateId;
    }

    private JobConfigEntity getOrCreateJobConfig() {
    String jobName = "sync.student.name";
    final Optional<JobConfigEntity> configEntityOptional = jobConfigService.lambdaQuery()
    .eq(JobConfigEntity::getName, jobName)
    .oneOpt();
    if (configEntityOptional.isPresent()) {
    return configEntityOptional.get();
    }
    final JobConfigEntity configEntity = new JobConfigEntity();
    configEntity.setName(jobName);
    jobConfigService.save(configEntity);
    return configEntity;
    }
    }

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94


    Source Server : 127.0.0.1
    Source Server Type : MySQL
    Source Server Version : 50731
    Source Host : 127.0.0.1:3306
    Source Schema : school

    Target Server Type : MySQL
    Target Server Version : 50731
    File Encoding : 65001

    Date: 28/12/2020 18:37:34
    \*/

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;

    ---

    -- Table structure for t_job_config

    ---

    DROP TABLE IF EXISTS `t_job_config`;
    CREATE TABLE `t_job_config` (
    `id` bigint(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
    `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '要同步的业务名称',
    `last_update_time` datetime(0) NULL DEFAULT NULL COMMENT '上次同步时间',
    `last_update_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '上次同步到了哪里(排序的 id 才有意义,结合 last_update_time 使用)',
    `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
    `ext` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备用字段',
    `gmt_create` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
    `gmt_modified` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
    `disabled` tinyint(1) NULL DEFAULT 0 COMMENT '是否已经禁用',
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE INDEX `idx_name`(`name`) USING BTREE
    ) ENGINE = MyISAM AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

    ---

    -- Table structure for t_student

    ---

    DROP TABLE IF EXISTS `t_student`;
    CREATE TABLE `t_student` (
    `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '学生 ID',
    `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '学生名称',
    `nick_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学生昵称',
    `class_id` int(11) NULL DEFAULT NULL COMMENT '班级 ID',
    `email` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电子邮件',
    `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
    `avatar` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '大头贴',
    `gmt_create` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
    `gmt_modified` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
    `disabled` tinyint(1) NULL DEFAULT 0 COMMENT '是否已经禁用',
    PRIMARY KEY (`id`) USING BTREE,
    INDEX `idx_name`(`name`) USING BTREE
    ) ENGINE = MyISAM AUTO_INCREMENT = 1000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学生表' ROW_FORMAT = Dynamic;

    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (1, 'student001', '学生 001', 2, 'student001@coocaa.com', '15212345001', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-28 15:56:56', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (2, 'student002', '学生 002', 2, 'student002@coocaa.com', '15212345002', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (3, 'student003', '学生 003', 1, 'student003@coocaa.com', '15212345003', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (4, 'student004', '学生 004', 9, 'student004@coocaa.com', '15212345004', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (5, 'student005', '学生 005', 8, 'student005@coocaa.com', '15212345005', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (6, 'student006', '学生 006', 7, 'student006@coocaa.com', '15212345006', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (7, 'student007', '学生 007', 6, 'student007@coocaa.com', '15212345007', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (8, 'student008', '学生 008', 5, 'student008@coocaa.com', '15212345008', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (9, 'student009', '学生 009', 4, 'student009@coocaa.com', '15212345009', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (10, 'student010', '学生 010', 9, 'student010@coocaa.com', '15212345010', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (11, 'student011', '学生 011', 8, 'student011@coocaa.com', '15212345011', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (12, 'student012', '学生 012', 7, 'student012@coocaa.com', '15212345012', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (13, 'student013', '学生 013', 6, 'student013@coocaa.com', '15212345013', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (14, 'student014', '学生 014', 5, 'student014@coocaa.com', '15212345014', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (15, 'student015', '学生 015', 4, 'student015@coocaa.com', '15212345015', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (16, 'student016', '学生 016', 3, 'student016@coocaa.com', '15212345016', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (17, 'student017', '学生 017', 2, 'student017@coocaa.com', '15212345017', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (18, 'student018', '学生 018', 1, 'student018@coocaa.com', '15212345018', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (19, 'student019', '学生 019', 9, 'student019@coocaa.com', '15212345019', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (20, 'student020', '学生 020', 5, 'student020@coocaa.com', '15212345020', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (21, 'student021', '学生 021', 4, 'student021@coocaa.com', '15212345021', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (22, 'student022', '学生 022', 3, 'student022@coocaa.com', '15212345022', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (23, 'student023', '学生 023', 2, 'student023@coocaa.com', '15212345023', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (24, 'student024', '学生 024', 1, 'student024@coocaa.com', '15212345024', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (25, 'student025', '学生 025', 9, 'student025@coocaa.com', '15212345025', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (26, 'student026', '学生 026', 8, 'student026@coocaa.com', '15212345026', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (27, 'student027', '学生 027', 7, 'student027@coocaa.com', '15212345027', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (28, 'student028', '学生 028', 6, 'student028@coocaa.com', '15212345028', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (29, 'student029', '学生 029', 5, 'student029@coocaa.com', '15212345029', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);
    INSERT INTO `school`.`t_student`(`id`, `name`, `nick_name`, `class_id`, `email`, `phone`, `avatar`, `gmt_create`, `gmt_modified`, `disabled`) VALUES (30, 'student030', '学生 030', 1, 'student030@coocaa.com', '15212345030', 'http://bpic.588ku.com/element_pic/20/06/30/e510dda05e0b09e44cec4e474546a014.jpg', '2020-12-22 09:33:35', '2020-12-22 09:33:35', 0);

    SET FOREIGN_KEY_CHECKS = 1;

OSI 七层与 TCP/IP 五层网络架构详解

字母 英文含义 中文含义
A Application 应用层
P Presentation 表示层
S Session 会话层
T Transport 传输层
N Network 网络层
D Data Link 数据链路层
P Physical 物理层
  • 七层模型简单记忆:PDNTSPA
  • 五层模型简单记忆:PDNTA

OSI 七层与 TCP/IP 五层网络架构详解

OSI 和 TCP/IP 是很基础但又非常重要的网络基础知识,理解得透彻对运维工程师来说非常有帮助。今天偶又复习了一下:

(1)OSI七层模型

OSI 中的层 功能 TCP/IP 协议族
应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示层 数据格式化,代码转换,数据加密 没有协议
会话层 解除或建立与别的接点的联系 没有协议
传输层 提供端对端的接口 TCP,UDP
网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2

img

img

(2)TCP/IP 五层模型的协议

应用层
传输层
网络层
数据链路层
物理层

物理层:中继器、集线器、还有我们通常说的双绞线也工作在物理层
数据链路层:网桥(现已很少使用)、以太网交换机(二层交换机)、网卡(其实网卡是一半工作在物理层、一半工作在数据链路层)
网络层:路由器、三层交换机
传输层:四层交换机、也有工作在四层的路由器

img

二、TCP/UDP 协议

TCP (Transmission Control Protocol)和 UDP(User Datagram Protocol)协议属于传输层协议。其中 TCP 提供 IP 环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复 用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而 UDP 则不为 IP 提供可靠性、 流控或差错恢复功能。一般来说,TCP 对应的是可靠性要求高的应用,而 UDP 对应的则是可靠性要求低、传输经济的应用。TCP 支持的应用协议主要 有:Telnet、FTP、SMTP 等;UDP 支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系 统)、TFTP(通用文件传输协议)等.
TCP/IP 协议与低层的数据链路层和物理层无关,这也是 TCP/IP 的重要特点

三、OSI 的基本概念
OSI 是 Open System Interconnect 的缩写,意为开放式系统互联。
OSI七层参考模型的各个层次的划分遵循下列原则:
** 1、同一层中的各网络节点都有相同的层次结构,具有同样的功能。
2、同一节点内相邻层之间通过接口(可以是逻辑接口)进行通信。
3、七层结构中的每一层使用下一层提供的服务,并且向其上层提供服务。
4、不同节点的同等层按照协议实现对等层之间的通信。

第一层:物理层(PhysicalLayer),
规定通信设备的机械的、电气的、功能的和过程的特性,用以建立、维护和拆除物理链路连接。具体地讲,机械 特性规定了网络连接时所需接插件的规格尺寸、引脚数量和排列情况等;电气特性规定了在物理连接上传输 bit 流时线路上信号电平的大小、阻抗匹配、传输速率 距离限制等;功能特性是指对各个信号先分配确切的信号含义,即定义了 DTE 和 DCE 之间各个线路的功能;规程特性定义了利用信号线进行 bit 流传输的一组 操作规程,是指在物理连接的建立、维护、交换信息是,DTE 和 DCE 双放在各电路上的动作系列。在这一层,数据的单位称为比特(bit)。属于物理层定义的典型规范代表包括:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45 等。

第二层:数据链路层(DataLinkLayer):
在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路,通过差错控制提供数据帧(Frame)在信道上无差错的传输,并进行各电路上的动作系列。数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。在这一层,数据的单位称为帧(frame)。数据链路层协议的代表包括:SDLC、HDLC、PPP、STP、帧中继等。

第三层是网络层
在 计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息- -源站点和目的站点地址的网络地址。如 果你在谈论一个 IP 地址,那么你是在处理第 3 层的问题,这是“数据包”问题,而不是第 2 层的“帧”。IP 是第 3 层问题的一部分,此外还有一些路由协议和地 址解析协议(ARP)。有关路由的一切事情都在这第 3 层处理。地址解析和路由是 3 层的重要目的。网络层还可以实现拥塞控制、网际互连等功能。在这一层,数据的单位称为数据包(packet)。网络层协议的代表包括:IP、IPX、RIP、OSPF 等。

第 四层是处理信息的传输层
第 4 层的数据单元也称作数据包(packets)。但是,当你谈论 TCP 等具体的协议时又有特殊的叫法,TCP 的数据单元称为段 (segments)而 UDP 协议的数据单元称为“数据报(datagrams)”。这个层负责获取全部信息,因此,它必须跟踪数据单元碎片、乱序到达的 数据包和其它在传输过程中可能发生的危险。第 4 层为上层提供端到端(最终用户到最终用户)的透明的、可靠的数据传输服务。所为透明的传输是指在通信过程中 传输层对上层屏蔽了通信传输系统的具体细节。传输层协议的代表包括:TCP、UDP、SPX 等。

第五层是会话层
这一层也可以称为会晤层或对话层,在会话层及以上的高层次中,数据传送的单位不再另外命名,而是统称为报文。会话层不参与具体的传输,它提供包括访问验证和会话管理在内的建立和维护应用之间通信的机制。如服务器验证用户登录便是由会话层完成的。

第六层是表示层
这一层主要解决拥护信息的语法表示问题。它将欲交换的数据从适合于某一用户的抽象语法,转换为适合于 OSI 系统内部使用的传送语法。即提供格式化的表示和转换数据服务。数据的压缩和解压缩, 加密和解密等工作都由表示层负责。

第七层应用层
应用层为操作系统或网络应用程序提供访问网络服务的接口。应用层协议的代表包括:Telnet、FTP、HTTP、SNMP 等。

除了层的数量之外,开放式系统互联(OSI)模型与TCP/IP协议有什么区别?

开放式系统互联模型是一个参考标准,解释协议相互之间应该如何相互作用。TCP/IP 协议是美国国防部发明的,是让互联网成为了目前这个样子的标准之一。开放式系统互联模型中没有清楚地描绘 TCP/IP 协议,但是在解释 TCP/IP 协议时很容易想到开放式系统互联模型。两者的主要区别如下:

TCP/IP 协议中的应用层处理开放式系统互联模型中的第五层、第六层和第七层的功能。

TCP/IP 协议中的传输层并不能总是保证在传输层可靠地传输数据包,而开放式系统互联模型可以做到。TCP/IP 协议还提供一项名为 UDP(用户数据报协议)的选择。UDP 不能保证可靠的数据包传输。

TCP/UDP协议

TCP(Transmission Control Protocol)和 UDP(User Datagram Protocol)协议属于传输层协议。其中 TCP 提供 IP 环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而 UDP 则不为 IP 提供可靠性、流控或差错恢复功能。一般来说,TCP 对应的是可靠性要求高的应用,而 UDP 对应的则是可靠性要求低、传输经济的应用。

TCP 支持的应用协议主要有:Telnet、FTP、SMTP 等;UDP 支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。

TCP/IP 协议与低层的数据链路层和物理层无关,这也是 TCP/IP 的重要特点。

OSI 是 Open System Interconnect 的缩写,意为开放式系统互联。

Kafka - 随笔分类 - 郭俊 Jason - 博客园

www.jasongj.com/2015/01/02/Kafka 深度解析/

查看 kafka 消息队列的积压情况-12463494-51CTO 博客

1
2
kafka-consumer-groups.sh --bootstrap-server 172.20.154.101:9092 --describe --group  marketing_group | grep task-prize-gift

Kafka 的 Lag 计算误区及正确实现_朱小厮的博客-CSDN 博客_kafka lag

查看正在运行的消费组
kafka_2020-07-30-12-51-21

1
2
kafka-consumer-groups --bootstrap-server master:9092 --list --new-consumer
kafka-consumer-groups.sh --bootstrap-server ce-kafka:9092 --list

计算消息的消息堆积情况
kafka_2020-07-30-12-51-47

1
2
kafka-consumer-groups --bootstrap-server master:9092 --describe --group  test_kafka_game_x_g1
kafka-consumer-groups.sh --bootstrap-server ce-kafka:9092 --describe --group default-group

说明:

LogEndOffset 下一条将要被加入到日志的消息的位移
CurrentOffset 当前消费的位移
LAG 消息堆积量

消息堆积量:消息中间件服务端中所留存的消息与消费掉的消息之间的差值即为消息堆积量也称之为消费滞后量

kafka 清理数据日志 - Adrian·Ding - 博客园

1
2
3
4
5
log.dirs=/data/kafka-logslog.cleaner.enable=true
log.cleanup.policy = delete    // delete|compact
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
1
2
kafka-configs.sh --zookeeper ce-zookeeper:2181 --entity-type topics --entity-name __consumer_offsets --describe
kafka-configs.sh --zookeeper ce-zookeeper:2181 --entity-type topics --entity-name __consumer_offsets --alter --delete-config cleanup.policy

命令行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建名称为 topic_1 的主题
kafka-topics.sh --zookeeper nodek.com:2181/myKafka --create --topic topic_1 --partitions 1 --replication-factor 1

# 显示消费组
kafka-consumer-groups.sh --bootstrap-server nodek.com:9092 --list
kafka-consumer-groups.sh --new-consumer --bootstrap-server nodek.com:9092 --list

# 描述消费组(可以查看 offset, client_id, partition等)
kafka-consumer-groups.sh --bootstrap-server nodek.com:9092 --describe --group consumer_demo1

# 生产消息
kafka-console-producer.sh --topic topic_1 --broker-list nodek.com:9092

# 消费消息(指定消费组为 console-consumer-83559)
kafka-console-consumer.sh --bootstrap-server nodek.com:9092 --topic topic_1 --group console-consumer-83559
kafka-console-consumer.sh --bootstrap-server 172.20.154.101:9092 --topic task-prize-gift-dev --from-beginning

kafka的concurrency 配置过大导致CPU占用率过大

问题:kafka的concurrency 配置过大导致CPU占用率过大。
说明和解决方案:3台机器,分区数量为10,concurrency修改前为30,修改后为3(参考值:机器数量*concurrency<=分区数)

修改前后趋势图
image.png

修改前:5dYCAwIUJ0.jpg
修改后:image.png

注意:concurrent 的数量和 @KafkaListener 是相关的(也可以通过注解参数配置覆盖factory的concurrency @KafkaListener(concurrency = 3)),互相直接的线程是不干扰的。
image.png

image.png

消耗资源分析
每一个consumer都会添加到线程池中
image.png

每个consumer都会再 while 循环中执行 isRunning()和 pollAndInvoke() 方法(空轮询消耗CPU)。
image.png

空轮询消耗CPU示例
image.png

参考资料:【spring-kafka】属性 concurrency 的作用及如何配置(RoundRobinAssignor 、RangeAssignor) - 云+社区 - 腾讯云

其他参考资料

kafka 系列七、kafka 核心配置 - 小人物的奋斗 - 博客园

Apache Kafka-通过 concurrency 实现并发消费_小小工匠的技术博客_51CTO 博客
kafka 动态添加 topic,动态添加消费者_小小传奇的博客-CSDN 博客_kafka topic 动态
Kafka 中@KafkaListener 如何动态指定多个 topicJava 知音的博客-CSDN 博客
Kafka auto.offset.reset 值详解_lishuangzhe7047 的博客-CSDN 博客_auto.offset.reset
Kafka 获得 topicPartition 的最早,最新 offset 的时间,以及存储量_卞卞要运动的博客-CSDN 博客_topicpartitions
Kafka 消费者重复消费问题解决 | 贫贫贫贫僧

“高深莫测”的Kafka时间轮原理,原来也就这么回事-CFANZ编程社区

1
curl -X POST -H "Accept-Language:zh-CN" -H 'x-auth-token:09ef4702-578e-408b-91b2-a40393dfc996' -F 'symbol=BTC/USDT' -F 'price=76.00000' -F 'amount=1002' -F 'direction=BUY' -F 'type=LIMIT_PRICE' http://192.168.1.22:8091/exchange/order/add
1
curl -X GET --data '{"album_id": "4510261846343990"}' -H "Content-Type:application/json"  http://localhost:6004/media/output/materiellist

docker安装RabbitMq - 掘金

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

version: '3.3'
services:
rabbitmq-server:
container_name: rabbitmq
image: rabbitmq:3.8-management
restart: always
ports:
- 15672:15672
- 25672:25672
- 4369:4369
- 5671:5671
- 5672:5672
volumes:
- ./mq/rabbitmq:/var/lib/rabbitmq
environment:
- TZ=Asia/Hong_Kong
- RABBITMQ_DEFAULT_USER=qq
- RABBITMQ_DEFAULT_PASS=1234
- RABBITMQ_DEFAULT_VHOST=/qq

Rabbit安装配置问题 - 简书

RabbitMQ入门教程(概念,应用场景,安装,使用) - 简书

0%