重磅来袭,使用CRL实现大数据分库分表方案
2015-09-21 10:57
781 查看
关于分库分表方案详细介绍
http://blog.csdn.net/bluishglc/article/details/7696085
这里就不作详细描述了,本方案拆分结构表示为
会员为业务核心,所有业务围绕会员来进行,所以垂直划分用会员编号作索引,将会员分配到不同的库
会员订单增长量是不固定的,所以需要平水拆分,和分库一样,一个表只存指定会员编号区间的订单
了解基本需求,就可以制作方案了,以下主索引表示主数据编号
库表结构配置
进行操作时,需要知道这个数据放在哪个库,哪个表,因此需要把这个划分结构做成可配置,需要配置有:
数据库:一共划分为几个库,主索引区间是多少
数据表:一共有几个分表,每个分表容量是多少
数据表分表:属于哪个表,主索引区间是多少
将结构以对象形式表示
DataBase 库
View
Code
Table 表
View
Code
TablePart 分表
View
Code
http://zhidao.baidu.com/question/362573981520597572.html
http://zhidao.baidu.com/question/178072669759268764.html http://zhidao.baidu.com/question/1542312678992888307.html http://zhidao.baidu.com/question/690520280714655524.html http://zhidao.baidu.com/question/1496595654085908219.html http://zhidao.baidu.com/question/136956581132048445.html http://zhidao.baidu.com/question/1692120461414474268.html http://zhidao.baidu.com/question/177944668296792444.html http://zhidao.baidu.com/question/1960737854840882860.html
数据定位
通过以上配置,就可以按主索引进行表定位了
过程表示为:初始库表配置=>按主索引定位库=>再定位到表
传入主索引编号,调用定位方法,得到对应的库和表名称
这样,库表位置就有了,剩下的就是对数据进行操作了,不过这需要数据访问框架能动态切换数据连接和映射对象,还好CRL能轻松实现
CRL内部调用比较复杂,这里不写具体实现了,只列出关键方法,详细实现可加入QQ群获取最新源代码
数据连接动态切换
因为CRL的数据访问是在应用层委托实现的,很容易实现,本次升级后增加了分库的区分
分表映射
在CRL内部实现了分表映射,如果传入了定位,则按定位找到分表名
以上过程表示为
整体封装
和之前CRL业务类封装一样,增加了CRL.Sharding.BaseProvider,继承实现业务对象,就能实现分库分表了
对比之前,此类删除了一些无关方法,增加了SetLocation定位方法
以文档带的例子讲解
会员实现
这里要注意主键的问题,不能为自增
订单实现
初始库表配置
以下会创建两个库 db1,db2
db1会员编号为1~10 ,db2会员编号为 11~20 ,当插入会员编号小于11的数据,则会定位到db1,11到20则会定位到db2
订单表OrderSharding设定为最大主数据容量5,1~5编号的会员订单会放在OrderSharding,6~10则会放到OrderSharding_1
插入会员和订单测试
插入的会员和订单会按库表配置分配到不同的表
这里为了演示,将定位信息保存了
数据查询
通过主索引编号定位库表,就能跟正常查询一样操作了
结果演示如下
分表联合查询
查询当前库所有分表订单union结果
设定union方式后,会遍历分表生成union查询
主索引的问题
以上演示主索引编号为手动输入,实际业务是需要从索引表产生,CRL.Sharding也增加了索引获取
分表结构创建
分表创建貌似比较麻烦,需要手动创建维护,然而不需要,CRL自动帮你创建了,这就是CRL强大之所在,在找不到表结构时,会按对象结构创建
分库分表难点
库表配置比较容易实现,比较麻烦的地方是从统一入口进行数据操作管理,要达到通用性,框架需要适应不同业务需求,封装和继承需要得到很好的支持
本方案已封装在CRL2.4,在文档示例中也有体现
演示地址:http://crl.changqidongli.com/page/Sharding.aspx
CRL最新版2.4代码在QQ群可以得到,有其它想法欢迎讨论,CRL3.0征集思路中,想共同开发的可与我联系
QQ群:1582632 密语:CRL
CRL框架介绍和早期源码:http://www.cnblogs.com/hubro/p/4616570.html
http://blog.csdn.net/bluishglc/article/details/7696085
这里就不作详细描述了,本方案拆分结构表示为
会员为业务核心,所有业务围绕会员来进行,所以垂直划分用会员编号作索引,将会员分配到不同的库
会员订单增长量是不固定的,所以需要平水拆分,和分库一样,一个表只存指定会员编号区间的订单
了解基本需求,就可以制作方案了,以下主索引表示主数据编号
库表结构配置
进行操作时,需要知道这个数据放在哪个库,哪个表,因此需要把这个划分结构做成可配置,需要配置有:
数据库:一共划分为几个库,主索引区间是多少
数据表:一共有几个分表,每个分表容量是多少
数据表分表:属于哪个表,主索引区间是多少
将结构以对象形式表示
DataBase 库
View
Code
Table 表
View
Code
TablePart 分表
View
Code
http://zhidao.baidu.com/question/362573981520597572.html
http://zhidao.baidu.com/question/178072669759268764.html http://zhidao.baidu.com/question/1542312678992888307.html http://zhidao.baidu.com/question/690520280714655524.html http://zhidao.baidu.com/question/1496595654085908219.html http://zhidao.baidu.com/question/136956581132048445.html http://zhidao.baidu.com/question/1692120461414474268.html http://zhidao.baidu.com/question/177944668296792444.html http://zhidao.baidu.com/question/1960737854840882860.html
数据定位
通过以上配置,就可以按主索引进行表定位了
过程表示为:初始库表配置=>按主索引定位库=>再定位到表
/// <summary> /// 初始表 /// </summary> public static void Init() { _DataBase = DataBaseManage.Instance.QueryList(); _Table = TableManage.Instance.QueryList(); _TablePart = TablePartManage.Instance.QueryList(); } /// <summary> /// 按主数据索引,确定库 /// </summary> 4000 /// <param name="mainDataIndex"></param> /// <returns></returns> public static DataBase GetDataBase(int mainDataIndex) { if (_DataBase.Count() == 0) { Init(); } var db = _DataBase.Find(b => mainDataIndex >= b.MainDataStartIndex && mainDataIndex <= b.MainDataEndIndex); if (db == null)//找属于哪个库 { throw new Exception("找不到指定的库,在主数据索引:" + mainDataIndex); } return db; } /// <summary> /// 按主数据索引,获取该查询位置 /// </summary> /// <param name="tableName"></param> /// <param name="mainDataIndex"></param> /// <param name="db"></param> /// <returns></returns> public static Location GetLocation(string tableName, int mainDataIndex, DataBase db) { var table = _Table.Find(b => b.TableName == tableName && b.DataBaseName == db.Name); if (table == null)//找哪个表 { throw new Exception(string.Format("找不到指定的表{1}在库{0}", db.Name, tableName)); } TablePart part; //找分表 if (table.IsMainTable)//如果只是主数据表,只按一个找就行了 { part = _TablePart.Find(b => b.TableName == tableName && b.DataBaseName == db.Name); } else//其它表,按分表找 { part = _TablePart.Find(b => mainDataIndex >= b.MainDataStartIndex && mainDataIndex <= b.MainDataEndIndex && b.TableName == tableName && b.DataBaseName == db.Name); } if (part == null) { throw new Exception(string.Format("找不到指定的表{1}在库{0}", db.Name, tableName)); } return new Location() { DataBase = db, TablePart = part }; }
传入主索引编号,调用定位方法,得到对应的库和表名称
var db=GetDataBase(100);//定位库 var location=GetLocation("Order", 100, db);//定位表
这样,库表位置就有了,剩下的就是对数据进行操作了,不过这需要数据访问框架能动态切换数据连接和映射对象,还好CRL能轻松实现
CRL内部调用比较复杂,这里不写具体实现了,只列出关键方法,详细实现可加入QQ群获取最新源代码
数据连接动态切换
因为CRL的数据访问是在应用层委托实现的,很容易实现,本次升级后增加了分库的区分
//配置数据连接 CRL.SettingConfig.GetDbAccess = (type) => { //可按type区分数据库 if (type.ShardingDataBase != null) { if (type.ShardingDataBase.Name == "db1")//定位到DB1 { return WebTest.Code.LocalSqlHelper.TestConnection; } else { return WebTest.Code.LocalSqlHelper.TestConnection2;//定位到DB2 } } else { return WebTest.Code.LocalSqlHelper.TestConnection;//默认库 } };
分表映射
在CRL内部实现了分表映射,如果传入了定位,则按定位找到分表名
public static string GetTableName(string tableName, DbContext dbContext) { if (dbContext != null && dbContext.UseSharding) { if (dbContext.ShardingMainDataIndex == 0) { throw new Exception("未设置分表定位索引,dbContext.ShardingMainDataIndex"); } var location = Sharding.DBService.GetLocation(tableName, dbContext.ShardingMainDataIndex, dbContext.DBLocation.ShardingDataBase); tableName = location.TablePart.PartName; } return tableName; }
以上过程表示为
整体封装
和之前CRL业务类封装一样,增加了CRL.Sharding.BaseProvider,继承实现业务对象,就能实现分库分表了
对比之前,此类删除了一些无关方法,增加了SetLocation定位方法
以文档带的例子讲解
会员实现
这里要注意主键的问题,不能为自增
public class MemberSharding : CRL.IModel { [CRL.Attribute.Field(KeepIdentity=true)]//保持插入主键 public int Id { get; set; } public string Name { get; set; } } public class MemberManage : CRL.Sharding.BaseProvider<MemberSharding> { public static MemberManage Instance { get { return new MemberManage(); } } }
订单实现
public class OrderSharding : CRL.IModelBase { public int MemberId { get; set; } public string Remark { get; set; } } public class OrderManage : CRL.Sharding.BaseProvider<OrderSharding> { public static OrderManage Instance { get { return new OrderManage(); } } }
初始库表配置
以下会创建两个库 db1,db2
db1会员编号为1~10 ,db2会员编号为 11~20 ,当插入会员编号小于11的数据,则会定位到db1,11到20则会定位到db2
订单表OrderSharding设定为最大主数据容量5,1~5编号的会员订单会放在OrderSharding,6~10则会放到OrderSharding_1
CRL.Sharding.DB.DataBaseManage.Instance.CleanData(); //创建库分组 var db = new CRL.Sharding.DB.DataBase(); db.Name = "db1"; db.MaxMainDataTotal = 10; CRL.Sharding.DB.DataBaseManage.Instance.Create(db); CRL.Sharding.DB.DataBaseManage.Instance.Create(db); //创建表 var dbList = CRL.Sharding.DB.DataBaseManage.Instance.QueryList(); foreach(var item in dbList) { var table = new CRL.Sharding.DB.Table(); table.TableName = "MemberSharding"; table.IsMainTable = true; CRL.Sharding.DB.TableManage.Instance.Create(item, table, out error); var table2 = new CRL.Sharding.DB.Table(); table2.TableName = "OrderSharding"; table2.IsMainTable = false; table2.MaxPartDataTotal = 5; CRL.Sharding.DB.TableManage.Instance.Create(item, table2, out error); //创建分区 CRL.Sharding.DB.TablePartManage.Instance.Create(table2, out error); }
插入会员和订单测试
插入的会员和订单会按库表配置分配到不同的表
这里为了演示,将定位信息保存了
var m = new Code.Sharding.MemberSharding(); m.Id = Convert.ToInt32(TextBox1.Text);//主索引编号 var location = CRL.Sharding.DBService.GetLocation("MemberSharding", m.Id); m.Name = location.ToString(); Code.Sharding.MemberManage.Instance.SetLocation(m.Id).Add(m); var order = new Code.Sharding.OrderSharding(); order.MemberId = m.Id; var location2 = CRL.Sharding.DBService.GetLocation("OrderSharding", m.Id); order.Remark = location2.ToString(); Code.Sharding.OrderManage.Instance.SetLocation(m.Id).Add(order); Label1.Text = "插入会员编号" + m.Id + "," + location + " 订单" + location2;
数据查询
通过主索引编号定位库表,就能跟正常查询一样操作了
//会员查询 var id = Convert.ToInt32(TextBox1.Text);//主索引编号 var list = Code.Sharding.OrderManage.Instance.SetLocation(id).QueryList(b => b.MemberId == id); GridView1.DataSource = list; GridView1.DataBind(); //订单查询 var id = Convert.ToInt32(TextBox1.Text);//主索引编号 var list = Code.Sharding.MemberManage.Instance.SetLocation(id).QueryList(b => b.Id == id); GridView1.DataSource = list; GridView1.DataBind();
结果演示如下
分表联合查询
查询当前库所有分表订单union结果
设定union方式后,会遍历分表生成union查询
var id = Convert.ToInt32(TextBox1.Text); var orderManage = Code.Sharding.OrderManage.Instance.SetLocation(id); var query = orderManage.GetLambdaQuery(); query.UnionType = UnionType.UnionAll;//只需设定union方式即可 var list = orderManage.QueryList(query); GridView1.DataSource = list; GridView1.DataBind();
主索引的问题
以上演示主索引编号为手动输入,实际业务是需要从索引表产生,CRL.Sharding也增加了索引获取
CRL.Sharding.DB.DataSequenceManage.Instance.GetSequence();
分表结构创建
分表创建貌似比较麻烦,需要手动创建维护,然而不需要,CRL自动帮你创建了,这就是CRL强大之所在,在找不到表结构时,会按对象结构创建
分库分表难点
库表配置比较容易实现,比较麻烦的地方是从统一入口进行数据操作管理,要达到通用性,框架需要适应不同业务需求,封装和继承需要得到很好的支持
本方案已封装在CRL2.4,在文档示例中也有体现
演示地址:http://crl.changqidongli.com/page/Sharding.aspx
CRL最新版2.4代码在QQ群可以得到,有其它想法欢迎讨论,CRL3.0征集思路中,想共同开发的可与我联系
QQ群:1582632 密语:CRL
CRL框架介绍和早期源码:http://www.cnblogs.com/hubro/p/4616570.html
相关文章推荐
- EAintroPage的使用
- 一文了解大数据领域创业的机会与方向
- 大数据笔记11:MapReduce的运行流程
- rails 时间格式化
- 重磅来袭,使用CRL实现大数据分库分表方案
- Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 数据库 'BHIoTV1.1' 的事务日志已满。若要查明无法重用日志中的空间的原
- 人类是否能够接受人工智能(AI)的存在?
- does not contain bitcode
- 第33本:《删除:大数据取舍之道》
- 第33本:《删除:大数据取舍之道》
- Xcode 添加 SVN 出现 nsurlerrordomain error 1012
- 第29本:《大数据时代》
- 第29本:《大数据时代》
- mail 发邮件
- 大数据学习篇:hadoop深入浅出系列之HDFS(一)——HDFS简介和优缺点
- 地址待验证----原创 【系统篇】PC 黑苹果破解版OS X Mountain Lion 10.8.X 系统大集合
- Sendmail+dovecot+saslauth+rainloop
- LeetCode Container With Most Water
- 云计算基本概念
- AIX nohup 不输出日志