net Core 使用MyCat分布式数据库,实现读写分离

net Core 使用MyCat分布式数据库,实现读写分离

目录索引 

【无私分享:ASP.NET CORE 项目实战】目录索引

简介

  

  MyCat2.0版本很快就发布了,关于MyCat的动态和一些问题,大家可以加一下MyCat的官方QQ群:106088787。我们今天主要介绍一下,在我们的Asp.net Core中如何使用Mycat,这源于一个大神(Amamiya Yuuko)的分享,但是,这中间还是有少许的 坑 :

  首先,因为大神是比较忙的,而且主要分享关键技术,所以有些地方很简略,而往往这些简略的地方容易造成新手的困惑。

  其次,在尝试了N次失败后,我发现大神的代理程序是有问题的,具体是什么问题,我们待会详细解释,经过修改之后的代理程序,可以正常运行。

  因此,我觉得很有必要写这篇文章,一步一步搭建、测试、运行。

什么是MyCat?

  

  

  从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。

  MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。

  此外,开发者可以根据不同的需求将表分配不同的数据节点,比如Table A存放在关系型数据库中(如MySQL),而Table B可能更适合NoSQL(如MongoDB),在MyCAT中开发者只需要简单配置,即可让MyCAT完成这一系列操作的路由。

  关于更多MyCat,大家可以参照官网:http://www.mycat.org.cn/

MyCat的优势

  

  • 基于阿里巴巴的开源项目Cobar,具备良好的稳定性、可靠性、优良的结构和优良的性能,拥有许多的项目案例。站在巨人的肩膀上,MyCAT将走的更远。
  • 广泛借鉴最好的开源项目和创新的理念,让这些融入MyCAT的基因,使MyCAT成为领先其他电商等类似的开源项目,甚至超过了一些企业级应用。
  • MyCAT技术团队的参与者都经历过至少五多年的项目经验,团队中包括一些高级软件工程师、架构师、DBA。由精英们组成的MyCAT技术团队将确保产品质量。
  • MyCAT是完全独立的社区,不依附于任何企业,遵循着完全开放、免费、开源的原则。它不像一些开源项目,重要的功能封闭在其商业产品,并使开源项目像一个装饰。
  • 支持超过60种的数据库作为数据节点,如MySQL、SQL Server、Oracle、MongoDB、DB2等

MyCat与ADO.NET

  由于MyCAT与MySQL协议有些许差异,开发者可能不能够直接使用Oracle官方提供的Mysql.Data(ADO层)来与MyCAT直接连接,因此有大神专门为.NET开发者设计了针对MyCAT优化过的ADO层驱动,即 Pomelo.Data.MyCat,开发者通过使用MyCatConnection、MyCatCommand类可以实现对MyCAT的连接与查询。

MyCat 与 Entity Framework Core

  由于MyCAT的协议与MySQL有所差异,导致了无论是Java平台下的Hibernate还是.NET下的Entity Framework都无法使用MySQL的provider直接来操作MyCAT。这点在EF中的Migrations以及Code First上表现的尤为明显,此外开发者不仅需要手动建库,还需要配置分片规则等,操作繁琐。

因此我们使用第三方专门为MyCAT量身打造的Entity Framework Core Provider,即 Pomelo.EntityFrameworkCore.MyCat。

安装Java8

  MyCat 需要 java cdk的支持,安装方法网上很多很详细,这里我们就不罗列了。

下载MyCat Server

  废话不多说,我们来开始我们的MyCat之旅:

  我们演示使用的服务器是:CentOS7 当然,Windows 也是支持的,我们以 CentOS为例。

  首先,我们在服务器安装 MySQL ,这里我安装的是 MySQL 5.7,关于 MySQL的安装,我们这里就不演示了,没有装过的朋友,网上有大片的详细安装步骤。值得注意的是,安装完MySQL之后,我们需要编辑 my.cnf 文件,将MySQL的默认编码设置为 UTF8 。

  我们下载MyCat Server:我是通过 wget XXXXXXXX;大家也可以直接下载下来,然后通过 FTP 传到服务器上。

  

  因为我们是Linux,所以我选择 linux.tar.gz,使用 Windows的朋友可以选择 win.tar.gz

  

  

  [[email protected] ~]# wget https://github.com/MyCATApache/Mycat-download/blob/master/1.5-RELEASE/Mycat-server-1.5.1-RELEASE-20160816173057-linux.tar.gz

  

  解压 MyCat Server 压缩包:[[email protected] ~]# tar -xzvf Mycat-server-1.5.1-RELEASE-20160816173057-linux.tar.gz

  

  将文件移动至 /usr/local/mycat 目录下:[[email protected] ~]# mv mycat /usr/local/mycat

  

  

  这样,我们的 MyCat Server,就完成了,我们来运行一下:

  打开mycat/bin目录,运行 ./mycat start ,通过 ./mycat status 查看 mycat的运行情况

  

  

  启动:./mycat start    重新启动:./mycat restart  停止:./mycat stop  状态:./mycat status

下载 运行代理程序

  我们使用的代理程序是由 Amamiya Yuuko 写的 Pomelo.EntityFrameworkCore.MyCat.Proxy

  

  这个代理程序是由问题的,我们前面说过了,我们先来尝试一下,对于出现的问题和解决方式,我们再讲解。

  我们先下载这个代理程序,下在方法跟上面 MyCat Server 一样,可以使用多种方式,大家可以直接下载到本地,解压完成后,把解压的文件通过FTP上传至proxy目录,我这里还是使用 wget

  

  

  [[email protected] ~]# wget https://github.com/PomeloFoundation/Entity-Framework-Core-MyCat-Proxy/releases/download/1.0.0-alpha2/MyCat-Entity-Framework-Core-Proxy.1.0.0-alpha2-netcore100.zip

  

  创建一个目录 proxy ,将压缩包移动到此目录下:

  [[email protected] ~]# mkdir proxy

  [[email protected] ~]# mv MyCat-Entity-Framework-Core-Proxy.1.0.0-alpha2-netcore100.zip proxy/MyCat-Entity-Framework-Core-Proxy.1.0.0-alpha2-netcore100.zip

  进入 proxy ,并解压 MyCat-Entity-Framework-Core-Proxy.1.0.0-alpha2-netcore100.zip 压缩包:

  [[email protected] ~]# cd proxy

   [[email protected] proxy]# unzip MyCat-Entity-Framework-Core-Proxy.1.0.0-alpha2-netcore100.zip

  编辑 config.json 文件,修改 MyCatRoot为"/usr/local/mycat":

  

安装.NET Core SDK for CentOS

  详见:【(第十章)】发布项目到 Linux 上运行 Core 项目

运行代理程序

  

  我们来运行一下代理程序:[[email protected] proxy]# dotnet Pomelo.EntityFrameworkCore.MyCat.Proxy.dll

  

  我们先不管在程序中是怎么实现MyCat的,这个后面我们再讲,我们先来测试一下这个代理程序,不先解决这个代理的问题,到后面都很难知道到底是程序出错还是服务器的问题还是代理的问题:

  我在VS2015的控制台里执行:Add-Migration  MySQL_Init(也可以使用命令:dotnet ef Migrations add  MySQL_Init)

  

  出错了。。。这个错误是操作超时了,这极有可能是连接不上MyCat服务器,这个问题曾困扰了我一段时间,后来突然发现忽略了一个重要的东西,防火墙。。。

  我们的代理使用的是7066端口,我们来开启一下防火墙端口,并重启防火墙:

  [[email protected] ~]# firewall-cmd --zone=public --add-port=7066/tcp --permanent

   [[email protected] ~]# systemctl restart firewalld

  

  我们再来执行 Add-Migration  MySQL_Init :

  

  创建数据库: Update-Database -Verbose (dotnet ef database update)

  

  

  创建成功,看似没有什么问题。

   我们来插入几条数据看下:出错了 Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

  超时,服务器没有响应。这是怎么回事呢,我们通过 Navicat 来连接一下 MyCat(同样服务器防火墙要开启 8066 端口,默认MyCat 是8066 端口,方法同上):

  

  首先,我们来检查一下我们的MyCat状态:   

  

  MyCat Server 关闭了。。。我们重启:

  

  

  重启之后,总是自动关闭。这是什么原因?我们看下日志(/usr/local/mycat/logs/wrapper.log):

  

  这下看清楚了,是因为rule columns 有多个 values值,这个是什么东西呢,这是就是配置MyCat 规则的拆分的列的名称。

  我们来看下代理生成的rule(/usr/local/mycat/conf/rule.xml):

  

  也就是说:MyCat 这个拆分规则 只支持单个,但是我们的代理生成了多个,导致 MyCat Server 错误。

  我这里修改一下,改成<columns>ID</columins>,MyCat 启动就没有问题了,但是问题来了,我这里有四个实体类,其中有三个的主键都是ID,但是有一个的主键是UserID,那么只根据ID拆分显然是不合理的。

  我们来看下 schema (/usr/local/mycat/conf/schema.xml):

  

  大家注意 table 标签的 rule 属性,都是 db_wkmvc_rule 跟 rule.xml 的 tableRule 标签的 name 属性是对应的。也就是说,这个表,按照 rule=""的规则,根据columns的值(列名,这里是主键也就是ID或UserID)拆分数据。

  如何解决?

  我想到的方案就是,每个表一个单独的规则,每个规则的columns值就是当前这个表的主键。

  我们来看下代理程序的源码:

  根据方法名称,我们可以看出这两个方法应该就是修改 rule.xml 和 schema.xml

  

  我们来看下GenerateRuleXml() :

  

  这一段就是生成xml内容的,为什么我们的 rule.xml 中的 columns 会生成 诸如:ID,ID,ID,UserID 呢?我们可以很清楚的看出 <columns>{ string.Join(",", s.Keys.First()) }</columns>

  在 foreach 循环 schema.xml 中 table 标签的时候,把他们的 Key (primaryKey) 通过 string.join 组合起来了,并且只生成了一个 tableRule

  那么,按照我们的方案,应该是每个表(在 schema.xml 中体现就是 一个 table 标签),单独生成一个 规则。

  

  修改起来也很简单:

  我们把循环中的 ruleXml="" 改为 rulexml+="",然后把 <columns>{ string.Join(",", s.Keys.First()) }</columns> 改为当前表的 primaryKey :<columns>{ s.Keys.First() }</columns>

  

  这是修改后的完整的 public void GenerateRuleXml(List<MyCatTable> Schema, List<MyCatDataNode> DataNodes, string database, bool IsUnder16)

  public void GenerateRuleXml(List<MyCatTable> Schema, List<MyCatDataNode> DataNodes, string database, bool IsUnder16)
  {
    foreach(var s in Schema)
    {
      if (s.Keys.Count() != 1)
              continue;

      string ruleXml = "";
      string funcXml = "";
      if (IsUnder16)
      {
        ruleXml += [email protected]"
              <tableRule name=""{ database }_{ s.TableName }_rule"">
              <rule>
              <columns>{ s.Keys.First() }</columns>
              <algorithm>{ database }_{ s.TableName }_func</algorithm>
              </rule>
              </tableRule>
              ";

        funcXml += [email protected]"
              <function name=""{ database }_{ s.TableName }_func"" class=""org.opencloudb.route.function.PartitionByMod"">
              <property name=""count"">{ s.DataNodes.Count() }</property>
              </function>
              ";
      }
      else // 1.6+
      {

        ruleXml += [email protected]"
              <tableRule name=""{ database }_{ s.TableName }_rule"">
              <rule>
              <columns>{ s.Keys.First() }</columns>
              <algorithm>{ database }_{ s.TableName }_func</algorithm>
              </rule>
              </tableRule>
              ";

        funcXml += [email protected]"
              <function name=""{ database }_{ s.TableName }_func"" class=""io.mycat.route.function.PartitionByMod"">
              <property name=""count"">{ s.DataNodes.Count() }</property>
              </function>
              ";

      }

      using (var reader = XmlReader.Create(Path.Combine(MyCatRoot, "conf", "rule.xml"), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore }))
      {
        var xml = new XmlDocument();
        xml.Load(reader);
        var mycatRule = xml.ChildNodes.Cast<XmlNode>().Single(x => x.Name == "mycat:rule");
        foreach (var x in mycatRule.ChildNodes.Cast<XmlNode>().Where(x => (x.Name == "tableRule" && x.Attributes["name"].Value == $"{ database }_{ s.TableName }_rule") || (x.Name == "function" &&         x.Attributes["name"].Value == $"{ database }_{ s.TableName }_func")).ToList())
        mycatRule.RemoveChild(x);
        mycatRule.InnerXml = ruleXml + mycatRule.InnerXml;
        mycatRule.InnerXml += funcXml;
        reader.Dispose();
        File.WriteAllText(Path.Combine(MyCatRoot, "conf", "rule.xml"), PatchXml("rule", xml.OuterXml));
      }
    }
  }

  我们重新编译生成,发布出来上传至服务器,替换掉我们之前的代理程序。然后重新运行一下,我们再来看下 rule.xml 和 schema.xml:

  

  

  是不是按照我们的预期,我们看下MyCat Server的状态:

  

  MyCat 连接也没问题了

  

  (后记:关于这个代理的问题,已经提交给作者了,这个代理程序我测试有一段时间了,当时还是alpha1版本,写文章的时候,我看到 alpha2版本貌似改进了,但是源码没有修改。)

如何在Asp.net Core中使用 Mycat

  分两部分,第一部分就是最简洁的应用,第二部分是我在项目中的应用,大家自行参考。

  第一部分,最简洁的应用(作者 Demo):

  

  首先,我们新建一个控制台程序

  

  并将 Pomelo.EntityFrameworkCore.MyCat 添加至 project.json 中(Nuget:Install-Package Pomelo.EntityFrameworkCore.MyCat -Pre)

  

  创建一个Blog模型:  

  public class Blog
  {
    public long Id { get; set; }

    public string Title { get; set; }

    public string Content { get; set; }

    public DateTime Time { get; set; }

  }

  

  创建DbContext类,并重写DbContext中的OnConfiguring方法,配置数据节点以及MyCAT服务器信息

  public class SampleContext : DbContext
  {
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
      base.OnConfiguring(optionsBuilder);

      optionsBuilder.UseMyCat("server=IP;port=8066;uid=test;pwd=test;database=blogs")
                .UseDataNode("IP", "blogs_1", "用户名", "密码")

              .UseDataNode("IP", "blogs_2", "用户名", "密码")

              .UseDataNode("IP", "blogs_3", "用户名", "密码");
    }
  }

  

  注意:

  .UseMyCat()中的 Server 是 MyCat 服务器的地址 Uid 和 Pwd 是 MyCat 的 用户名和密码,不要和数据的混了。 

  .UseDataNode()中的 Server 是节点数据库的地址 Uid 和 Pwd 是节点数据库的 用户名和密码。

  如何查看 MyCat 的用户名和密码:

    打开mycat目录下的 conf 目录(我们这里是:/usr/local/mycat/conf)

     查看 server.xml 文件:

    

    

  上面插入一段,一般使用mycat的应该都知道这些文件分别是干什么的,我们这里啰嗦一下。

  我把整个的 Program.cs 内容给大家展示一下:

  

  然后,就不多说了,你可以使用控制台命令 Add-Migration 和 Update-database 也可以使用命令 dotnet ef migrations add 和 dotnet ef database update 执行迁移和其它操作了。

  

  第二部分,我在项目中的应用:

  

  首先,在配置文件(siteconfig.json)中添加一个是否使用 MyCat 的配置:

  

  然后,同样在配置文件(siteconfig.json)中添加数据库节点配置:

  

  在 【(第十二章)】添加对SqlServer、MySql、Oracle的支持 中,我们有个数据库选择类 DataBaseProvider.cs

  

  这里面已经写了一个 _isUseMyCat 和 GetMyCatConnect(),是否使用 MyCat 这个 跟 数据库选择一样,我们从配置文件中读取这个配置返回即可:

  

  我们来重写一下 GetMyCatConnect 返回 MyCat 和 节点数据库连接的 DbContextOptionsBuilder:

  

  public DbContextOptionsBuilder GetMyCatConnect(string connectionStr, DbContextOptionsBuilder _options)
  {
    _options.UseMyCat(connectionStr);

    List<MyCatDatabaseHost> hosts = new Services.ConfigServices.AppConfigurtaionServices().GetListAppSettings<MyCatDatabaseHost>("MyCatDatabaseHost");

    foreach(var host in hosts)
    {
      _options.UseDataNode(host.Host, host.Database, host.Username, host.Password, host.Port);
    }

    return _options;
  }

  对于读取配置的方法,我们在 【(第十二章)】添加对SqlServer、MySql、Oracle的支持 中已经完整的贴出。

  修改一下 Startup.cs :

  

  

  这样,我们就实现了对 MyCat的支持和切换,当然,在实际项目中,我们可能不需要这些,使用什么,是否有必要使用 MyCat 这些可能是早就定好的,因为我这个是测试学习的项目,所以罗列了各种东西。

希望跟大家一起学习Asp.net Core

刚开始接触,水平有限,很多东西都是自己的理解和翻阅网上大神的资料,如果有不对的地方和不理解的地方,希望大家指正!

虽然Asp.net Core 现在很火热,但是网上的很多资料都是前篇一律的复制,所以有很多问题我也暂时没有解决,希望大家能共同帮助一下!

原创文章 转载请尊重劳动成果 http://yuangang.cnblogs.com

时间: 2024-10-23 21:01:54

net Core 使用MyCat分布式数据库,实现读写分离的相关文章

Mycat - 实现数据库的读写分离与高可用【转】

文章地址:https://www.cnblogs.com/youzhibing/p/9553766.html 前言 开心一刻 上语文课,不小心睡着了,坐在边上的同桌突然叫醒了我,并小声说道:“读课文第三段”.我立马起身大声读了起来.正在黑板写字的老师吓了一跳,老师郁闷的看着我,问道:“同学有什么问题吗?”,我貌似知道了什么,蛋定的说了一句:“这段写的真好!我给大伙念念!”,老师还较真了:“你说说看,好在哪里?”,顿时我就无语了,脸黑着望向了同桌了,心想着:“这是个畜生啊!” 路漫漫其修远兮,吾将

Mycat数据库中间件上手实践及分布式事务和读写分离实现

前言 现在微服务真是火得不行不行的, 最近开始找工作, 打开Boss直聘一看, 乖乖, 整页整页全是要求会整微服务的, 其中不乏很多小微企业, 搞得好像微服务就是万能的似的, 真不知道是中了谁的毒. 微服务肯定是个好东西, 优点很多, 百度一下一大把, 这里我们就不说了, 先讨论讨论微服务必然会带来几个问题. 通信问题, 微服务间是肯定需要通信的, 不能像以前一样调个方法搞定了. 分布式事务问题暨数据一致性问题, 微服务之间DB操作无法放在一个数据库事务中了. 维护问题, 微服务的维护难度必然是

MyCAT部署及实现读写分离(转)

MyCAT是mysql中间件,前身是阿里大名鼎鼎的Cobar,Cobar在开源了一段时间后,不了了之.于是MyCAT扛起了这面大旗,在大数据时代,其重要性愈发彰显.这篇文章主要是MyCAT的入门部署. 一.安装java 因Mycat是用java开发的,所以需要在实验环境下安装java,官方建议jdk1.7及以上版本 Java Oracle官方下载地址为: http://www.oracle.com/technetwork/java/javase/archive-139210.html 解压jdk

基于 EntityFramework 的数据库主从读写分离服务插件

基于 EntityFramework 的数据库主从读写分离服务插件 1.       版本信息和源码 1.1 版本信息 v1.0 beta(2015-04-02),基于 EF 6.1 开发,支持 EF 6.1 之后的所有 EF6 版本. 1.2 开放源码地址 https://github.com/cjw0511/NDF.Infrastructure 关于该 EF 数据库主从读写分离服务核心源码位于文件夹: src\ NDF.Data.EntityFramework\MasterSlaves 文件

MyCAT实现MySQL的读写分离

在MySQL中间件出现之前,对于MySQL主从集群,如果要实现其读写分离,一般是在程序端实现,这样就带来一个问题,即数据库和程序的耦合度太高,如果我数据库的地址发生改变了,那么我程序端也要进行相应的修改,如果数据库不小心挂掉了,则同时也意味着程序的不可用,而这对很多应用来说,并不能接受. 引入MySQL中间件能很好的对程序端和数据库进行解耦,这样,程序端只需关注数据库中间件的地址,而无需知晓底层数据库是如何提供服务. 作为当前炙手可热的MySQL中间件,MyCAT实现MySQL主从集群的读写分离

mycat基本概念及读写分离一

mycat基本概念及读写分离一 目录(?)[+] 安装与启动 mycat目录介绍 mycat三个最重要配置文件 验证读写分离 安装与启动 linux下可以下载Mycat-server-xxxxx.linux.tar.gz 解压在某个目录下,建议放在usr/local/mycat目录下,注意目录不能有空格.下载后改名,解压到/usr/server,工程名字mycat,配置环境变量,并使之生效: 1) vi /etc/profile,在系统环境变量文件中增加 [java] view plain co

linux下mysql基于mycat做主从复制和读写分离之基础篇

Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , mycat1.6-RELEASE jdk1.7及其以上版本2.实现步骤一(mycat实现读写分离) 1.首先在两台服务器安装mysql 1.下载mysql的repo源 $ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rp

通过mycat实现mysql的读写分离

mysql的主从配置沿用上一篇博客的配置:https://www.cnblogs.com/MasterSword/p/9434169.html mycat下载地址:http://www.mycat.io/ 试验版本:Mycat-server-1.6-release # cd /usr/local # mv ~/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz /usr/local # tar -zxvf Mycat-server-1.6-R

mycat做Mysql的读写分离

在MySQL中间件出现之前,对于MySQL主从集群,如果要实现其读写分离,一般是在程序端实现,这样就带来一个问题,即数据库和程序的耦合度太高,如果我数据库的地址发生改变了,那么我程序端也要进行相应的修改,如果数据库不小心挂掉了,则同时也意味着程序的不可用,而这对很多应用来说,并不能接受. 引入MySQL中间件能很好的对程序端和数据库进行解耦,这样,程序端只需关注数据库中间件的地址,而无需知晓底层数据库是如何提供服务. 作为当前炙手可热的MySQL中间件,MyCAT实现MySQL主从集群的读写分离