Mysql8初始化新建库

mysql8

安装mysql8

  • 安装完成后,之前的MariaDB就会被覆盖掉
  1. wget -i -c https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
  2. yum -y install mysql80-community-release-el7-3.noarch.rpm
  3. yum -y install mysql-community-server

启动mysql

  1. 启动MySQL服务:systemctl start mysqld.service
  2. 查看MySQL服务:systemctl status mysqld.service
  • 查看MySQL是不是开机自启,可以执行命令查看开机自启列表
    1
    systemctl list-unit-files|grep enabled

进入mysql

  1. 此时如果要进入MySQL得找出root用户的密码,输入命令:grep “password” /var/log/mysqld.log
    1
    2021-05-10T08:10:47.232877Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: [这里是密码]
  2. MySql需要重新设置密码才能操作数据库。:ALTER USER ‘root’@’localhost’ IDENTIFIED BY ‘123456’;
    1
    2
    3
    注意:先登录进去:mysql -u root -p
    设置密码的时候需要遵守MySQL密码设置规范,如果不符合规范是不能修改成功的。
    如下图,我将密码设置为123456,它提示我 密码不符合规范

登录后远程连接备注

需要重新创建用户的:

1
2
3
4
5
6
7
8
9
设置允许远程连接。

如果直接使用命令:GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456'; 会提示一个语法错误,有人说是mysql8的分配权限不能带密码隐士创建账号了,要先创建账号再设置权限。也有的说8.0.11之后移除了grant 添加用户的功能。

创建新用户 admin

创建用户:CREATE USER 'admin'@'%' IDENTIFIED BY '123456';

允许远程连接:GRANT ALL ON *.* TO 'admin'@'%';

不创建用户:

1
2
3
4
5
6
7
8
mysql8下试验通过的:
use mysql

update mysql.user set host = '%' where user = 'root';

FLUSH PRIVILEGES;

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'WITH GRANT OPTION;

创建数据库

  1. CREATE DATABASE [数据库表] 语句创建数据库
  2. SHOW CREATE DATABASE [数据库表] 查询创建的库

导出导出数据库

  1. mysqldump -u root -pmima [数据库表] > dbname.sql
    1
    2
    3
    4
    5
    6
    1. 格式:mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名 
    2. 导出所有库:mysqldump -u root -proot --all-databases >/tmp/all.sql
    3. 导出几个:mysqldump -u root -proot --databases db1 db2 >/tmp/user.sql
    4. 导出一个数据库:mysqldump -u root -proot --skip-add-drop-table nacos_config >d:/nacos_config_db.sql
    5. 只导出结构:加上 -d
    6. --skip-add-drop-table 导出的sql创建表之前都会drop 表.加上该参数会不加drop的sql
  2. 导入数据库
    1
    2
    3
    4
    1. 常用source 命令
    2. 进入mysql数据库控制台:mysql -u root -p
    3. mysql>use 数据库
    4. 然后使用source命令,后面参数为脚本文件(如这里用到的.sql):mysql>source d:/dbname.sql

概念理解

概念解读

  1. mysql的锁和mysql的隔离级别的关系。有哪些锁
  2. mysql一条查询语句干了啥
  3. grpc的特性
  4. 服务器load的分析与排查
  5. kafka性能高原因
  6. 什么场景选用什么mq
  7. java线程释放原理
    1
    线程中断,运行结束
  8. java的syc锁升级原理,轻量级什么锁,重量级什么锁
  9. juc下面有什么包?引入queue的问题 cas aqs
  10. 限流算法怎么做
  11. tcp连接的状态
  12. LockSupport的理解

Mysql事务开启

//查看当前事物级别:
SELECT @@tx_isolation;

//设置read uncommitted级别: 未提交读
set session transaction isolation level read uncommitted;

//设置read committed级别: 已提交读
set session transaction isolation level read committed;

//设置repeatable read级别: 可重复读
set session transaction isolation level repeatable read;

//设置serializable级别: 可串行化
set session transaction isolation level serializable;

  1. 手动开启事务:
    begin;
    select xxx
    commit;

微博热搜的实现

微博

实现原理

  1. 网上没有具体的,看该内容涉及几个词。也进行一个总结记录
  • 抽样检查

    1
    用于计算和存储相关数据
  • 热词排名方法一:贝叶斯平均法(Bayesian average)/热词排名法二:牛顿冷却定律

    1
    已关键字进行求值分数,在用优先级队列进行求TOP

线上JVM运行调试

jvm调试

gc部分

  • jvm的垃圾收集器状态

    1. jmap -heap [pid]
  • jvm dump堆文件

    1. jmap -dump:format=b,file=[路径].hprof [pid]
  • 手动gc

    1. jmap -histo:live [pid]
  • 查看gc的次数和频率

    1. 使用jstat。参考文章:java性能调试工具
    2. 在实际使用中发现如下的问题。后面在一篇文章有部分说明:参考文章
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      1. 新生代为680M。SurvivorRatio为8。也就是新生区544M,2个幸存区各68M。但结合线上的jmap和jstat中,这个使用内存量会变,幸存区实际再用低于68M,新生区会大于544。
      原因:使用的是ps新生代垃圾收集器才会是这个问题。parnew则是按照配置来预先分配
      parallel scavenge新生代中具体分配策略参见:
      备注: Parallel Scavenge 收集器
      特点:属于新生代收集器也是采用复制算法的收集器,又是并行的多线程收集器(与ParNew收集器类似)。
      该收集器的目标是达到一个可控制的吞吐量。还有一个值得关注的点是:GC自适应调节策略(这就是为啥幸存区不是按照比例的来配置大小的原因)(与ParNew收集器最重要的一个区别)
      GC自适应调节策略:Parallel Scavenge收集器可设置-XX:+UseAdaptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等,虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量,这种调节方式称为GC的自适应调节策略。
      Parallel Scavenge收集器使用两个参数控制吞吐量:
      XX:MaxGCPauseMillis 控制最大的垃圾收集停顿时间
      XX:GCRatio 直接设置吞吐量的大小。

jvm更换垃圾收集器

  1. Serial(串行)收集器
    1. -XX:+UseSerialGC
  2. Parallel(并行)收集器
    1. -XX:+UseParallelGC -XX:+UseParallelOldGC
  3. CMS(并发)收集器
    1. -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
  4. 开启G1收集器的方式
    1. -XX:+UseG1GC
  5. 组合说明
    1
    2
    3
    4
    5
    -XX:+UseParNewGC = ParNew + SerialOld这个组合已经很少用(在某些版本中已经废弃)
    -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old
    -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】
    -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old
    -XX:+UseG1GC = G1

jvm内存管理

  1. Java_JVM参数-XX:MaxDirectMemorySize 与 两种 ByteBuffer: heap,direct ByteBuffer(参考:https://www.cnblogs.com/laoqing/p/10380536.html)
  2. ByteBuffer有两种:
    • heap ByteBuffer -> -XX:Xmx
      • 1.1、一种是heap ByteBuffer,该类对象分配在JVM的堆内存里面,直接由Java虚拟机负责垃圾回收;
    • direct ByteBuffer -> -XX:MaxDirectMemorySize
      • 1.2、一种是direct ByteBuffer是通过jni在虚拟机外内存中分配的。通过jmap无法查看该快内存的使用情况。只能通过top来看它的内存使用情况。
        • 1.2.1、JVM堆内存大小可以通过-Xmx来设置,同样的direct ByteBuffer可以通过-XX:MaxDirectMemorySize来设置,此参数的含义是当Direct ByteBuffer分配的堆外内存到达指定大小后,即触发Full GC。注意该值是有上限的,默认是64M,最大为sun.misc.VM.maxDirectMemory(),在程序中中可以获得-XX:MaxDirectMemorySize的设置的值。
        • 1.2.2、没有配置MaxDirectMemorySize的,因此MaxDirectMemorySize的大小即等于-Xmx
        • 1.2.3、Direct Memory的回收机制,Direct Memory是受GC控制的
        • 1.2.4、对于使用Direct Memory较多的场景,需要注意下MaxDirectMemorySize的设置,避免-Xmx + Direct Memory超出物理内存大小的现象

常用参数说明

  • jvm一些常用参数
    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
    -server                                             ## 服务器模式
    -Xms2g ## 初始化堆内存大小
    -Xmx2g ## 堆内存最大值
    -Xmn256m ## 年轻代内存大小,整个JVM内存=年轻代 + 年老代 + 持久代
    -Xss256k ## 设置每个线程的堆栈大小
    -XX:PermSize=256m ## 持久代内存大小
    -XX:MetaspaceSize=21m ## 最大持久代内存大小
    -XX:MaxMetaspaceSize=21m ## 最大可分配元空间
    -XX:MaxDirectMemorySize=21m ## 直接内存分配
    -XX:ReservedCodeCacheSize=256m ## 代码缓存,存储已编译方法生成的本地代码
    -XX:+UseCodeCacheFlushing ## 代码缓存满时,让JVM放弃一些编译代码
    -XX:+DisableExplicitGC ## 忽略手动调用GC, System.gc()的调用就会变成一个空调用,完全不触发GC
    -Xnoclassgc ## 禁用类的垃圾回收,性能会高一点
    -XX:+UseConcMarkSweepGC ## 并发标记清除(CMS)收集器
    -XX:+CMSParallelRemarkEnabled ## 启用并行标记,降低标记停顿
    -XX:+UseParNewGC ## 对年轻代采用多线程并行回收,这样收得快
    -XX:+UseCMSCompactAtFullCollection ## 在FULL GC的时候对年老代的压缩,Full GC后会进行内存碎片整理,过程无法并发,空间碎片问题没有了,但提顿时间不得不变长了
    -XX:CMSFullGCsBeforeCompaction=3 ## 多少次Full GC 后压缩old generation一次
    -XX:LargePageSizeInBytes=128m ## 内存页的大小
    -XX:+UseFastAccessorMethods ## 原始类型的快速优化
    -XX:+UseCMSInitiatingOccupancyOnly ## 使用设定的回收阈值(下面指定的70%)开始CMS收集,如果不指定,JVM仅在第一次使用设定值,后续则自动调整
    -XX:CMSInitiatingOccupancyFraction=70 ## 使用cms作为垃圾回收使用70%后开始CMS收集
    -XX:SoftRefLRUPolicyMSPerMB=50 ## Soft reference清除频率,默认存活1s,设置为0就是不用就清除
    -XX:+AlwaysPreTouch ## 强制操作系统把内存真正分配给JVM
    -XX:+PrintClassHistogram ## 按下Ctrl+Break后,打印类的信息
    -XX:+PrintGCDetails ## 输出GC详细日志
    -XX:+PrintGCTimeStamps ## 输出GC的时间戳(以基准时间的形式)
    -XX:+PrintHeapAtGC ## 在进行GC的前后打印出堆的信息
    -XX:+PrintGCApplicationConcurrentTime ## 输出GC之间运行了多少时间
    -XX:+PrintTenuringDistribution ## 参数观察各个Age的对象总大小
    -XX:+ParallelRefProcEnabled ## 默认为 false,并行的处理 Reference 对象,如 WeakReference,除非在 GC log 里出现 Reference 处理时间较长的日志,否则效果不会很明显。
    -XX:+PrintGCApplicationStoppedTime ## GC造成应用暂停的时间
    -Xloggc:../log/gc.log ## 指定GC日志文件的输出路径
    -ea ## 打开断言机制,jvm默认关闭
    -Dsun.io.useCanonCaches=false ## java_home没有配置,或配置错误会报异常
    -Dsun.awt.keepWorkingSetOnMinimize=true ## 可以让IDEA最小化到任务栏时依然保持以占有的内存,当你重新回到IDEA,能够被快速显示,而不是由灰白的界面逐渐显现整个界面,加快回复到原界面的速度
    -Djava.net.preferIPv4Stack=true ## 让tomcat默认使用IPv4
    -Djdk.http.auth.tunneling.disabledSchemes="" ## 等于Basic会禁止proxy使用用户名密码这种鉴权方式,反之空就可以使用
    -Djsse.enablesSNIExtension=false ## SNI支持,默认开启,开启会造成ssl握手警告
    -XX:+HeapDumpOnOutOfMemoryError ## 表示当JVM发生OOM时,自动生成DUMP文件
    -XX:HeapDumpPath=D:/data/log ## 表示生成DUMP文件的路径,也可以指定文件名称,如果不指定文件名,默认为:java_<pid>_<date>_<time>_heapDump.hprof。
    -XX:-OmitStackTraceInFastThrow ## 省略异常栈信息从而快速抛出,这个配置抛出这个异常非常快,不用额外分配内存,也不用爬栈,但是出问题看不到stack trace,不利于排查问题
    -Dfile.encoding=UTF-8
    -Duser.name=qhong

    -XX:NewRatio=3 ## 新生代与年老代的比例。比如为3,则新生代占堆的1/4,年老代占3/4。
    -XX:SurvivorRatio=8 ## 新生代中调整eden区与survivor区的比例,默认为8,即eden区为80%的大小,两个survivor分别为10%的大小。
    -XX:PretenureSizeThreshold=10m ## 晋升年老代的对象大小。默认为0,比如设为10M,则超过10M的对象将不在eden区分配,而直接进入年老代。
    -XX:MaxTenuringThreshold=15 ## 晋升老年代的最大年龄。默认为15,比如设为10,则对象在10次普通GC后将会被放入年老代。
    -XX:MaxTenuringThreshold=0 ## 垃圾最大年龄,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代,该参数只有在串行GC时才有效
    -XX:+HeapDumpBeforeFullGC ## 当JVM 执行 FullGC 前执行 dump
    -XX:+HeapDumpAfterFullGC ## 当JVM 执行 FullGC 后执行 dump
    -XX:+HeapDumpOnCtrlBreak ## 交互式获取dump。在控制台按下快捷键Ctrl + Break时,JVM就会转存一下堆快照
    -XX:+PrintGC ## 输出GC日志
    -verbose:gc ## 同PrintGC,输出GC日志
    -XX:+PrintGCDateStamps ## 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
    -XX:+PrintFlagsInitial ## 显示所有可设置参数及默认值
    -enablesystemassertions ## 激活系统类的断言
    -esa ## 同上
    -disablesystemassertions ## 关闭系统类的断言
    -dsa ## 同上
    -XX:+ScavengeBeforeFullGC ## FullGC前回收年轻代内存,默认开启
    -XX:+CMSScavengeBeforeRemark ## CMS remark前回收年轻代内存
    -XX:+CMSIncrementalMode ## 采用增量式的标记方式,减少标记时应用停顿时间
    -XX:+CMSClassUnloadingEnabled ## 相对于并行收集器,CMS收集器默认不会对永久代进行垃圾回收。如果希望回收,就使用该标志,注意,即使没有设置这个标志,一旦永久代耗尽空间也会尝试进行垃圾回收,但是收集不会是并行的,而再一次进行Full GC
    -XX:+CMSConcurrentMTEnabled ## 当该标志被启用时,并发的CMS阶段将以多线程执行(因此,多个GC线程

NACOS源码解读(2.0.0版本)

nacos使用方面概述

概述

工程简介。

  • 站在前人肩膀,少走弯路,快速切入入口;文章属于较早的,本文解读从2.0.0开始。
    1
    2
    3
    4
    参考文章:1. https://blog.csdn.net/ZhangQingmu/article/details/105212470
    2. https://blog.csdn.net/CX610602108/article/details/110099591
    3. https://www.cnblogs.com/HendSame-JMZ/p/13046614.html
    划重点:上述3篇文章仅供参考,实际需要根据自己的版本所建立
  1. nacos-console: nacos主体项目入口和启动项目
  2. nacos-naming: nacos注册发现业务。
  3. nacos-config: nacos的配置中心服务
  4. nacos-api: 用户nacos客户端和服务端进行通信的定义
  5. nacos-client: nacos客户端,进行和服务端通信
  6. nacos-test: 测试用例

启动demo

  1. 执行脚本 (MySQL)
    1
    2
    create database nacos_config;
    \distribution\conf\nacos-db.sql
  2. IDEA 找到 nacos-console项目并运行 Nacos.java
    1
    2
    3
    4
    5
    6
    7
    jvm参数配置如下:
    -Dnacos.standalone=true
    -DuseAddressServer=false
    -Ddb.num=1
    -Ddb.url=jdbc:mysql://localhost:3306/nacos_config
    -Ddb.user=nacos
    -Ddb.password=nacos

编译源码jar包启动

  1. 选择nacos-distribution项目执行:mvn clean install -Dmaven.test.skip=true -P release-nacos

  2. 选择对应的压缩包.进行传输

  3. 解压压缩包到bin目录:sh startup.sh -m standalone

    • 如果使用ubuntu或者运行脚本报错提示[[符号找不到,可尝试如下运行:bash startup.sh -m standalone
  4. 修改链接数据等前往conf目录.

  5. 运行控制台页面

    1
    2
    http://localhost:8848/nacos/index.html#/login
    用户名密码 nacos/nacos

项目分析解读

  1. nacos-test
    1
    2
    3
    4
    5
    6
    7
    1. 包下面的结构还是挺清晰的,每个不同的模块都会聚集在一个包下面。以下举例config。
    2. 第一个类:ConfigAPI_CITCase->nacos_getconfig_1
    3. 测试方法用于一个配置注册和删除,在进行获取。
    4. 启动该测试类的会启动:Nacos.class(参照上面demo启动)。
    5. 随后用nacos-client包下的类进行远程调用进行各项方法。
    总结:test方法会一同启动nacos服务,同时用client进行调用。这里会进行一个全链路的测试。
    这个一个很好的方法,学习了。

#nacos理念

数据一致性

  1. nacos由AP CP组成混合使用;

    • 临时节点使用AP模式,进行服务端存储,存在在一个Map中
      1
      AP协议:Distro协议。Distro是阿里巴巴的私有协议,目前流行的 Nacos服务管理框架就采用了 Distro协议。Distro 协议被定位为 临时数据的一致性协议 :该类型协议, 不需要把数据存储到磁盘或者数据库 ,因为临时数据通常和服务器保持一个session会话, 该会话只要存在,数据就不会丢失 。
    • 持久化节点使用CP模式(集群Leader),该数据会序列化进磁盘中。备注:nacos1.4之前使用raft自己实现,之后版本使用了:蚂蚁金服的jraft。
      1
      Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它。为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导选取(leader selection)、日志复制(log replication)、安全(safety),并且使用了更强的一致性来减少了必须需要考虑的状态。
    1. 参考文章:Nacos注册中心设计分析-CP模式(重点)
    2. 参考文章:蚂蚁金服开源 SOFAJRaft:生产级 Java Raft 算法库
    3. 参考文章:Nacos中Distro协议梳理
    4. 参考文章:Nacos 实现 AP+CP原理Raft 算法
    5. 参考文章:Raft协议动态图

      2.0版本

  2. 新增gprc。

  3. 支持长链接

问题故障解析

mq故障

  1. 事故现象:服务开始出现请求缓慢,进而系统全面崩溃

    1
    2
    3
    4
    5
    6
    8:00,收到系统故障提醒,并立即进行故障的排查; 
    8:00至16:00,分析问题,从CPU、内存、连接数量、系统日志等进行分析均未发现明显异常,
    尝试各种解决方案,包括限流、熔断、服务降级、服务重启等均无法有效解决;
    16:00, 发现到消息队列服务器有阻塞现象,对消息队列服务器进行重启;
    16:30,完成所有相关的服务器重启,系统恢复正常,并开始验证服务的稳定性;
    17:20,对外恢复服务;
  2. 问题出现原因。

    1
    2
    3
    4
    5
    1. 出现问题原因在于生产者发送消息过快,mq出现消息堆积,同时消费者处理过慢。
    2. 由于消息持续堆积引发了rabbitmq自己的保护机制,开始阻塞生产者写入消息。
    3. 生产者开启的是线程,线程被阻塞无法释放,线程不断开启,重启服务后没过几分钟服务又开始宕机。
    4. 虽然看见mq消费堆积,服务重启后依然在不断消费,所以还未察觉到是mq有问题。
    5. mq的阻塞写入造成一个循环,消费慢,写入快,系统服务级联反应。造成系统持续不可用。
  3. 执行过程。

    1
    2
    3
    4
    1. 线上出现问题,第一要点保证服务尽快可用。
    2. 对于中间件重启,第一要点恢复数据,防止数据丢失。
    3. mq由于本次消费堆积,进行了和相应业务方对接,对mq消息进行区分。哪些可以直接删除(需要参照业务)。哪些重新导出写脚本进行补偿。
    4. mq重启后服务一切正常,系统恢复可用状态

rabbitmq阻塞说明:https://cloud.tencent.com/developer/article/1454194

1
2
3
4
5
6
7
8
9
1. 因为RabbitMQ服务器在启动时会计算系统内存总大小。然后会根据vm_memory_high_watermark参数指定的百分比,进行控制
2. 当RabbitMQ的磁盘空闲空间小于50M(默认),生产者将被BLOCK,并且阻塞信息发布前,会尝试把内存中的信息输出到磁盘上
```

# redis故障

1. 事故现象:个别服务大量redis timeout。导致涉及缓存接口不可用。
```$xslt
1. 重启redis,数据抓紧恢复,影响1小时
  1. 问题出现原因。本次问题出现为3个原因进行叠加。
    1
    2
    3
    1. redis存在大量的大key,导致redis服务的压力过大。
    2. 中间件的不合理,由于开发者不了解jedis,对jedis在外面在包装一个线程池,导致线程池套用线程池。redis服务的tcp连接非常多。
    3. redis目前为共享一个,线上服务多。最终问题出现压垮了redis。

java线程池状态

  1. Java线程不同状态下中断机制的效果
    状态 中断效果 描述
    NEW    无
    RUNNABLE    设置中断标志位    用户自己判断是否中断,以及如何处理
    BLOCKED    设置中断标志位    用户自己判断是否中断,以及如何处理
    WAITING    抛InterruptedException异常,并清空中断标志位
    TIMED_WAITING    抛InterruptedException异常,并清空中断标志位
    TERMINATED    死亡状态