MYCAT 配置(转)

 server.xml配置

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
<system>
<property name="defaultSqlParser">druidparser</property>
<property name="useCompression">1</property>
<property name="processorBufferPool">204800000</property> #BufferPool的大小
<property name="processorBufferChunk">40960</property> #每一个Buffer块的大小,processorBufferPool/processorBufferChun可以得到buffer块的数量
<property name="maxStringLiteralLength">65535</property>
<property name="sequnceHandlerType">0</property>
<property name="backSocketNoDelay">1</property>
<property name="frontSocketNoDelay">1</property>
<property name="mutiNodeLimitType">1</property>
<property name="mutiNodePatchSize">100</property>
<property name="processors">32</property> #可用线程数,实际上由于现在的多核CPU和超线程技术 酌情调高4-8倍
<property name="processorExecutor">32</property> #线程池是用来做异步处理逻辑的时候用的,对并发能力的影响相对较小
<property name="serverPort">3306</property> #定义访问端口
<property name="managerPort">9066</property> #定义管理端口
<property name="idleTimeout">300000</property> #超时时间
<property name="bindIp">0.0.0.0</property> #安全绑定IP
<property name="frontWriteQueueSize">4096</property>
<property name="processors">32</property>
</system>
<user name="root"> #访问账号
<property name="password">123456</property> #访问密码
<property name="schemas">chshop</property> #库文件名
</user>
<user name="root_read">                                   #只读账号
<property name="password">654321</property>
<property name="schemas">chshop</property>
<property name="readOnly">true</property> #只读模式
</user>

 <quarantine>
<whitehost>
<host host="127.0.0.1" user="root"></host> #白名单
<host host="172.16.1.45" user="root"></host> #白名单允许那些IP能通过root访问
</whitehost>
 <blacklist check="false"></blacklist>                   #黑名单
</quarantine>
</mycat:server>

server调整总结:
processors+processorExecutor会影响到MyCAT可用的线程数,虽然调高点会比较好,但是调的太高会导致频繁的上下文切换和软中断,在实际调整中,用top观察sys和si的百分比,如果服务器/虚拟机并没有什么不干净的后台程序和其他的服务在运行,sys在10%-15%之内,si在5%之内是比较理想的状态
processorBufferPool+processorBufferChunk影响的server缓存,保持processorBufferChunk大小合理的情况下,增加buffer块的数量才是关键

cacheservice配置-是SQL的缓存服务

#used for mycat cache service conf
factory.encache=org.opencloudb.cache.impl.EnchachePooFactory
#key is pool name ,value is type,max size, expire seconds
pool.SQLRouteCache=encache,10000,1800 #sql路由缓存,通过缓存SQL语句的路由信息,下次查询,不用再路由了,直接从缓存中获取路由信息,然后发到各个节点执行;
pool.ER_SQL2PARENTID=encache,1000,1800 #ER关系的缓存目前只是在Insert语句中才使用缓存,子表插入数据的时候根据joinKey值,判断父表所在分片,从而定位子表分片,分片信息put缓存layedpool.TableID2DataNodeCache=encache,10000,18000#表主键ID的路由缓存,为每一个表建一个缓存池,命名为TableID2DataNodeCache.TESTDB_表名,缓存key是id的值,value是节点名
layedpool.TableID2DataNodeCache.TESTDB_ORDERS=50000,18000

Cacheservice调整总结

SQLRouteCache的大小对具体的QPS有比较大的影响 参考: pool.SQLRouteCache=encache,1500000,60

rule.xml 配置

hash-int---在这一条切分规则的下面,有一个mapfile,这代表着,这个切分规则是根据partition-hash-int的内容来决定的,那么看一下这个文本文件
         MYCAT 配置(转)
            很简单的内容,这代表着切分使用的基准列里面,值为10000的时候,放在第一个DN里面(dn1),值为10010的时候,放在第二个DN里面(dn2) 可以看一下实际效果
         MYCAT 配置(转)
         MYCAT 配置(转)
            看一下MyCAT的Debug日志,这两条语句被分配到了dn1和dn2上面,数据库里面也插入了相对应的数据
         MYCAT 配置(转)
            那么~问题来了(挖掘机滚粗~),如果插入的数据中,基准列的取值不是这个文件里面写明的值,会是什么效果?
         MYCAT 配置(转)
            直截了当的报错了~
            好了,hash-int的这种切分规则,大体上可以理解为枚举分区,会比较适合于取值固定的场合,比如说性别(0,1),省份(固定值,短时间不会收复日本省吧~),渠道商 or 各种平台的ID
            而且,用逗号分隔可以把多个值放在一个分区里面,所以可以根据实际的数据量/流量/访问量来综合制定切分策略;
            缺点:毕竟不是全能战士

range-long ----仔细一看的话,和hash-int是比较像的,也是由特定的文件来决定切分策略,所以还是去看一下文件的内容
         MYCAT 配置(转)
            从文件内容可以看出,这是一种范围切分的方式,制定基准列的取值范围,然后把这一范围的所有数据都放到一个DN上面,这种方式和hash-int基本一致,就不截图了(懒癌晚期,时间不够了!)
            这种切分策略,个人感觉在业务数据库里面的使用场景会少一些,因为这种切分方式需要预定好整体的数量,这就决定了那种无限增长的数据不能用这个,毕竟要改动这个切分策略会很麻烦
            真要用起来,感觉也就对自增主键用,然后按照一定的数量来均匀切分,比如那种一天固定X条数据的业务(温度采集?数据采集?之类的情况),然后提前建好多个DN(库)。
            当然,也存在一种潜在的问题,如果在短时间发生海量的顺序插入操作,而每一个DN(分库)设定的数量比较高(比如说一个DN设定的放1000W条数据),那么在这个时候,会出现某一个DN(分库)IO压力非常高,而其他几个DN(分库)完全没有IO操作,就会出现类似于DB中常见的热块/热盘的现象,而MySQL经常用自增主键,所以使得MySQL的表出现大量“顺序”插入的机会会多很多。

mod-long--从mod来看这应该是一种取余数的方法,来看一下具体配置的信息
         MYCAT 配置(转)
            count=4,这是代表着总共把数据切分成四份,一般是和具体的DN数量对应,从而达到把数据均匀的分布在四个DN上(当然,count<dn数量也没什么问题)   看一下实际的效果
         MYCAT 配置(转)
            看一下MyCAT的Debug日志,看看MyCAT是如何处理的
         MYCAT 配置(转)
            采用这种取余数的方式时,这四条数据分别插入了四个DN(库),而且可以看到,顺序插入时,数据是被均匀的分散在多个DN(库)上面
            相比较于上面的range的方法,这种切分策略会更好的分散数据库写的压力,但是问题也很明显,一旦出现了范围查询,就需要MyCAT去合并结果,当数据量偏高的时候,这种跨库查询+合并结果消耗的时间有可能会增加很多,尤其是还出现了order by的时候。
            所以这种切分策略会比较适合于单点查询的情景,比如说.....我也不知道......真的不知道,也许在银行,查询个人账户信息的时候,一些和用户信息的表可以做好冗余,然后利用这种方式来提供更为高效的查询(毕竟银行的用户数量多,恩恩~)

partition-by-long---处于range-long和mod-long之间的一个略微折中的划分策略,具体切分形势依照如下描述:
            以1024为一个单位,每个DN存放partitionLength数量的数据,且,partitionCount x partitionLength=1024
            看起来有点难以理解,形象点描述的话,以partitionCount(4) x partitionLength(256)为例,sid%1024=0-255的放在DN1,256-511的放在DN2,以此类推
            试着以128为偏移值插入了八条数据,直接看MyCAT的日志
         MYCAT 配置(转)
            可以看到,八条数据均匀的分布在这四个DN里面~
            值得一提的是,这种切分策略也支持非均匀分布~实在是测不动了,盗图两张~
          MYCAT 配置(转)          MYCAT 配置(转)
            这两张图基本上也说明白了这种非均匀分布的划分策略,重点还是在2x256+1x512=1024上面~
            这种划分策略在range-long和mod-long之间取了一个折中点,同时,也还算是比较灵活,可以根据不同的情况进行非均匀划分,实际上能应用的场景会稍微多一点吧,或者说,不少场景都能用一用,相对减少了跨DN的情形,又把数据比较均匀的切分开来了,单点查询也不会太慢。

可以说,MyCAT的分库分表的重点,基本全部在这个rule里面体现了,表要不要分,表的数据怎么切分,都是需要根据实际业务来决定,充分根据业务的特点去决定最合适的划分策略

------------------------------------------------------------------------------------------

schema.xml 配置

  1. <?xml version=\"1.0\"?>
  2. <!DOCTYPE mycat:schema SYSTEM \"schema.dtd\">
  3. <mycat:schema xmlns:mycat=\"http://org.opencloudb/\">
  4. <schema name=\"mycat\" checkSQLschema=\"false\" sqlMaxLimit=\"100\">
  5. <!-- auto sharding by id (long) -->
  6. <table name=\"students\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule1\" />
  7. <table name=\"log_test\" dataNode=\"dn1,dn2,dn3,dn4\" rule=\"rule2\" />
  8. <!-- global table is auto cloned to all defined data nodes ,so can join
  9. with any table whose sharding node is in the same data node -->
  10. <!--<table name=\"company\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3\" />
  11. <table name=\"goods\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2\" />
  12. -->
  13. <table name=\"item_test\" primaryKey=\"ID\" type=\"global\" dataNode=\"dn1,dn2,dn3,dn4\" />
  14. <!-- random sharding using mod sharind rule -->
  15. <!-- <table name=\"hotnews\" primaryKey=\"ID\" dataNode=\"dn1,dn2,dn3\"
  16. rule=\"mod-long\" /> -->
  17. <!--
  18. <table name=\"worker\" primaryKey=\"ID\" dataNode=\"jdbc_dn1,jdbc_dn2,jdbc_dn3\" rule=\"mod-long\" />
  19. -->
  20. <!-- <table name=\"employee\" primaryKey=\"ID\" dataNode=\"dn1,dn2\"
  21. rule=\"sharding-by-intfile\" />
  22. <table name=\"customer\" primaryKey=\"ID\" dataNode=\"dn1,dn2\"
  23. rule=\"sharding-by-intfile\">
  24. <childTable name=\"orders\" primaryKey=\"ID\" joinKey=\"customer_id\"
  25. parentKey=\"id\">
  26. <childTable name=\"order_items\" joinKey=\"order_id\"
  27. parentKey=\"id\" />
  28. <ildTable>
  29. <childTable name=\"customer_addr\" primaryKey=\"ID\" joinKey=\"customer_id\"
  30. parentKey=\"id\" /> -->
  31. </schema>
  32. <!-- <dataNode name=\"dn\" dataHost=\"localhost\" database=\"test\" /> -->
  33. <dataNode name=\"dn1\" dataHost=\"localhost\" database=\"test1\" />
  34. <dataNode name=\"dn2\" dataHost=\"localhost\" database=\"test2\" />
  35. <dataNode name=\"dn3\" dataHost=\"localhost\" database=\"test3\" />
  36. <dataNode name=\"dn4\" dataHost=\"localhost\" database=\"test4\" />
  37. <!--
  38. <dataNode name=\"jdbc_dn1\" dataHost=\"jdbchost\" database=\"db1\" />
  39. <dataNode name=\"jdbc_dn2\" dataHost=\"jdbchost\" database=\"db2\" />
  40. <dataNode name=\"jdbc_dn3\" dataHost=\"jdbchost\" database=\"db3\" />
  41. -->
  42. <dataHost name=\"localhost\" maxCon=\"100\" minCon=\"10\" balance=\"1\"
  43. writeType=\"1\" dbType=\"mysql\" dbDriver=\"native\">
  44. <heartbeat>select user()<beat>
  45. <!-- can have multi write hosts -->
  46. <writeHost host=\"localhost\" url=\"localhost:3306\" user=\"root\" password=\"wangwenan\">
  47. <!-- can have multi read hosts -->
  48. <readHost host=\"hostS1\" url=\"localhost:3307\" user=\"root\" password=\"wangwenan\"/>
  49. </writeHost>
  50. <writeHost host=\"localhost1\" url=\"localhost:3308\" user=\"root\" password=\"wangwenan\">
  51. <!-- can have multi read hosts -->
  52. <readHost host=\"hostS11\" url=\"localhost:3309\" user=\"root\" password=\"wangwenan\"/>
  53. </writeHost>
  54. </dataHost>
  55. <!-- <writeHost host=\"hostM2\" url=\"localhost:3316\" user=\"root\" password=\"123456\"/> -->
  56. <!--
  57. <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"1\" balance=\"0\" writeType=\"0\" dbType=\"mongodb\" dbDriver=\"jdbc\">
  58. <heartbeat>select user()<beat>
  59. <writeHost host=\"hostM\" url=\"mongodb://192.168.0.99/test\" user=\"admin\" password=\"123456\" ></writeHost>
  60. </dataHost>
  61. -->
  62. <!--
  63. <dataHost name=\"jdbchost\" maxCon=\"1000\" minCon=\"10\" balance=\"0\"
  64. dbType=\"mysql\" dbDriver=\"jdbc\">
  65. <heartbeat>select user()<beat>
  66. <writeHost host=\"hostM1\" url=\"jdbc:mysql://localhost:3306\"
  67. user=\"root\" password=\"123456\">
  68. </writeHost>
  69. </dataHost>
  70. -->
  71. </mycat:schema>

        第一行参数<schema name="mycat" checkSQLschema="false" sqlMaxLimit="100"/>
                在这一行参数里面,schema name定义了可以在MyCAT前端显示的逻辑数据库的名字,
                checkSQLschema这个参数为False的时候,表明MyCAT会自动忽略掉表名前的数据库名,比如说mydatabase1.test1,会被当做test1;
                sqlMaxLimit指定了SQL语句返回的行数限制;
                     MYCAT 配置(转)

MYCAT 配置(转)
                       
                如截图,这个limit会让MyCAT在分发SQL语句的时候,自动加上一个limit,限制从分库获得的结果的行数,另外,截图右上角可以看到,MyCAT本身也是有缓存的;
                那么,如果我们执行的语句要返回较多的数据行,在不修改这个limit的情况下,MyCAT会怎么做?
                      MYCAT 配置(转)
                可以从截图看到,MyCAT完全就没搭理前端的实际需求,老老实实返回100条数据,所以如果实际应用里面需要返回大量数据,可能就得手动改逻辑了
                MyCAT的1.4版本里面,用户的Limit参数会覆盖掉默认的MyCAT设置 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

<table name="students" dataNode="dn1,dn2,dn3,dn4" rule="rule1" />
                这一行代表在MyCAT前端会显示哪些表名,类似几行都代表一样的意思,这里强调的是表,而MyCAT并不会在配置文件里面定义表结构
                    如果在前端使用show create table ,MyCAT会显示正常的表结构信息,观察Debug日志,
                      MYCAT 配置(转)
                可以看到,MyCAT把命令分发给了dn1代表的数据库,然后把dn1的查询结果返回给了前端
                可以判断,类似的数据库级别的一些查询指令,有可能是单独分发给某个节点,然后再把某个节点的信息返回给前端;
               
                dataNode的意义很简单,这个逻辑表的数据存储在后端的哪几个数据库里面                
                rule代表的是这个逻辑表students的具体切分策略,目前MyCAT只支持按照某一个特殊列,遵循一些特殊的规则来切分,如取模,枚举等,具体的留给之后细说

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                
                <table name="item_test" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3,dn4" />
                这一行代表的是全局表,这意味着,item_test这张表会在四个dataNode里面都保存有完整的数据副本,那么查询的时候还会分发到所有的数据库么?
                      MYCAT 配置(转)
                结果如截图,MyCAT依然是规规矩矩的返回了100条数据(╮(╯_╰)╭),而针对全局表的查询,只会分发到某一个节点上
                配置的primaryKey没发现作用在哪里,姑且忽略吧,以后发现了再补上

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

childtable我在测试中并没有实际用起来不过在MyCAT的设计文档里面有提到,childtable是一种依赖于父表的结构,
                这意味着,childtable的joinkey会按照父表的parentKey的策略一起切分,当父表与子表进行连接,且连接条件是childtable.joinKey=parenttable.parentKey时,不会进行跨库的连接.
                PS:具体测试以后再补

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

dataNode的参数在之前的篇章介绍过,这里直接跳过~

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

dataHost配置的是实际的后端数据库集群,大部分参数简单易懂,这里就不一个个介绍了,只介绍比较重要的两个参数,writeType和balance.
                writeType和balance是用来控制后端集群的读写分离的关键参数,这里我用了双主双从的集群配置
                这里的测试过程比较麻烦,所以直接贴结论:
                        1.balance=0时,读操作都在localhost上(localhost失败时,后端直接失败)
                        2.balance=1时,读操作会随机分散在localhost1和两个readhost上面(localhost失败时,写操作会在localhost1,如果localhost1再失败,则无法进行写操作)
                        3.balance=2时,写操作会在localhost上,读操作会随机分散在localhost1,localhost1和两个readhost上面(同上)
                        4.writeType=0时,写操作会在localhost上,如果localhost失败,会自动切换到localhost1,localhost恢复以后并不会切换回localhost进行写操作
                        5.writeType=1时,写操作会随机分布在localhost和localhost1上,单点失败并不会影响集群的写操作,但是后端的从库会无法从挂掉的主库获取更新,会在读数据的时候出现数据不一致
                                举例:localhost失败了,写操作会在localhost1上面进行,localhost1的主从正常运行,但是localhost的从库无法从localhost获取更新,localhost的从库于其他库出现数据不一致

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

实际上,MyCAT本身的读写分离是基于后端集群的同步来实现的,而MyCAT本身则提供语句的分发功能,当然,那个sqlLimit的限制也使得MyCAT会对前端应用层的逻辑造成一些影响
                由schema到table的配置,则显示出MyCAT本身的逻辑结构里面,就包含了分库分表的这种特性(可以指定不同的表存在于不同的数据库中,而不必分到全部数据库)

上一篇:个性二维码开源专题<前背景>


下一篇:分布式系统理论进阶 - Raft、Zab