MySQL主从数据库配置

使用工具

MySQL数据版本:5.6.36-log、
两台云服务器(Linux系统)

首先,需要在Linux系统下安装MySQL,具体步骤可以参考这里,并且确保两台主机可以相互访问,可以直接ping一下。

配置Master

  • Linux环境下,MySQL的配置文件在/ect/my.cnf,直接打开并编辑该文件:vim /etc/my.cnf
  • [mysqld]下输入配置
    1
    2
    3
    4
    5
    log-bin=mysql-bin
    server-id=2
    binlog-ignore-db=information_schema
    binlog-ignore-db=mysql
    binlog-do-db=rwtest

这里的server-id用于标识唯一的数据库,这里设置为2在设从库需要设置为其他值

binlog-ignore-db:表示同步的时候ignore的数据库
binlog-do-db:指定需要同步的数据库

  • 重启MySQLservice mysqld restart
  • 登录MySQL并对访问用户进行授权:Slave机器需要File权限和REPLICATION SLAVE权限,当然也可以授予全部权限。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    grant file on *.* to 'root'@'%' identified by 'your password';
    grant replication slave on *.* to 'root'@'%' identified by 'your password';
    flush privileges;
    -------------------------------------------
    grant all privileges on *.* to 'root'@'%' identified by 'your password';
    flush privileges;
  • 完成后,可以查看下Master的状态:show master status

    1
    2
    3
    4
    5
    6
    7
    mysql> show master status;
    +------------------+----------+--------------+----------------------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+----------------------------------+-------------------+
    | mysql-bin.000001 | 2272 | rwtest | information_schema,mysql | |
    +------------------+----------+--------------+----------------------------------+-------------------+
    1 row in set (0.03 sec)

这里的FilePositionSlave中都要用到,Binlog_Do_DB指需要同步的数据库,Binlog_Ignore_DB指不需要同步的数据库,就是刚才配置的值。

配置Slave

  • 同样在[mysqld]下对配置文件进行编写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    log-bin=mysql-bin
    server-id=3
    binlog-ignore-db=information_schema
    binlog-ignore-db=mysql
    replicate-do-db=rwtest
    replicate-ignore-db=mysql
    log-slave-updates
    slave-skip-errors=all
    slave-net-timeout=60
  • 配置完毕后同样重启一下MySQL,并进入设置其对应的Master

    1
    2
    3
    4
    mysql> stop slave; #关闭Slave
    mysql> change master to master_host='Master主机IP',master_user='刚才授权的用户',master_password='your password',master_log_file='mysql-bin.000001', master_log_pos=2272;
    mysql> start slave; #开启Slave

master_log_filemaster_log_pos都是Master的状态值。必须对应

  • 登录slave的数据库,查看slave的状态:show slave status \G
    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
    Slave_IO_State: Waiting for master to send event
    Master_Host: 你的Master主机IP
    Master_User: root
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000001
    Read_Master_Log_Pos: 2272
    Relay_Log_File: izwz9fcvpu481xh55cegx0z-relay-bin.000002
    Relay_Log_Pos: 1339
    Relay_Master_Log_File: mysql-bin.000001
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Replicate_Do_DB: rwtest
    Replicate_Ignore_DB: mysql
    Replicate_Do_Table:
    Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
    Replicate_Wild_Ignore_Table:
    Last_Errno: 0
    Last_Error:
    Skip_Counter: 0
    Exec_Master_Log_Pos: 2272
    Relay_Log_Space: 1530
    Until_Condition: None
    Until_Log_File:
    Until_Log_Pos: 0
    Master_SSL_Allowed: No
    Master_SSL_CA_File:
    Master_SSL_CA_Path:
    Master_SSL_Cert:
    Master_SSL_Cipher:
    Master_SSL_Key:
    Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
    Last_IO_Errno: 0
    Last_IO_Error:
    Last_SQL_Errno: 0
    Last_SQL_Error:
    Replicate_Ignore_Server_Ids:
    Master_Server_Id: 2
    Master_UUID: de20814f-2fb8-11e7-8f61-5254002b91a1
    Master_Info_File: /var/lib/mysql/master.info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
    Master_Retry_Count: 86400
    Master_Bind:
    Last_IO_Error_Timestamp:
    Last_SQL_Error_Timestamp:
    Master_SSL_Crl:
    Master_SSL_Crlpath:
    Retrieved_Gtid_Set:
    Executed_Gtid_Set:
    Auto_Position: 0
    1 row in set (0.03 sec)

如果状态中含有没有报Error,则表示配置成功了。

接下来你通过可视化工具连接两个数据库,在主库中进行增删改操作,从库中也会有相应的操作,而在从库中进行此类操作对主库无效。

Dubbo 版 Helloworld

使用工具:MAVEN、IDEA、Spring、Dubbo、Zookeeper

直接上代码

项目结构:
structur

步骤如下:

搭建MAVEN项目,添加相关依赖

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--Zookeeper-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<!--dubbo-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.1</version>
</dependency>

dubbo-demo-consumer.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService"/>
</beans>

dubbo-demo-provider.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
</beans>

Provider.java

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class Provider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-demo-provider.xml");
context.start();
System.in.read();
}
}

Consumer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import com.alibaba.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-demo-consumer.xml");
context.start();
// obtain proxy object for remote invocation
DemoService demoService = (DemoService) context.getBean("demoService");
// execute remote invocation
String hello = demoService.sayHello("world");
// show the result
System.out.println(hello);
}
}

DemoService.java

1
2
3
4
5
6
7
package com.alibaba.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}

DemoServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
package com.alibaba.dubbo.demo.provider;
import com.alibaba.dubbo.demo.DemoService;
public class DemoServiceImpl implements DemoService{
public String sayHello(String name) {
return "Hello " + name;
}
}

运行方式:打开本地Zookeeper服务,先运行Provider,再运行Consumer

运行结果:控制台输出Hello world,Zookeeper 服务器会输出几行信息:
image
打开一个Zookeeper客户端检查是否有节点存在
image

Java GC 笔记

Java程序不用像C++程序在程序中自行处理内存的回收释放。这是因为Java在JVM虚拟机上增加了垃圾回收(GC)机制,用以在合适的时间触发垃圾回收,将不需要的内存空间回收释放,避免无限制的内存增长导致的OOM。

回收前的准备

垃圾回收器在对堆进行回收前,第一件事情就是要确定这些对象哪些还“存活”,哪些已经“死去”。

引用计数算法

给对象中添加一个引用计数器,每当有一个地方引用它,计数器加1,当引用失效时,计数器值减1;任何时刻计数器为0的对象就是不可能在被使用的。它实现简单,判定效率高,但主流的Java虚拟机都不用它来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。

可达性反洗算法

通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,即从GC Roots到这个对象不可达,则证明此对象是不可用的。即使有的对象相互关联,只要GC Roots不可达,均被判定为可回收对象。这也是主流的实现方法。

Java中可作为GC Roots的对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象

对象的自救

在可达性算法中判断为不可达的对象时,它们不会立即被回收,真正宣告一个对象死亡,还需要判断该对象是否有必要执行finalize()方法,当对象没有覆盖该方法,或者已经执行过该方法,虚拟机会将这两种情况视为没有必要执行。如果对象有必要执行该方法,该对象会被放在名为F-Queue的队列中,虚拟机会建立一个低优先级的FInalizer线程去执行该方法,并不保证等它运行结束,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环,很可能会导致F-Queue队列一直等待。如果在执行中重新与引用链上的任何一个对象建立关联,如把自己复制给某个类变量或者对象的成员变量,那么就可以逃脱这一次回收。

回收算法

标记-清楚算法

首先标记出所有需要回收的对象, 在标记完成后统一回收。如图:

mark-sweep

不足:标记和清除两个过程效率都不高;标记清除后产生大量不连续的内存碎片,导致以后运行的时候要分配较大对象时,无法找到足够的连续内存而不得不再一次垃圾回收。

复制算法

将内存按容量大小划分为大小相等的两块,每次使用其中一块,当这一块用完了,就将还存活着的对象复制到另一块上,然后再把已使用过的内存空间一次清理掉。
copying

标记-整理算法

同标记清理算法一样,首先标记对象,但后续步骤不是直接清理,而是将所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
mark-compact

分代收集

Java堆主要分为新生代和老年代。对于新生代,每次收集都有大量对象死去,所以采用“复制算法”,将少量存货对象副职即可完成收集;对于老年代,其中的对象存活率高、没有额外空间对它们进行分配担保,必须使用“标记清除算法”或“标记整理算法”来收集。

简单工厂模式

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式有三种:简单工厂模式、工厂方法模式、抽象工厂模式

这里先介绍简单工厂模式

简单工厂模式

又称静态工厂方法模式,从名字来看,这种模式体现的就是简单。主要的实现思想是通过创建一个工厂类,通过调用工厂方法的静态方法返回相应的对象。例如有一个计算程序:输入两个数和运算符号(+-*/),输出运算结果。可以这样写:

Executor 框架详解

Executor框架最核心的类是ThreadPoolExecutor,它是Java线程池的实现类,通过Executors工具类,可以创建3种类型的ThreadPoolExecutor:
首先附上ThreadPoolExecutor的构造函数

1
2
3
4
5
6
7
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

Executor 框架

Java的线程既是工作单元,也是执行机制。从JDK5开始,把工作单元与执行机制分离开来。工作单元包括RunnableCallable,而执行机制由Executor框架提供。

Executor 框架简介

HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程。Java线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也被收回。操作系统会调度所有线程并将他们分配给可用的CPU。如图

两级调度模型

Java 线程池

使用线程池的优点

  1. 降低资源消耗。通过反复利用已创建的线程降低创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建好就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

线程池主要工作原理

工作原理

Java8函数式编程学习笔记(初探)

编程语言的整个目的就在于操作值,要是按照历史上编程语言的传统,这些值被成为一等值,而编程语言中的其他结构也许有助于表示值的结构,但在程序执行期间不能传递,因此为二等值,比如方法和类等则是二等值,类可以实例化来产生值,但方法和类本身都不是值,java8的设计者则决定允许方法作为值,让编程更轻松.

举个栗子

就农场库存程序而言,如果要实现一个从列表中塞选出绿色苹果的功能,可能会这样写(1.0)

1
2
3
4
5
6
7
8
9
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ("green".equals(apple.getColor())){
result.add(apple);
}
}
return result;
}

Linux系统部署Web项目与问题分享

首先,需要有java环境和tomcat服务器,至于这个怎么安装,可以参考:云服务器 java+tomcat 部署与配置

项目部署

有两个大步骤:

Step1

将已经写好的web项目打包成war包,在IDEA中使用Maven项目时,可以直接在pom.xml中指定打包方式为war,在target目录中可以找到对应的war包文件

1
<packaging>war</packaging>

Step2

将打包好的*.war文件用文件传输工具上传到Linux系统中的Tomcat服务器的webapps文件夹中,上传之后,Tomcat会自动帮我们部署项目,接下来就可以访问了.

例如:按上面文章所采用的方法,需要把war包放到/usr/local/java/tomcat9/webapps文件夹下

之后就可以通过http://host:port/content来访问项目了

例如:有一个test项目

1
http://39.39.39.39:8080/test/index.html

|