精华内容
下载资源
问答
  • Redis是一种NoSQL的文档数据库,...下面用一个实例实现redis的读写分离,步骤如下:第一步:下载redis官网下载地址:https://redis.io/download下载最新的稳定版,解压拷贝到 ~/redis 中编译代码:$ make$ test第二...

    Redis是一种NoSQL的文档数据库,通过key-value的结构存储在内存中,Redis读的速度是110000次/s,写的速度是81000次/s,性能很高,使用范围也很广。

    下面用一个实例实现redis的读写分离,步骤如下:

    第一步:下载redis

    官网下载地址: https://redis.io/download

    下载最新的稳定版,解压拷贝到 ~/redis 中

    15e2869ea17563a63c6ec2762cfc5fd8.png

    编译代码:

    $ make

    $ test

    第二步:配置redis

    编辑redis.conf文件

    bind 127.0.0.1

    port 6379

    拷贝redis.conf文件,改名为slave.conf,打开编辑

    bind 127.0.0.1

    port 6380

    slaveof 127.0.0.1 6379

    第三步:运行服务

    开启【主服务】

    $ src/redis-server

    开启【从服务】

    $ src/redis-server slave.conf

    运行【主服务】的客户端

    $ src/redis-cli

    运行【从服务】的客户端

    $ src/redis-cli -h 127.0.0.1 -p 6380

    查看主从服务的关系

    $ src/redis-cli info replication

    4dda70d6d070141da6a1556a52b0a8ac.png

    第四步:测试服务器

    下面实例演示:在主服务器中存储一些数据,然后在从服务器中查询出来

    ddfa98eca342ad68219a741bc1ea9d81.png

    b8a32b97519c5c78421badac32937d58.png

    可以看出,从服务器成功的获取到了主服务器的备份数据。

    假如我们在从服务器中保存数据,看结果如何?

    185b3dfceed8d7c1512d556f535fcc70.png

    提示错误:

    (error) READONLY You can't write against a read only slave.

    说明从服务器只能读数据,而不能写入数据。

    数据在【从服务器】里【读】,在【主服务器】里【写】。

    这样就实现了redis数据库的读写分离功能。

    展开全文
  • Redis是一种NoSQL的文档数据库,...下面用一个实例实现redis的读写分离,步骤如下:第一步:下载redis官网下载地址:https://redis.io/download下载最新的稳定版,解压拷贝到 ~/redis 中 编译代码:$ make$ test第...

    Redis是一种NoSQL的文档数据库,通过key-value的结构存储在内存中,Redis读的速度是110000次/s,写的速度是81000次/s,性能很高,使用范围也很广。

    下面用一个实例实现redis的读写分离,步骤如下:

    第一步:下载redis

    官网下载地址: https://redis.io/download

    下载最新的稳定版,解压拷贝到 ~/redis 中

    15e2869ea17563a63c6ec2762cfc5fd8.png

    编译代码:

    $ make

    $ test

    第二步:配置redis

    编辑redis.conf文件

    bind 127.0.0.1

    port 6379

    拷贝redis.conf文件,改名为slave.conf,打开编辑

    bind 127.0.0.1

    port 6380

    slaveof 127.0.0.1 6379

    第三步:运行服务

    开启【主服务】

    $ src/redis-server

    开启【从服务】

    $ src/redis-server slave.conf

    运行【主服务】的客户端

    $ src/redis-cli

    运行【从服务】的客户端

    $ src/redis-cli -h 127.0.0.1 -p 6380

    查看主从服务的关系

    $ src/redis-cli info replication

    4dda70d6d070141da6a1556a52b0a8ac.png

    第四步:测试服务器

    下面实例演示:在主服务器中存储一些数据,然后在从服务器中查询出来

    ddfa98eca342ad68219a741bc1ea9d81.png

    b8a32b97519c5c78421badac32937d58.png

    可以看出,从服务器成功的获取到了主服务器的备份数据。

    假如我们在从服务器中保存数据,看结果如何?

    185b3dfceed8d7c1512d556f535fcc70.png

    提示错误:

    (error) READONLY You can't write against a read only slave.

    说明从服务器只能读数据,而不能写入数据。

    数据在【从服务器】里【读】,在【主服务器】里【写】。

    这样就实现了redis数据库的读写分离功能。

    展开全文
  • Redis的主从架构,能帮助我们实现读多,写少的情况,下面这篇文章主要给大家介绍了关于Redis如何实现数据库读写分离的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习...
  • EFCore如何通过代码实现读写分离,我们可以搜索到很多案例。总结起来一种方法是注册一个DbContextFactory,读操作注入ReadDcontext,写操作注入WriteDbcontext;另外一种是动态修改数据库连接串。 以上无论哪种方法...

    前言

    我们都知道当单库系统遇到性能瓶颈时,读写分离是首要优化手段之一。因为绝大多数系统读的比例远高于写的比例,并且大量耗时的读操作容易引起锁表导致无发写入数据,这时读写分离就更加重要了。

    EFCore如何通过代码实现读写分离,我们可以搜索到很多案例。总结起来一种方法是注册一个DbContextFactory,读操作注入ReadDcontext,写操作注入WriteDbcontext;另外一种是动态修改数据库连接串。

    以上无论哪种方法,实现简单粗暴的读写分离功能也不复杂。但是如果需要实现从库状态监测(从库宕机)、主备自动切换(主库宕机)、从库灵活的负载均衡配置、耗时查询的SQL路由到指定的从库、指定一些表不需要读写分离(如:基础数据表)等等,随着系统的数据量增加,以后还会涉及到分片(分库,分表),分片后又会涉及到分布式事务,以上这些如果通过业务代码去实现那需要费太多脑子且稳定性是个大问题。

    有没有更优雅的法案?中间件或许是个不错的选择,EFCore也一样可以很好的基于中间实现读写分离。
    为什么要使用中间件

    读写分离采用客户端直连方案(c#代码实现),因为少了一层中间件转发,查询性能可能会稍微好一点。但是这种方案,由于要了解后端部署细节,所以在出现主备切换、库迁移等操作的时候,客户端都需要感知到,并且需要调整数据库连接信息。如果通过中间件转发,客户端不需要关注后端细节、连接维护、主从切换等工作,都由中间件完成。这样可以让业务端只专注于业务逻辑开发。
    绝大部分生产项目,性能的瓶颈都在数据库。实现读写分离是解决性能瓶颈的首要手段之一。然而当读写分离还不能解决时,接下来手段就是分片(分库、分表)。数据被分到多个分片数据库后,应用如果需要读取数据,就要需要处理多个数据源的数据。如果没有数据库中间件,那么应用将直接面对分片集群,数据源切换、事务处理、数据聚合都需要应用直接处理,原本该是专注于业务的应用,将会花大量的工作来处理分片后的问题,最重要的是每个应用处理将是完全的重复造轮子。所以有了数据库中间件,应用只需要集中与业务处理,大量的通用的数据聚合,事务,数据源切换都由中间件来处理。
    国内各大厂、各个云平台都有自己的数据库中间件。
    

    几款免费开源中间件介绍

    目前社区成熟的、免费开源并且还在维护的中间件有mycat、shardingsphere-proxy、proxysql、maxscale。
    mycat

    官网:http://www.mycat.org.cn/
    开发语言:Java
    是否支持分片:支持
    支持的数据库:MySQL/Mariadb、Oracle、DB2、SQL Server、PostgreSQL
    路由规则:事务包裹的SQL会全部走写库、没有事务包裹SQL读写库通过设置Hint实现。其它功能通过配置文件实现。
    简介:mycat 2013年从阿里cobar分离出来重构而成,至今还一直在更新。据官方文档介绍2015年就已经有电信、银行级别的客户在用。mycat也是四个中间件中支持数据库类型最多、功能最全的。不管你是否使用mycat, mycat权威指南 这个PDF文件建议大家都看一看,里面详细介绍了各种主从复制方法、分库/分表的规则、如何实现以及它们优缺点等等,作者2016年写这本书应该花费了很多时间与精力。2016年后mycat官方文档、wiki以及配套的mycat-web几乎停滞了,这也是mycat需要吐槽的地方。如果mycat能一直坚持更新完善文档以及配套的mycat-web,更合理有序的规划产品版本,那么mycat还真是第一选择。
    

    shardingsphere-proxy

    官网:http://shardingsphere.apache.org/index_zh.html
    开发语言:Java
    是否支持分片:支持
    支持的数据库:MySQL/Mariadb、PostgreSQL
    路由规则:同一个线程且同一个数据库连接遇到有写操作那么之后的读操作都会读写库,同时也可以通过设置Hint强制读写库。其它功能通过配置文件实现。
    简介:shardingsphere有三个产品,对于dotneter来说shardingsphere-proxy是唯一的选择。shardingsphere是当当网开源贡献给社区,京东在基础上发扬光大。已于2020年4月成为Apache基金会顶级项目,shardingsphere-proxy后期可以重点关注。网上搜索shardingsphere-proxy相关文档绝大部分都是copy了官方的介绍文档,相关案例文档也很少,可能还需要再养一养。
    

    proxysql

    官网:https://proxysql.com/
    开发语言:C++
    是否支持分片:支持
    支持的数据库:MySQL/Mariadb
    简介:proxysql也是一款成熟的MySQL/Mariadb数据库中间件。官网文档完整,使用案例应该是4款中间件中最丰富和最多的。ProxySQL 的路由规则非常灵活,可以基于用户,基于schema,以及单个sql语句实现路由规则定制。同样也可以通过Hint与路由规则配合指定路由。proxysql也是一个非常不错的选择。
    

    maxscale

    官网:https://mariadb.com/kb/en/maxscale/
    开发语言:C
    是否支持分片:不支持
    支持的数据库:MySQL/Mariadb
    路由规则:事务包裹的SQL会全部走写库、没有事务包裹SQL读写库通过设置Hint实现。其它功能通过配置文件实现。
    简介:maridb开发的一个MySQL/Mariadb数据中间,已经非常成熟。官网文档非常完整,使用案例丰富。同时它提供了很多过滤器,如HintFilter;NamedServerFilter该过滤器可以设置指定表不需要读写分离,全部路由到写库;TopFilter该过滤器可以设置查询最慢的N条sql路由到指定读库;其他过滤器请查看官方文档。maxscale对于数据库集群高可用性提供的配置应该是4款中最丰富的。
    

    通过对4款中间件的简单介绍,我们发现他们都有自己路由规则,最配合丰富配置实现读写分离,而不是简单粗暴的分离。也都都提供了Hint的支持以及后端数据库监控。对于我们c#代码端要做的事情只需设置Sql的Hint,其它的交给中间件处理。

    Hint作为一种 SQL 补充语法,在关系型数据库中扮演着非常重要的角色。它允许用户通过相关的语法影响 SQL 的执行方式,对 SQL 进行特殊的优化。
    简单来说就是SQL语句前加注解,如maxscale指定读写库的Hint:SELECT * from table1; -- maxscale route to master
    

    EFCore生成maxscale的Hint

    读写分离必须要部署集群,基于maxscale中间件实现,还需要安装maxsale。

    mariadb基于GTID主从复制搭建
    maxscale安装
    

    EFCore的TagWith是什么请参考官方文档。
    点击查看完整源码

    public class EfCoreConsts
    {
    public const string MyCAT_ROUTE_TO_MASTER = “#mycat:db_type=master”;
    public const string MAXSCALE_ROUTE_TO_MASTER = “maxscale route to master”;
    }

    public abstract class BaseRepository<TDbContext, TEntity> : IEfRepository
    where TDbContext : DbContext
    where TEntity : EfEntity
    {
    public virtual IQueryable GetAll(bool writeDb = false) where TrdEntity : EfEntity
    {
    var dbSet = DbContext.Set().AsNoTracking();
    if (writeDb)
    //读操作路由到写库
    return dbSet.TagWith(EfCoreConsts.MAXSCALE_ROUTE_TO_MASTER);
    return dbSet;
    }

        public virtual async Task<IEnumerable<TResult>> QueryAsync<TResult>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null, bool writeDb = false)
        {
            if (writeDb)
                //这个方法集成了dapper实现复杂查询,读操作路由到写库
                sql = string.Concat("/* ", EfCoreConsts.MAXSCALE_ROUTE_TO_MASTER, " */", sql);
            return await DbContext.Database.GetDbConnection().QueryAsync<TResult>(sql, param, null, commandTimeout, commandType);
        }
    

    }

    基于maxscale要写的代码就是上面这些,数据库连接字符串与直连数据库一样,端口改成maxscale的端口。
    EFCore生成mycat的Hint

    再介绍一下mycat如何生成Hint
    同样也必须要先部署好集群,基于mycat中间件实现,还需要安装mycat。

    mariadb基于GTID主从复制搭建
    mycat安装
    

    EFCore生成mycat的Hint稍微复杂一些,EFCore的TagWith方法生成的Hint是这这样的

    – #mycat:db_type=master
    SELECT * FROM TABLE1

    mycat要求是这样

    /#mycat:db_type=master/
    SELECT * FROM TABLE1

    我以Pomelo.EntityFrameworkCore.MySql为例,简单点说就是EFCore有一个IQuerySqlGeneratorFactory接口,Pomelo的MySqlQuerySqlGeneratorFactory类实现了这个接口,Create()方法负责创建具体的QuerySqlGenerator,这个类负责查询SQL的生成。点击查看完整源码。

    我们需要做三件事情,

    新建工厂类AdncMySqlQuerySqlGeneratorFactory继承MySqlQuerySqlGeneratorFactory并覆写Create()方法。代码如下
    

    namespace Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal
    {
    ///
    /// adnc sql生成工厂类
    ///
    public class AdncMySqlQuerySqlGeneratorFactory : MySqlQuerySqlGeneratorFactory
    {
    private readonly QuerySqlGeneratorDependencies _dependencies;
    private readonly MySqlSqlExpressionFactory _sqlExpressionFactory;
    private readonly IMySqlOptions _options;

        public AdncMySqlQuerySqlGeneratorFactory(
            [NotNull] QuerySqlGeneratorDependencies dependencies,
            ISqlExpressionFactory sqlExpressionFactory,
            IMySqlOptions options) : base(dependencies, sqlExpressionFactory, options)
        {
            _dependencies = dependencies;
            _sqlExpressionFactory = (MySqlSqlExpressionFactory)sqlExpressionFactory;
            _options = options;
        }
    
        /// <summary>
        /// 重写QuerySqlGenerator
        /// </summary>
        /// <returns></returns>
        public override QuerySqlGenerator Create()
        {
            var result = new AdncQuerySqlGenerator(_dependencies, _sqlExpressionFactory, _options);
            return result;
        }
    }
    

    }

    新建Sql生成类AdncQuerySqlGenerator继承QuerySqlGenerator,覆写两个方法。
    

    namespace Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal
    {
    ///
    /// adnc sql 生成类
    ///
    public class AdncQuerySqlGenerator : MySqlQuerySqlGenerator
    {
    protected readonly Guid ContextId;
    private bool _isQueryMaseter = false;

        public AdncQuerySqlGenerator(
            [NotNull] QuerySqlGeneratorDependencies dependencies,
            [NotNull] MySqlSqlExpressionFactory sqlExpressionFactory,
            [CanBeNull] IMySqlOptions options)
            : base(dependencies, sqlExpressionFactory, options)
        {
            ContextId = Guid.NewGuid();
        }
    
        /// <summary>
        /// 获取IQueryable的tags
        /// </summary>
        /// <param name="selectExpression"></param>
        protected override void GenerateTagsHeaderComment(SelectExpression selectExpression)
        {
            if (selectExpression.Tags.Contains(EfCoreConsts.MyCAT_ROUTE_TO_MASTER))
            {
                _isQueryMaseter = true;
                selectExpression.Tags.Remove(EfCoreConsts.MyCAT_ROUTE_TO_MASTER);
            }
            base.GenerateTagsHeaderComment(selectExpression);
        }
    
        /// <summary>
        /// pomelo最终生成的sql
        /// 该方法主要是调试用
        /// </summary>
        /// <param name="selectExpression"></param>
        /// <returns></returns>
        public override IRelationalCommand GetCommand(SelectExpression selectExpression)
        {
            var command = base.GetCommand(selectExpression);
            return command;
        }
    
        /// <summary>
        /// 在pomelo生成查询sql前,插入mycat注解
        /// 该注解的意思是从写库读取数据
        /// </summary>
        /// <param name="selectExpression"></param>
        /// <returns></returns>
        protected override Expression VisitSelect(SelectExpression selectExpression)
        {
            if (_isQueryMaseter)
                Sql.Append(string.Concat("/*", EfCoreConsts.MyCAT_ROUTE_TO_MASTER, "*/ "));
    
            return base.VisitSelect(selectExpression);
        }
    }
    

    }

    注册DbContext时替换Pomelo的SQL生成工厂
    

    ///
    /// 注册EfcoreContext
    ///
    public virtual void AddEfCoreContext()
    {
    _services.AddDbContext(options =>
    {
    options.UseMySql(_mysqlConfig.ConnectionString, mySqlOptions =>
    {
    mySqlOptions.ServerVersion(new ServerVersion(new Version(10, 5, 4), ServerType.MariaDb));
    mySqlOptions.CharSet(CharSet.Utf8Mb4);
    });
    //替换默认查询sql生成器,如果通过mycat中间件实现读写分离需要替换默认SQL工厂。
    options.ReplaceService<IQuerySqlGeneratorFactory, AdncMySqlQuerySqlGeneratorFactory>();
    });
    }

    使用方法
    

    public class EfCoreConsts
    {
    public const string MyCAT_ROUTE_TO_MASTER = “#mycat:db_type=master”;
    public const string MAXSCALE_ROUTE_TO_MASTER = “maxscale route to master”;
    }

    public abstract class BaseRepository<TDbContext, TEntity> : IEfRepository
    where TDbContext : DbContext
    where TEntity : EfEntity
    {
    public virtual IQueryable GetAll(bool writeDb = false) where TrdEntity : EfEntity
    {
    var dbSet = DbContext.Set().AsNoTracking();
    if (writeDb)
    //读操作路由到写库
    return dbSet.TagWith(EfCoreConsts.MyCAT_ROUTE_TO_MASTER);
    return dbSet;
    }

        public virtual async Task<IEnumerable<TResult>> QueryAsync<TResult>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null, bool writeDb = false)
        {
            if (writeDb)
                //这个方法集成了dapper实现复杂查询,读操作路由到写库
                sql = string.Concat("/* ", EfCoreConsts.MyCAT_ROUTE_TO_MASTER, " */", sql);
            return await DbContext.Database.GetDbConnection().QueryAsync<TResult>(sql, param, null, commandTimeout, commandType);
        }
    

    }

    基于mycat要写的代码就是上面这些,数据库连接字符串与直连数据库一样,端口改成mycat的端口。

    展开全文
  • mysql实现读写分离

    2021-02-04 16:57:32
    传统的MySql读写分离方案是通过在代码中根据SQL语句的类型动态切换数据源来实现的,那么有没有什么中间件可以自动实现读写分离呢?小米开源的数据库中间件Gaea就可以实现,接下来我们将详细讲解如何使用Gaea来实现...

    简介

    传统的MySql读写分离方案是通过在代码中根据SQL语句的类型动态切换数据源来实现的,那么有没有什么中间件可以自动实现读写分离呢?小米开源的数据库中间件Gaea就可以实现,接下来我们将详细讲解如何使用Gaea来实现MySql的读写分离。
    Gaea是小米中国区电商研发部研发的基于MySql协议的数据库中间件,目前在小米商城大陆和海外得到广泛使用,包括订单、社区、活动等多个业务。Gaea支持分库分表、SQL路由、读写分离等基本特性,其中分库分表方案兼容了mycat和kingshard两个项目的路由方式。

    前提

    要实现读写分离的前提条件是要先实现MySql主从复制,具体实现可在这里查看:Mysql主从复制

    安装Gaea

    目前官方提供的是在Linux下直接安装的方式

    安装Go语言环境

    由于Gaea是使用Go语言编写的,所以我们需要先安装Go语言的环境。

    • 先下载安装包
    wget https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz
    

    如果提示wegt命令找不到,可执行

    yum -y install wget
    
    • 下载完成后解压到/mydata目录下
    tar -zxvf go1.13.5.linux-amd64.tar.gz -C /mydata/
    
    • 添加/mydata/go/bin目录到PATH变量中
    # 编辑环境变量配置文件
    vim /etc/profile
    # 在最后一行添加
    export GOROOT=/mydata/go
    export PATH=$PATH:$GOROOT/bin
    # 刷新配置文件
    source /etc/profile
    
    • 查看版本号,测试是否安装成功
    go version
    
    • 返回以下信息表示Go语言环境已经安装成功了
    go version go1.13.5 linux/amd64
    

    安装Gaea

    由于Gaea并没有提供安装包,所以我们需要自行编译源码获取可执行文件

    • 下载Gaea的源码,直接下载zip包即可
      下载地址:https://github.com/XiaoMi/Gaea
    • 将下载好的压缩包进行解压操作,这里我们解压到/mydata/gaea/目录下:
    unzip Gaea-master.zip
    
    • 进入/mydata/gaea/目录下,使用make命令对源码编译:
    make build
    

    tip:某些Go的依赖会下载不下来导致编译失败,这里可能会出现连接失败
    这时可以执行一下命令:

    #切换成一个国内能访问的代理地址
    go env -w GOPROXY=https://goproxy.cn;
    ##配置 GOPROXY 环境变量
    export GOPROXY=https://goproxy.io;
    

    这时再去执行make build 命令就能编译成功了

    • 编译完成后在/mydata/gaea/bin目录下会生成Gaea的执行文件gaea
      在这里插入图片描述
    • 由于我们没有搭建etcd配置中心,所以需要修改本地配置文件/mydata/gaea/etc/gaea.ini,将配置类型改为file
    config_type=file
    

    在这里插入图片描述

    • 添加namespace配置文件,用于配置我们的主从数据库信息,配置文件地址:/mydata/gaea/etc/file/namespace/wdj_namespace_1.json
      在这里插入图片描述
    • 配置文件内容如下
    {
        "name": "wdj_namespace_1",
        "online": true,
        "read_only": false,
        "allowed_dbs": {
            "mall": true
        },
        "slow_sql_time": "1000",
        "black_sql": [
            ""
        ],
        "allowed_ip": null,
        "slices": [
            {
                "name": "slice-0",
                "user_name": "root",
                "password": "root",
                "master": "192.168.131.3:3307",
                "slaves": ["192.168.131.3:3308"],
                "statistic_slaves": null,
                "capacity": 12,
                "max_capacity": 24,
                "idle_timeout": 60
            }
        ],
        "shard_rules": null,
        "users": [
            {
                "user_name": "wdj",
                "password": "123456",
                "namespace": "wdj_namespace_1",
                "rw_flag": 2,
                "rw_split": 1,
                "other_property": 0
            }
        ],
        "default_slice": "slice-0",
        "global_sequences": null
    }
    

    namespace配置文件

    namespace的配置格式为json,包含分表、非分表、实例等配置信息,都可在运行时改变

    • 整体配置说明
      在这里插入图片描述
    • slice配置
      在这里插入图片描述
    • users配置
      在这里插入图片描述

    在Docker容器中运行

    打包成Docker镜像

    Docker Hub 中并没有打包好的Gaea镜像,我们需要自行构建一个

    • 这里我们使用Dockerfile构建Docker镜像,Dockerfile中的内容如下
    # 该镜像需要依赖的基础镜像
    FROM golang:latest
    # 将当前目录下的gaea源码包复制到docker容器的/go/Gaea-master目录下,对于.tar.gz文件会自动解压
    ADD Gaea-master.tar.gz /go/Gaea-master
    # 将解压后的源码移动到/go/gaea目录中去
    RUN bash -c 'mv /go/Gaea-master/Gaea-master /go/gaea'
    # 进入/go/gaea目录
    WORKDIR /go/gaea
    RUN bash -c 'go env -w GOPROXY=https://goproxy.cn'
    RUN bash -c 'export GOPROXY=https://goproxy.io'
    # 将gaea源码进行打包编译
    RUN bash -c 'make build'
    # 声明服务运行在13306端口
    EXPOSE 13306
    # 指定docker容器启动时执行的命令
    ENTRYPOINT ["/go/gaea/bin/gaea"]
    # 指定维护者的名字
    MAINTAINER wdj
    

    TIP;在此之前我们需要把Gaea的源码压缩包转换为.tar.gz格式
    转换命令:

    #将xxx.zip解压  
    unzip xxx.zip
    #会得到xxx文件夹
    #将xxx压缩成tar.gz   
    tar -czf  xxx.tar.gz  xxx
    #就得到了xxx.tar.gz
    
    • 之后使用Docker命令构建Gaea的Docker镜像
    docker build -t gaea:1.0.2 .
    
    • 构建成功控制台输出
      在这里插入图片描述
    • 将本地安装的Gaea配置文件复制到/mydata/gaea-docker/etc/目录下
    cp -r /mydata/gaea/etc/ /mydata/gaea-docker/etc/
    
    • 使用Docker命令启动Gaea容器
    docker run -p 13306:13306 --name gaea \
    -v /mydata/gaea-docker/etc:/go/gaea/etc \
    -d gaea:1.0.2
    

    测试读写分离

    测试思路:首先我们关闭从实例的主从复制,然后通过Gaea代理来操作数据库,插入一条数据,如果主实例中有这条数据而从实例中没有,说明写操作是走的主库。然后再通过Gaea代理查询该表数据,如果没有这条数据,表示读操作走的是从库,证明读写分离成功。

    • 通过Navicat连接到Gaea代理,注意此处账号密码为Gaea的namespace中配置的内容,端口为Gaea的服务端口
      在这里插入图片描述
    • 通过Navicat分别连接到主库和从库,用于查看数据,此时建立了以下三个数据库连接
      在这里插入图片描述
    • 通过stop slave命令关闭mysql-slave实例的主从复制功能
      在这里插入图片描述
    • 通过Gaea代理在test表中插入一条数据
      在这里插入图片描述
    • 在主库中查看test表的数据,发现已有该数据
      在这里插入图片描述
    • 在从库中查看test表的数据,发现没有该数据,证明写操作走的是主库
      在这里插入图片描述
    • 直接在代理中查看test表中的数据,发现没有该数据,证明读操作走的是从库
      在这里插入图片描述

    结合SpringBoot使用

    在我们的SpringBoot应用中,我们只需要把Gaea的代理服务直接当做数据库服务来使用就可以实现读写分离了。

    测试连接代码

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    /**
     * @author wdj
     * Created on 2021/2/5 11:40
     */
    
    public class JdbcTest {
        //属性
        private static String driver="com.mysql.jdbc.Driver";
        //JDBC驱动类名
        private static final String URL="jdbc:mysql://192.168.131.3:13306/mall?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false";
        private static final String USER="wdj";
        //用户名
        private static final String PASSWORD="123456";
        //密码
        //创建连接
        public static Connection getConnection(){
            Connection conn=null;
            try {
                Class.forName(driver);
                //加载jdbc驱动
                conn=DriverManager.getConnection(URL, USER, PASSWORD);
    //创建连接
                //System.out.println("创建连接成功!");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return conn;
        }
        //关闭连接
        public static void close(Connection conn,Statement st,ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                    //System.out.println("关闭rs成功!");
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
            if(st!=null){
                try {
                    st.close();
                    //System.out.println("关闭st成功!");
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                    //System.out.println("关闭conn成功!");
                } catch (Exception e) {
    
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        }
    
    
        public static void main(String[] args) {
    
            try        {
                Connection conn = JdbcTest.getConnection();
                if(conn!=null)
                {
                    System.out.println("数据库连接正常!");
                }
                else            {
                    System.out.println("数据库连接异常!");
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace();
            }
    
        }
    }
    
    展开全文
  • 这节说代码如何和mycat实现读写分离 1、pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apa...
  • 文章目录1. 环境搭建具备条件1.1 dubbo+... 如何测试读写分离 1. 环境搭建具备条件 1.1 dubbo+springboot2.x+mybatisPlus3.x环境 但是首先你要有一些MybatisPlus3.x的基本概念,有兴趣的童鞋可以去官网参考一下,...
  • 传统的MySql读写分离方案是通过在代码中根据SQL语句的类型动态切换数据源来实现的,那么有没有什么中间件可以自动实现读写分离呢?小米开源的数据库中间件Gaea就可以实现,接下来我们将详细讲解如何使用Gaea来实现...
  • 主要给大家介绍了关于spring boot + mybatis如何实现数据库的读写分离的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • Springboot+Mybatis+Druib实现读写分离

    千次阅读 2020-08-01 23:15:26
    本文主要就是介绍springboot+mybatis+druib 连接池架构下如何实现读写分离以加快数据库读取速度。 2.如何实现 注:这里不讲如何搭建主从数据库集群。主要讲代码集成。 总结下来需要实现读写分离,主要需
  • PHP+MySQL实现读写分离

    千次阅读 2019-05-21 09:23:06
    关于 中间件 和 驱动层的方式这里不做深究 暂且简单介绍下 如何通过PHP代码来控制MySQL读写分离 我们都知道 “读” 在SQL语句里是 “SELECT”, ”写” 是 “INSERT” 那么我们第一时间就应该想到 字符串截取 substr...
  • 最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考。 关键词:DataSource 、AbstractRoutingDataSource、AOP 首先是配置数据源 <!--读数据源配置--><bean id=...
  • 大型网站为了软解大量的并发...Ok切入今天文章主题,利用MySQL主从配置,实现读写分离,减轻数据库压力。这种方式,在如今很多网站里都有使用,也不是什么新鲜事情,今天总结一下,方便大家学习参考一下。 概述:搭设
  • Mysql主从配置,实现读写分离 大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够。到了数据业务层、数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库...
  • 已经通过mycat对数据进行了读写分离,在代码如何实现读写用不同的DataSource呢? 原理是:通过切面的方式对方法进行判断,如果是增删改,设置数据源为updateDataSource,如果是查询操作,设置数据源为...
  • 大型网站为了软解大量的并发访问,...这时候,我们会考虑如何减少数据库的联接,一方面采用优秀的代码框架,进行代码的优化,采用优秀的数据缓存技术如:memcached,如果资金丰厚的话,必然会想到假设服务器群,来...
  • 徐无忌MySQL笔记:案例实战:如何实现MySQL数据库的读写分离? 完成:第一遍 1.理想的主从架构实现的效果是怎样的? 主库负责所有读写操作,从库只实现对主库备份功能,这样的主从架构性价比是很低的 我们所希望的...
  • 使用springboot实现读写分离+项目实战

    千次阅读 2019-03-27 22:19:47
    使用springboot实现读写分离这也是闲着无聊然后去了解了一下然后写了一个项目,如有不足,欢迎来指出来功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一...
  • 网上大多读写分离实例,都是需要手动侵入代码修改数据源,本博客主要实现如何对现有系统,不侵入原有代码,进行读写分离配置。 Mybatis-Plus自带动态数据源配置,但是也需要对手动配置,需要的可以参考官网Mybstis...
  • 主要介绍了详解如何利用amoeba(变形虫)实现mysql数据库读写分离,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Spring boot实现数据库读写分离

    千次阅读 2019-04-29 19:27:38
    数据库配置主从之后,如何代码层面实现读写分离? 用户自定义设置数据库路由 Spring boot提供了AbstractRoutingDataSource根据用户定义的规则选择当前的数据库,这样我们可以在执行查询之前,设置读取从库,在...
  • 数据库配置主从之后,如何代码层面实现读写分离?所以下面这篇文章主要给大家介绍了关于spring boot配置读写分离的完整步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...
  • php实现MySQL读写分离

    2019-05-21 10:44:14
    关于 中间件 和 驱动层的方式这里不做深究 暂且简单介绍下 如何通过PHP代码来控制MySQL读写分离 我们都知道 “读” 在SQL语句里是 “SELECT”, ”写” 是 “INSERT” 那么我们第一时间就应该想到 字符串截取 ...
  • 想了半天如何解决mongodb复制集master出问题,程序如何自动连接到slave(当然这里冲裁选举完毕),朋友说java代码可以实现, 找到如下代码: http://api.mongodb.org/java/3.0/com/mongodb/MongoClient.html ...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 222
精华内容 88
关键字:

代码如何实现读写分离