Mac Android Studio离线配置gradle

Android Studio每次大更新,基本Gradle也需要大更新。每次通过studio都下载半天,甚至下载不了。所以通过在Gradle官网下载并手动配置,几分钟就可以搞定。

Gradle官网下载

1、首先要知道你需要下载的Gradle版本号。

在项目目录下,找到该文件:

2、下载gradle-4.1-all.zip之后,Copy 到Gradle所在的目录。

这里推荐用命令行直接打开:

#open .gradle

把gradle-4.1-all.zip直接放到gradle-4.1-all目录下的那一长串目录下。然后重启Android Studio就可以了。

JedisCluster应用详解

Redis集群的搭建参考Redis Cluster安装配置

本文主要介绍JedisCluster客户端结合spring注解的使用。

1、rediscluster.properties

#redis的服务器地址
redis.host=172.18.209.168
#redis的服务端口
redis.port=6379
#密码
redis.password=×××××××
#最大空闲数
redis.maxIdle=100
#最大连接数
redis.maxActive=300
#最大建立连接等待时间
redis.maxWait=1000
#客户端超时时间单位是毫秒
redis.timeout=100000
redis.maxTotal=1000
redis.minIdle=8
#明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#连接耗尽时是否阻塞  false报异常,ture阻塞直到超时
redis.blockWhenExhausted=false
#当设置为true,且服务开启的jmx服务时,使用jconsole等工具将看到连接池的状态
redis.jmxEnabled=true
#向连接池归还链接时,是否检测链接对象的有效性
redis.testOnReturn=false
#对象空闲多久后逐出,当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出
redis.softMinEvictableIdleTimeMillis=10000

#jediscluster
cluster1.host.port=172.18.209.168:7001
cluster2.host.port=172.18.209.168:7002
cluster3.host.port=172.18.209.168:7003
cluster4.host.port=172.18.209.169:7004
cluster5.host.port=172.18.209.169:7005
cluster6.host.port=172.18.209.169:7006

#rediscluster
spring.redis.cluster.nodes=172.18.209.168:7001,172.18.209.168:7002,172.18.209.168:7003,172.18.209.169:7004,172.18.209.169:7005,172.18.209.169:7006
spring.redis.cluster.max-redirects=3  

2、spring-redis.xml

<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:rediscluster.properties" />
</bean>

<!-- 基础参数配置 -->
<bean id="jedisClusterPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 连接池最大允许连接数 -->
    <property name="maxTotal" value="${redis.maxTotal}"/>
    <!-- 对象空闲多久后逐出,当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出 -->
    <property name="softMinEvictableIdleTimeMillis" value="${redis.softMinEvictableIdleTimeMillis}"/>
    <!-- 向连接池归还链接时,是否检测链接对象的有效性 -->
    <property name="testOnReturn" value="${redis.testOnReturn}"/>
    <!-- 当设置为true,且服务开启的jmx服务时,使用jconsole等工具将看到连接池的状态 -->
    <property name="jmxEnabled" value="${redis.jmxEnabled}"/>
    <!-- 连接耗尽时是否阻塞  false报异常,ture阻塞直到超时 -->
    <property name="blockWhenExhausted" value="${redis.blockWhenExhausted}"/>
    <!--最大空闲数-->
    <property name="maxIdle" value="${redis.maxIdle}" />
    <!--最大建立连接等待时间-->
    <property name="maxWaitMillis" value="${redis.maxWait}" />
    <!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个-->
    <property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>

<bean id="resourcePropertySource" class="org.springframework.core.io.support.ResourcePropertySource">
    <constructor-arg name="name" value="rediscluster.properties"/>
    <constructor-arg name="resource" value="classpath:rediscluster.properties"/>
</bean>

<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
    <constructor-arg name="propertySource" ref="resourcePropertySource"/>
</bean>

<!-- JedisCluster -->
<bean id="jedisCluster" class="*.*.jedis.JedisClusterFactory">
    <property name="addressConfig" value="classpath:rediscluster.properties" />
    <property name="addressKeyPrefix" value="cluster" />
    <property name="timeout" value="300000" />
    <property name="maxRedirections" value="6" />
    <property name="genericObjectPoolConfig" ref="jedisClusterPoolConfig" />
</bean>

<!-- 配置redis connection -->
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <constructor-arg ref="redisClusterConfiguration"/>
    <constructor-arg ref="jedisClusterPoolConfig"/>
</bean>

<!-- 数据以字符串存储  -->
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

<!-- 数据以字节流存储 -->
<bean id="jdkRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>

<!--  redis String类型 访问模版本 -->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
    <property name="connectionFactory" ref="redisConnectionFactory"/>
</bean>

<!-- redis 访问模版 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="redisConnectionFactory"/>
    <!-- 在hash数据结构中,hash-key的序列化策略 -->
    <property name="hashKeySerializer" ref="stringRedisSerializer"/>
    <!-- 对于普通K-V操作时,key采取的序列化策略 -->
    <property name="keySerializer" ref="stringRedisSerializer"/>
    <!-- value采取的序列化策略 -->
    <property name="valueSerializer" ref="jdkRedisSerializer"/>
</bean>

3、JedisClusterFactory.java

public class JedisClusterFactory implements FactoryBean, InitializingBean {

    private Resource addressConfig;
    private String addressKeyPrefix;

    private JedisCluster jedisCluster;
    private Integer timeout;
    private Integer maxRedirections;
    private GenericObjectPoolConfig genericObjectPoolConfig;

    private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");

    @Override
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    @Override
    public Class<? extends JedisCluster> getObjectType() {
        return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    private Set parseHostAndPort() throws Exception {
        try {
            Properties prop = new Properties();
            prop.load(this.addressConfig.getInputStream());
            Set haps = new HashSet<>();
            for (Object key : prop.keySet()) {
                if (!((String) key).startsWith(addressKeyPrefix)) {
                    continue;
                }
                String val = (String) prop.get(key);
                boolean isIpPort = p.matcher(val).matches();
                if (!isIpPort) {
                    throw new IllegalArgumentException("ip 或 port 不合法");
                }
                String[] ipAndPort = val.split(":");
                HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
                haps.add(hap);
            }

            return haps;
        } catch (IllegalArgumentException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new Exception("解析jedis配置文件失败", ex);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Set haps = this.parseHostAndPort();
        jedisCluster = new JedisCluster(haps, timeout, maxRedirections, genericObjectPoolConfig);
    }

    public void setAddressConfig(Resource addressConfig) {
        this.addressConfig = addressConfig;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setMaxRedirections(int maxRedirections) {
        this.maxRedirections = maxRedirections;
    }

    public void setAddressKeyPrefix(String addressKeyPrefix) {
        this.addressKeyPrefix = addressKeyPrefix;
    }

    public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) {
        this.genericObjectPoolConfig = genericObjectPoolConfig;
    }
}

Redis Cluster安装配置

Redis集群介绍

  • Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
  • Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
  • Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.
  • Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么: 节点 A 包含 0 到 5500号哈希槽. 节点 B 包含5501 到 11000 号哈希槽. 节点 C 包含11001 到 16384号哈希槽.

Redis Cluster集群的优势:

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
  • 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  • 支持主从复制模型。(slave->master 选举,集群容错)

Redis Cluster集群的主从复制模型:

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,假如有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.
然而如果在集群创建的时候我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。

Redis Cluster模型图

Redis Cluster的官方文档介绍

1、Redis Cluster集群配置

环境:CentOS7,两台服务器:172.18.209.168、172.18.209.168
Redis的安装步骤可以参考之前的文章 Linux安装配置Redis
我们需要创建三个主节点和三个从节点:

172.18.209.168:7001
172.18.209.168:7002
172.18.209.168:7003
172.18.209.169:7004
172.18.209.169:7005
172.18.209.169:7006

为了方便起见,我这里在168这台机器上创建所有的节点。

#cd /usr/local/redis-4.0.1
#mkdir /data/cluster
#cd /data/cluster
#mkdir 7001 7002 7003 7004 7005 7006

复制默认的配置文件到7001端口对应的目录下。

#cp ../../redis.conf 7001/
修改配置文件:
#vim 7001/redis.conf
port 7001
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

然后分别copy到其他端口对应的目录下,再打开配置文件修改一下端口号,其他内容不变。
进入对应的端口目录下启动实例:

#redis-server redis.conf

查看进程:

#ps -ef | grep redis
root 5371 1 0 Sep07 ? 00:01:35 redis-server *:6379
root 11891 1 0 10:35 ? 00:00:17 redis-server 172.18.209.168:7002 [cluster]
root 11914 1 0 10:37 ? 00:00:17 redis-server 172.18.209.168:7003 [cluster]
root 11921 1 0 10:37 ? 00:00:17 redis-server 172.18.209.168:7004 [cluster]
root 11926 1 0 10:37 ? 00:00:17 redis-server 172.18.209.168:7005 [cluster]
root 11931 1 0 10:37 ? 00:00:17 redis-server 172.18.209.168:7006 [cluster]

ps:我这里没有7001,是因为我创建后测试被我杀掉了。
接下来就是创建集群了,首先要安装依赖:

#yum install ruby rubygems -y

再安装gem-redis,下载gem-redis-4.0.0
下载gem-redis-4.0.0后执行命令安装

#gem install -l redis-4.0.0.gem

不出意外的话会报错:
ERROR: Error installing redis-4.0.0.gem:
redis requires Ruby version >= 2.2.2.
解决办法参考:redis requires Ruby version >= 2.2.2
为了方便执行命令,copy redis-trib 到/usr/bin目录下。

#cp redis-4.0.0/src/redis-trib.rb /usr/local/bin/redis-trib

接着开始创建集群,执行命令:

#redis-trib create --replicas 1 172.18.209.168:7001 172.18.209.168:7002 172.18.209.168:7003 172.18.209.169:7004 172.18.209.169:7005 172.18.209.169:7006

ps:redis-trib.rb 程序的命令是 create,这表示创建一个新的集群。
–replicas 1 表示为集群中的每个主节点创建一个从节点。
然后redis-trib 会打印出详细配置,确认没问题的话,输入yes确定:

>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.18.209.168:7001
172.18.209.169:7004
172.18.209.168:7002
Adding replica 172.18.209.169:7005 to 172.18.209.168:7001
Adding replica 172.18.209.168:7003 to 172.18.209.169:7004
Adding replica 172.18.209.169:7006 to 172.18.209.168:7002
M: 3e00a8c896fd0957e7d423e5b350415ba0572182 172.18.209.168:7001
slots:0-5460 (5461 slots) master
M: 28432a59f26a10f2c1eedad3f41c4ac47110d549 172.18.209.168:7002
slots:10923-16383 (5461 slots) master
S: 4806d7fb4c04880b3d7a6a20728088f243c52087 172.18.209.168:7003
replicates a59bef6cacd813b13742cdb22026bd167ef9aeaf
M: a59bef6cacd813b13742cdb22026bd167ef9aeaf 172.18.209.169:7004
slots:5461-10922 (5462 slots) master
S: f715ef8bcf25b1b7c0960c26b1e1b600c12ca09b 172.18.209.169:7005
replicates 3e00a8c896fd0957e7d423e5b350415ba0572182
S: dd39cd4b2b1ba8b34e0207023922f522ae72d2b6 172.18.209.169:7006
replicates 28432a59f26a10f2c1eedad3f41c4ac47110d549
Can I set the above configuration? (type 'yes' to accept):
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 172.18.209.168:7001)
M: 3e00a8c896fd0957e7d423e5b350415ba0572182 172.18.209.168:7001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: a59bef6cacd813b13742cdb22026bd167ef9aeaf 172.18.209.169:7004
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 4806d7fb4c04880b3d7a6a20728088f243c52087 172.18.209.168:7003
   slots: (0 slots) slave
   replicates a59bef6cacd813b13742cdb22026bd167ef9aeaf
M: 28432a59f26a10f2c1eedad3f41c4ac47110d549 172.18.209.168:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: dd39cd4b2b1ba8b34e0207023922f522ae72d2b6 172.18.209.169:7006
   slots: (0 slots) slave
   replicates 28432a59f26a10f2c1eedad3f41c4ac47110d549
S: f715ef8bcf25b1b7c0960c26b1e1b600c12ca09b 172.18.209.169:7005
   slots: (0 slots) slave
   replicates 3e00a8c896fd0957e7d423e5b350415ba0572182
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

这样就配置成功了。
可以使用命令验证:

#redis-cli -c -h 172.18.209.168 -p 7001
172.18.209.168:7001> set name "abswolf"
-> Redirected to slot [5798] located at 172.18.209.169:7004
OK
172.18.209.168:7001> get name
-> Redirected to slot [5798] located at 172.18.209.169:7004
"abswolf"
172.18.209.169:7004> 

ps:关于Redis集群的介绍来自Redis Cluster集群主从方案(附Jedis Cluster教程)

redis requires Ruby version >= 2.2.2

在做redis集群,安装redis-gem的时候出现该错误:

#gem install -l redis-4.0.0.gem
ERROR:  Error installing redis-4.0.0.gem:
redis requires Ruby version >= 2.2.2.

原来是因为CentOS7 yum库中ruby的版本支持到 2.0.0,可gem 安装redis需要最低是2.2.2。那么只能手动更新了。
解决步骤:

1、安装RVM

gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L get.rvm.io | bash -s stable
source /usr/local/rvm/scripts/rvm

2、安装Ruby新版本

rvm install 2.3.3

3、设置默认使用新版本

rvm use 2.3.3 --default

4、卸载旧版本

rvm remove 2.0.0

负载均衡使用nginx sticky实现session共享

nginx-sticky-module第三方模块主要用于基于cookie实现会话保持。

nginx sticky 模块工作流程图

下载nginx sticky

安装nginx+stiky

# wget http://nginx-sticky-module.googlecode.com/files/nginx-sticky-module-1.1.tar.gz
# tar -xzvf nginx-sticky-module-1.1.tar.gz
# wget http://nginx.org/download/nginx-1.8.1.tar.gz
# tar -xzvf nginx-1.8.1.tar.gz
# cd nginx-1.8.1
# ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --add-module=../nginx-sticky-module-1.1
# make
# make install

执行./configure的过程中可能会遇到以下错误:
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using –without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using –with-pcre= option.

执行该命令解决:

yum -y install pcre-devel

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using –with-openssl= option.

执行该命令解决:

yum -y install openssl openssl-devel

在执行make的时候会报错:
../nginx-sticky-module-1.1/ngx_http_sticky_misc.c:281:2: error: passing argument 2 of ‘ngx_sock_ntop’ makes integer from pointer without a cast [-Werror]
digest->len = ngx_sock_ntop(in, digest->data, len, 1);

解决办法:

cd ../nginx-sticky-module-1.1
vim ngx_http_sticky_misc.c
将281行的digest->len = ngx_sock_ntop(in, digest->data, len, 1);改成
digest->len = ngx_sock_ntop(in, sizeof(struct sockaddr_in), digest->data, len, 1);

配置nginx sticky

upstream dispatch {
    sticky;
    server 192.168.100.100:8080;
    server 192.168.100.102:8080;
}
server {
        listen       80;
        server_name  abswolf.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
                proxy_redirect off;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://dispatch;
        }
    }

Nginx配置启动脚本和开机启动

vim /etc/init.d/nginx
#!/bin/bash
# nginx Startup script for the Nginx HTTP Server
# it is v.0.0.2 version.
# chkconfig: - 85 15
# description: Nginx is a high-performance web and proxy server.
# It has a lot of features, but it's not for everyone.
# processname: nginx
# pidfile: /usr/local/nginx/logs/nginx.pid
# config: /usr/local/nginx/conf/nginx.conf
nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0
# Start nginx daemons functions.
start() {
if [ -e $nginx_pid ];then
echo "nginx already running...."
exit 1
fi
echo -n $"Starting $prog: "
daemon $nginxd -c ${nginx_config}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
return $RETVAL
}
# Stop nginx daemons functions.
stop() {
echo -n $"Stopping $prog: "
killproc $nginxd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /var/run/nginx.pid
}
# reload nginx service functions.
reload() {
echo -n $"Reloading $prog: "
#kill -HUP `cat ${nginx_pid}`
killproc $nginxd -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|reload|status|help}"
exit 1
esac
exit $RETVAL
chkconfig --add nginx #添加服务
chkconfig nginx on #开机启动

MySQL主从同步、主主同步配置

MySQL的 Replication 是一个异步的复制过程,从一个 MySQL Instance( Master)复制到另一个 MySQL Instance(Slave)。在 Master 与 Slave 之间的实现整个复制过程主要由三个线程来完成,其中两个线程(SQL线程和IO线程)在 Slave 端,另外一个线程(IO线程)在 Master 端。

软件环境:CentOS7,MySQL5.6.37 
服务器:192.168.1.100(Master),192.168.1.101(Slave)

1、配置192.168.1.100(Master)my.cnf

vim /etc/my.cnf
log-bin=mysql-bin #打开二进制日志(必须)
server-id=100 #设置唯一id,任意数。
binlog-do-db=test_db #设置要复制的数据库,多个数据库重复设置
#不需要复制的数据库,多个数据库重复设置,一般设置了bindlog-do-db,就不需要设置这个了。
binlog-ignore-db=mysql

注意:如果要实现复杂的主从同步:比如说,A->B->C,其中B是A的从服务器,同时B又是C的主服务器,那么B服务器除了需要打开log-bin之外,还需要打开log-slave-updates选项,可以在B上使用“show variables like ‘log%’;”来确认是否已经生效。

2、配置192.168.1.101(Slave)my.cnf

server-id=101
replicate-do-db=test_db 
log-bin=mysql-bin

3、在Master服务器中创建一个Slave可以登录的用户

GRANT ALL PRIVILEGES ON *.* TO 'abswolf'@'192.168.1.101' IDENTIFIED BY 'abswolf' WITH GRANT OPTION;

4、保持主从数据库的test_db数据库状态一致

数据量小的话可以用mysqldump,它有一个master-data参数很有用,通过使用此参数,导出的SQL文件里会自动包含CHANGE MASTER TO MASTER_LOG_FILE=’…’, MASTER_LOG_POS=…;,这样创建从服务器就更方便了。如果数据量大的话不太适合使用mysqldump(慢),如果是myisam表的话,加上–lock-all-tables参数,如果是innodb表的话,加上–single-transaction参数。
先在主服务器上锁定所有的表,以免在复制过程中数据发生变化:

mysql> flush tables with read lock;

然后在主服务器上查询当前二进制文件的文件名及偏移位置:

mysql > show master status;

然后停止主服务器上的MySQL服务:

shell> mysqladmin -u root shutdown

注意:如果仅是MyISAM的话,可以不停止MySQL服务,但要在复制数据文件的过程中保持只读锁,如果是InnoDB的话,必须停止MySQL服务。
再拷贝数据文件:

shell> tar -cvf /tmp/mysql-snapshot.tar .

拷贝完别忘了启动主服务上的MySQL服务了。
然后把数据文件应用到从服务器上,再次启动slave的时候使用,记得启动时加上skip-slave-start选项,使之不会立刻去连接master。

5、在Master服务器上执行命令mysql>show master status

+——————+———-+————–+——————+——————-+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+——————+———-+————–+——————+——————-+
| mysql-bin.000001 | 120 | test_db | | |
+——————+———-+————–+——————+——————-+
1 row in set (0.00 sec)
记录File的名字和Position,下面从服务器上设置需要用到。

6、在Salve服务器上设置相关的二进制日志信息

mysql> stop slave;
mysql> CHANGE MASTER TO
    -> MASTER_HOST='192.168.1.100',
    -> MASTER_USER='abswolf',
    -> MASTER_PASSWORD='abswolf',
    -> MASTER_LOG_FILE='mysql-bin.000001',
    -> MASTER_LOG_POS=120;
mysql> start slave; #开启Salve数据库复制功能
mysql> show slave status\G #查看是否开启成功,

*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.100
Master_User: abswolf
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 120
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

如果看到Slave_IO_Running和Slave_SQL_Running都是Yes的话,表示配置正确。

7、主主同步

主主同步就是两台数据库的数据进行变更的时候,另一台也会进行相应的变更。那么我们只需要把两个主从配置和起来就可以。需要不同的是一些主键的配置,分别在两台服务器的my.cnf配置文件中加上如下配置:

auto_increment_increment=2   #步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=1   #起始值。一般填第n台主MySQL。此时为第一台主MySQL

然后在192.168.1.101中设置Master的日志信息。参考上面的步骤反过来做即可。

8、注意事项 参考(转)mysql主从同步 binlog-do-db replicate-do-db

应该保证从服务器上任何数据的修改都是通过从主服务器上复制操作获取的,换句话说,从服务器应该是只读的,如果不能保证这一点,则可能造成主从数据不一致。
可以在从服务器的my.cnf里加入read-only参数来实现这一点,唯一需要注意的一点事read-only仅对没有super权限的用户有效。所以最好核对一下连接从服务器的用户,确保其没有super权限。

从理想角度看,主从数据库应该无故障的运转下去,可以有时候还是会出现一些莫名其妙的问题,比如说即便从未在从服务器上手动更新过数据,但还是可能遇到“Error: 1062 Duplicate entry”错误,具体原因不详,可能是MySQL本身的问题。遇到这类问题的时候,从服务器会停止复制操作,我们只能手动解决问题,具体的操作步骤如下:

mysql> set global sql_slave_skip_counter = 1;
mysql> start slave;

同样的操作可能需要进行多次,也可以设置自动处理此类操作,在从服务器的my.cnf里设置: slave-skip-errors=1062

最后再唠叨一下日志的问题:时间长了,数据库服务器上的二进制文件会越来越多,清理是必要的,你可以设置自动清理,相关参数是expire_logs_days,也可以使用手动删除的方式,但这里说的手动不是指rm,而是指PURGE BINARY LOGS,删除任何日志前,最好在所有的从服务器上通过show slave status命令确认一下相关日志是否已经无用。

补充:[ERROR] Error in Log_event::read_log_event(): ‘Event too big’ 在使用主从复制的时候,出现的问题多半是和日志(主服务器的二进制日志,从服务器的延迟日志)相关的。比如说加入你遇到了上面的错误,你可以根据错误日志的信息在主从数据库服务器上分别执行:

mysqlbinlog 日志文件 > /dev/null 查看错误,如果没有错误,则不会有任何输出,反之会输出错误信息,如果确定了错误是出现在主服务器二进制日志上,可以跳过适当的位置,再在从服务器上重新设定LOG_POS,如果确定了错误是出现在从服务器延迟日志上,则可以删除从服务器的延迟日志(使用CHANGE TO MASTER的时候,除非设定了延迟日志信息,否则会自动删除延迟日志),并在从服务器上重新设定LOG_POS。期间也可以考虑手动执行不能自动执行的SQL日志。

补充:配置的时候如果版本允许最好打开sync_binlog选项。

补充:有时候,从服务器延迟日志可能已经损坏,这时需要执行CHANGE MASTER TO设置新的日志文件信息,但是在从服务器上SHOW SLAVE STATUS会显示很多日志信息,他们的含义有所不同: Master_Log_File:Read_Master_Log_Pos 是IO相关的日志信息 Relay_Master_Log_File:Exec_Master_Log_Pos 是SQL相关的日志信息 从服务器需要设置的是SQL相关的日志信息: slave stop; change master to master_log_file=’(binlog name in relay_master_log_file)’, master_log_pos=(exec_master_log_pos number); slave start; 1) When you are using the master as a consistent snapshot, use SHOW MASTER STATUS to determine the position. 2) When you are using a slave as a consistent snapshot, use SHOW SLAVE STATUS and Exec_Master_Log_Pos.

MySQL 5.7 并行复制实现原理与调优

# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

show master status empty

问题出现在做Mysql的主主复制或者主从复制的时候,查看Master日志的使用命令:

mysql>show master status;
Empty set (0.00 sec)

解决方法:
1、如果是从yum install mysql的话,在/etc/my.cnf配置文件中的[mysqld] 增加一行:
log-bin=mysql-bin
2、找到log.bin的位置,并在配置文件/etc/my.cnf中指定:
log-bin=/var/lib/mysql/log-bin.log

重启数据库。

mysql> show master status;
+——————+———-+————–+——————+——————-+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+——————+———-+————–+——————+——————-+
| mysql-bin.000005 | 1234552 | | | |
+——————+———-+————–+——————+——————-+
1 row in set (0.00 sec)

CentOS7 yum安装MySQL

如果使用正常的yum install mysql-server 安装mysql的话,会提示:

No package mysql-server available.

原来是CentOS7带有MariaDB而不是mysql,MariaDB和MySQL一样也是开源的数据库。如果一定要用yum安装的话,可以使用命令mysql社区repo通过输入命令:

rpm -Uvh http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm

最后使用像安装MySQL的常规方法一样安装mysql:

yum install mysql mysql-server mysql-libs mysql-server

MySQL允许外网连接

1、设置mysql的配置文件

vim /etc/my.cnf
#bind-address=127.0.0.1
service mysql restart

2、登录mysql修改user表

mysql> use user;
mysql> select user,host from user;
mysql> update user set host='%' where user='root';
mysql> flush privileges;
或者:
mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;

1、其中第一个*表示数据库名;第二个*表示该数据库的表名;如果像上面那样 *.*的话表示所有到数据库下面的所有表都允许访问。
2、’%’表示允许访问到mysql的ip地址,也可以配置为具体的ip,%表示所有ip均可以访问。