资讯专栏INFORMATION COLUMN

【操作教程】SequoiaDB分布式存储教程

tunny / 3304人阅读

摘要:而分布方式与分布方式最大的不同点,在于对数据的删除上。操作指南作者在为下面各种数据分布方式做操作前,需要先在数据库中一些准备操作。

1.各模式适用场景介绍

由于SequoiaDB对比其他的NoSQL有更多的方式将数据分布到多台服务器上,所以下面笔者为阅读者一一介绍每种分布式方式适合于哪种场景。

1.1Hash 方式分布数据
在Hash分布方式中,由于是对集合中某个字段的Hash值进行数据均匀,所以用户未来在使用Hash分布时,ShardingKey 一定要选择集合中字段值比较随机,并且Hash值比较均匀的字段,这样才能够保证集合中的数据被均匀的分布在各个数据分区组上。

Hash分布式方式主要适合数据量比较大,并且集合中包含一个Hash值比较随机的字段。如果集合中并没有Hash值比较随机的字段,但是集合的数据量又非常的巨大,用户可以考虑使用SequoiaDB中的主键-“_id”作为ShardingKey。

1.2Range 方式分布数据
Range 分布方式,主要适用用于集合数据量大,并且集合包含某个具有比较明确的数值范围的字段,例如时间字段或者是业务类型字段,来帮助用户做集合的范围切分。

1.3Partition 方式分布数据
Partition 分布方式,和Range 分布方式的适用场景非常类似,都是要求集合数据量大,并且集合包含某个具有比较明确的数值范围的字段。

Partition分布方式,实际上并不能够做到数据自动均匀分布到多个数据分区组,而是需要用户在建立子表时,人工显式指定此子表是被分配到哪个数据分区组上,然后再通过主表的attach 命令将子表按照某个字段的范围值挂载到主表上。

而Partition 分布方式与Range 分布方式最大的不同点,在于对数据的删除上。

在Range 分布方式中,如果用户需要对集合中某个过旧的时间范围数据进行删除,用户需要调用remove 命令,真实地从数据库磁盘中删除这部分数据,这个耗时会比较久。

而在Partition 分布方式中,用户同样希望删除某个过旧的时间范围数据,用户只需要调用dettach命令,将符合时间范围的子表从主表中卸载下来,即可完成数据从集合中清除的目的,dettach命令的效率非常高,基本是秒级完成。然后用户可以对过旧的子表执行truncate 命令,回收磁盘空间。

注意,集合truncate 命令的执行效率比集合remove 命令的执行效率要高出几个量级。

1.4多维分区
SequoiaDB的多维分区方式,它很好地结合了Hash分布方式和Partition 分布方式的优点,能够让集合中的数据以更小的颗粒度分布到数据库多个数据分区组上。

多维分区分布方式,主要适合的场景是集合数据量特别巨大,集合中同时包含两个关键的ShardingKey,一般为time和id两个字段,time字段给主子表使用,id字段给Hash 分布使用,并且用户在使用在集合过程中,还可能会定期对部分数据进行空间回收。

在真实的客户环境中,多维分区主要使用的场景为:银行的历史数据流水表,业务系统历史日志表等。

2.操作指南

作者在为下面各种数据分布方式做操作前,需要先在数据库中一些准备操作。
连接到数据库中

var db = new Sdb("localhost", 11810); 

查看当前数据库有多少数据分区组

var cursor = db.listReplicaGroups();while (cursor.next()){var obj = cursor.current().toObj();if (obj["GroupName"] != "SYSCoord" && obj["GroupName"] != "SYSCatalogGroup") {println (obj["GroupName"]);}} cursor.close ();

返回的结果为

group1
group2
group3
group4

为了做Hash 切分方便,用户可以先给数据库建立Domain

db.createDomain ("domain1", ["group1", "group2"], {AutoSplit:true});
db.createDomain ("domain2", ["group3", "group4"], {AutoSplit:true});

2.1Hash 方式分布数据
建立一个集合空间,名为testcs_domain1,并且指定此集合空间是建立在domain1 上的
db.createCS("testcs_domain1", {Domain:"domain1"});
在testcs_domain1 集合空间上建立一个集合,名为testcl_hash,设置ShardingType = hash,ShardingKey = id

var CS = db.getCS("testcs_domain1");
CS.createCL("testcl_hash", {ShardingType:"hash", ShardingKey:{id:1}});

检查testcl_hash 集合在数据库中的分布情况

db.snapshot(8, {Name:"testcs_domain1.testcl_hash"});
{
  "AutoSplit": true,
  "CataInfo": [
    {
      "ID": 0,
      "GroupID": 1001,
      "GroupName": "group2",
      "LowBound": {
        "": 0
      },
      "UpBound": {
        "": 2048
      }
    },
    {
      "ID": 1,
      "GroupID": 1000,
      "GroupName": "group1",
      "LowBound": {
        "": 2048
      },
      "UpBound": {
        "": 4096
      }
    }
  ],
  "EnsureShardingIndex": true,
  "InternalV": 3,
  "Name": "testcs_domain1.testcl_hash",
  "Partition": 4096,
  "ShardingKey": {
    "id": 1
  },
  "ShardingType": "hash",
  "Version": 2,
  "_id": {
    "$oid": "57c73fe8ed44740501b46dee"
  }
}

用户可以从snapshot 的输出中看到,testcs_domain1.testcl_hash 被切分到group1 和group2 上,并且Hash桶是均匀分配的。

2.2Range 方式分布数据

用户在做Range 切分时,Domain 的功能就不能帮上忙了。为了让本文档的阅读者更加清晰地了解Range 切分,作者在数据库中新建一个集合空间,名为testcs_range

db.createCS("testcs_range");

建立一个名为testcl_range 的集合,ShardingKey = time, ShardingType = range,并且指定此集合在初始化时建立在group1 数据分区组上。

var CS = db.getCS("testcs_range");
CS.createCL("testcl_range", {ShardingType:"range", ShardingKey:{time:1}, Group:"group1"});

对testcl_range 做范围切分

CS.testcl_range.split ("group1", "group2", {time:"20160401"}, {time:"20160701"});
CS.testcl_range.split ("group1", "group3", {time:"20160701"}, {time:"20161001"});
CS.testcl_range.split ("group1", "group4", {time:"20161001"}, {time:"20170101"});

查看testcs_range.testcl_range 的切分情况

db.snapshot (8, {Name:"testcs_range.testcl_range"});
{
  "CataInfo": [
    {
      "ID": 0,
      "GroupID": 1000,
      "GroupName": "group1",
      "LowBound": {
        "time": {
          "$minKey": 1
        }
      },
      "UpBound": {
        "time": "20160401"
      }
    },
    {
      "ID": 1,
      "GroupID": 1001,
      "GroupName": "group2",
      "LowBound": {
        "time": "20160401"
      },
      "UpBound": {
        "time": "20160701"
      }
    },
    {
      "ID": 3,
      "GroupID": 1002,
      "GroupName": "group3",
      "LowBound": {
        "time": "20160701"
      },
      "UpBound": {
        "time": "20161001"
      }
    },
    {
      "ID": 4,
      "GroupID": 1003,
      "GroupName": "group4",
      "LowBound": {
        "time": "20161001"
      },
      "UpBound": {
        "time": "20170101"
      }
    },
    {
      "ID": 2,
      "GroupID": 1000,
      "GroupName": "group1",
      "LowBound": {
        "time": "20170101"
      },
      "UpBound": {
        "time": {
          "$maxKey": 1
        }
      }
    }
  ],
  "EnsureShardingIndex": true,
  "Name": "testcs_range.testcl_range",
  "ShardingKey": {
    "time": 1
  },
  "ShardingType": "range",
  "Version": 4,
  "_id": {
    "$oid": "57c754b6ed44740501b46e0e"
  }
}

testcs_range.testcl_range 集合数据切分情况如下
group2 负责 time 范围为 "20160401" ~ "20160701"
group3 负责 time 范围为 "20160701" ~ "20161001"
group4 负责 time 范围为 "20161001" ~ "20170101"
group1 负责 time 范围为除 group2、group3、group4 范围外的所有数据
用户可以写入两条记录去验证一下

CS.testcl_range.insert({name:"test", id:1, time:"20160425"});
CS.testcl_range.insert({name:"haha", id:2, time:"20160101"});

用户可以通过快照查看每个数据分区组的记录数

db.snapshot(4, {Name:"testcs_range.testcl_range"}, {"Details.Group.TotalRecords":null,"Details.GroupName":null});
{
  "Details": [
    {
      "GroupName": "group1",
      "Group": [
        {
          "TotalRecords": 1
        },
        {
          "TotalRecords": 1
        },
        {
          "TotalRecords": 1
        }
      ]
    },
    {
      "GroupName": "group2",
      "Group": [
        {
          "TotalRecords": 1
        },
        {
          "TotalRecords": 1
        },
        {
          "TotalRecords": 1
        }
      ]
    },
    {
      "GroupName": "group3",
      "Group": [
        {
          "TotalRecords": 0
        },
        {
          "TotalRecords": 0
        },
        {
          "TotalRecords": 0
        }
      ]
    },
    {
      "GroupName": "group4",
      "Group": [
        {
          "TotalRecords": 0
        },
        {
          "TotalRecords": 0
        },
        {
          "TotalRecords": 0
        }
      ]
    }
  ]
}

由于本集群是一个数据分区组,包含3个数据副本,所以在快照信息中,一个group 会显示3条记录。

并且用户从快照信息中,group1 包含1 条记录,group2 包含1 条记录,符合作者对testcs_range.testcl_range 的切分情况。

2.3Parttion 方式分布数据
为了验证使用主子表来做数据切分,作者在数据库中新建一个名为 testcs_mainsub 的集合空间

db.createCS("testcs_mainsub");
var CS = db.getCS("testcs_mainsub");

在 testcs_mainsub 集合空间上建立一个主表,ShardingType = range, ShardingKey = time, isMainCL = true

CS.createCL("testcl_main", {ShardingType:"range", ShardingKey:{time:1}, IsMainCL:true});

建立子表,并且在建立子表时,显式指定每个子表被分配到哪个数据分区组上。

CS.createCL("testcl_sub1", {Group:"group1"});
CS.createCL("testcl_sub2", {Group:"group2"});
CS.createCL("testcl_sub3", {Group:"group3"});
CS.createCL("testcl_sub4", {Group:"group4"});

将各个子表挂载到主表上

CS.testcl_main.attachCL ("testcs_mainsub.testcl_sub1", {LowBound:{time:"20160101"}, UpBound:{time:"20160401"}});
CS.testcl_main.attachCL ("testcs_mainsub.testcl_sub2", {LowBound:{time:"20160401"}, UpBound:{time:"20160701"}});
CS.testcl_main.attachCL ("testcs_mainsub.testcl_sub3", {LowBound:{time:"20160701"}, UpBound:{time:"20161001"}});
CS.testcl_main.attachCL ("testcs_mainsub.testcl_sub4", {LowBound:{time:"20161001"}, UpBound:{time:"20170101"}});

用户可以通过快照了解主表数据的切分情况

db.snapshot (8, {Name:"testcs_mainsub.testcl_main"});
{
  "CataInfo": [
    {
      "ID": 1,
      "SubCLName": "testcs_mainsub.testcl_sub1",
      "LowBound": {
        "time": "20160101"
      },
      "UpBound": {
        "time": "20160401"
      }
    },
    {
      "ID": 2,
      "SubCLName": "testcs_mainsub.testcl_sub2",
      "LowBound": {
        "time": "20160401"
      },
      "UpBound": {
        "time": "20160701"
      }
    },
    {
      "ID": 3,
      "SubCLName": "testcs_mainsub.testcl_sub3",
      "LowBound": {
        "time": "20160701"
      },
      "UpBound": {
        "time": "20161001"
      }
    },
    {
      "ID": 4,
      "SubCLName": "testcs_mainsub.testcl_sub4",
      "LowBound": {
        "time": "20161001"
      },
      "UpBound": {
        "time": "20170101"
      }
    }
  ],
  "EnsureShardingIndex": true,
  "IsMainCL": true,
  "Name": "testcs_mainsub.testcl_main",
  "ShardingKey": {
    "time": 1
  },
  "ShardingType": "range",
  "Version": 5,
  "_id": {
    "$oid": "57c75d35ed44740501b46e28"
  }
}

目前 testcs_mainsub.testcl_main 的数据切分情况如下
testcl_sub1 属于 group1,它负责的数据范围为 20160101 ~ 20160401
testcl_sub2 属于 group2,它负责的数据范围为 20160401 ~ 20160701
testcl_sub3 属于 group3,它负责的数据范围为 20160701 ~ 20161001
testcl_sub4 属于 group4,它负责的数据范围为 20161001 ~ 20170101

用户可以写入两条记录来验证一下数据的分布情况

CS.testcl_main.insert ({name:"test", id:1, time:"20160123"});
CS.testcl_main.insert ({name:"haha", id:2, time:"20161207"});

用户可以查看一下每个子表的数据情况

CS.testcl_sub1.count();
CS.testcl_sub2.count();
CS.testcl_sub3.count();
CS.testcl_sub4.count();


图6
数据分布情况符合主子表的切分范围。

2.4多维分区
为了验证SequoiaDB 的多维分区功能,并且为了给阅读者更好了解在多维分区和Domain功能的结合,作者在数据库中新建两个集合空间,分别为 testcs_doublepartition_domain1 和 testcs_doublepartition_domain2

db.createCS ("testcs_doublepartition_domain1", {Domain:"domain1"});
var CS1 = db.getCS ("testcs_doublepartition_domain1");
db.createCS ("testcs_doublepartition_domain2", {Domain:"domain2"});
var CS2 = db.getCS ("testcs_doublepartition_domain2");

刚才作者已经在数据库多维分区的技术原理也介绍了,SequoiaDB的多维分区,实际上就是在一个集合中,同时运用主子表和Hash分区两个数据分区功能,从而使得集合能够以更小的颗粒度做数据均衡。
在 testcs_mainsub 集合空间上建立一个主表,ShardingType = range, ShardingKey = time, isMainCL = true

var CS = db.getCS("testcs_mainsub");
CS.createCL("testcl_main_doublepartition", {ShardingType:"range", ShardingKey:{time:1}, IsMainCL:true});

建立子表,并且在建立子表时,注意选择集合空间,并且显式指定ShardingType = hash 和 ShardingKey = id。

CS1.createCL("testcl_sub1", {ShardingType:"hash", ShardingKey:{id:1}});
CS1.createCL("testcl_sub2", {ShardingType:"hash", ShardingKey:{id:1}});
CS2.createCL("testcl_sub3", {ShardingType:"hash", ShardingKey:{id:1}});
CS2.createCL("testcl_sub4", {ShardingType:"hash", ShardingKey:{id:1}});

将各个子表挂载到主表上

CS.testcl_main_doublepartition.attachCL ("testcs_doublepartition_domain1.testcl_sub1", {LowBound:{time:"20160101"}, UpBound:{time:"20160401"}});
CS.testcl_main_doublepartition.attachCL ("testcs_doublepartition_domain1.testcl_sub2", {LowBound:{time:"20160401"}, UpBound:{time:"20160701"}});
CS.testcl_main_doublepartition.attachCL ("testcs_doublepartition_domain2.testcl_sub3", {LowBound:{time:"20160701"}, UpBound:{time:"20161001"}});
CS.testcl_main_doublepartition.attachCL ("testcs_doublepartition_domain2.testcl_sub4", {LowBound:{time:"20161001"}, UpBound:{time:"20170101"}});

用户可以通过快照信息核对数据的切分情况

db.snapshot (8, {Name:"testcs_mainsub.testcl_main_doublepartition"});
{
  "CataInfo": [
    {
      "ID": 1,
      "SubCLName": "testcs_doublepartition_domain1.testcl_sub1",
      "LowBound": {
        "time": "20160101"
      },
      "UpBound": {
        "time": "20160401"
      }
    },
    {
      "ID": 2,
      "SubCLName": "testcs_doublepartition_domain1.testcl_sub2",
      "LowBound": {
        "time": "20160401"
      },
      "UpBound": {
        "time": "20160701"
      }
    },
    {
      "ID": 3,
      "SubCLName": "testcs_doublepartition_domain2.testcl_sub3",
      "LowBound": {
        "time": "20160701"
      },
      "UpBound": {
        "time": "20161001"
      }
    },
    {
      "ID": 4,
      "SubCLName": "testcs_doublepartition_domain2.testcl_sub4",
      "LowBound": {
        "time": "20161001"
      },
      "UpBound": {
        "time": "20170101"
      }
    }
  ],
  "EnsureShardingIndex": true,
  "IsMainCL": true,
  "Name": "testcs_mainsub.testcl_main_doublepartition",
  "ShardingKey": {
    "time": 1
  },
  "ShardingType": "range",
  "Version": 5,
  "_id": {
    "$oid": "57c80046ed44740501b46e43"
  }
}

testcs_doublepartition_domain1.testcl_sub1 属于 group1,它负责的数据范围为 20160101 ~ 20160401
testcs_doublepartition_domain1.testcl_sub2 属于 group2,它负责的数据范围为 20160401 ~ 20160701
testcs_doublepartition_domain2.testcl_sub3 属于 group3,它负责的数据范围为 20160701 ~ 20161001
testcs_doublepartition_domain2.testcl_sub4 属于 group4,它负责的数据范围为 20161001 ~ 20170101

用户也可以使用快照来确认一下各个子表是否被正确切分,例如查看集合 testcs_doublepartition_domain1.testcl_sub1 是否被分布到 domain1 上

db.snapshot (8, {Name:"testcs_doublepartition_domain1.testcl_sub1"});
{
  "AutoSplit": true,
  "CataInfo": [
    {
      "ID": 0,
      "GroupID": 1000,
      "GroupName": "group1",
      "LowBound": {
        "": 0
      },
      "UpBound": {
        "": 2048
      }
    },
    {
      "ID": 1,
      "GroupID": 1001,
      "GroupName": "group2",
      "LowBound": {
        "": 2048
      },
      "UpBound": {
        "": 4096
      }
    }
  ],
  "EnsureShardingIndex": true,
  "InternalV": 3,
  "MainCLName": "testcs_mainsub.testcl_main_doublepartition",
  "Name": "testcs_doublepartition_domain1.testcl_sub1",
  "Partition": 4096,
  "ShardingKey": {
    "id": 1
  },
  "ShardingType": "hash",
  "Version": 3,
  "_id": {
    "$oid": "57c8004eed44740501b46e46"
  }
}

用户从快照信息中了解到,testcs_doublepartition_domain1.testcl_sub1 集合被切分到group1 和 group2 上,满足domain1 的数据分区组列表。

SequoiaDB巨杉数据库2.6最新版下载

SequoiaDB巨杉数据库技术博客

SequoiaDB巨杉数据库社区

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38749.html

相关文章

  • 新手福音:巨杉数据库教程专区上线啦!

    摘要:为了提供更优质的学习资源,巨杉数据库的技术大牛录制了一套视频教程,以简单直观的方式提供大家学习使用巨杉数据库。如果你是刚刚接触巨杉数据库的用户,本套教程会让你对巨杉产生一套完整的认知,并系统的掌握使用方法。 作为一个程序员 在经历了种种入门之后…showImg(https://segmentfault.com/img/bVMhAI?w=640&h=406); showImg(https...

    oujie 评论0 收藏0
  • 新手福音:巨杉数据库教程专区上线啦!

    摘要:为了提供更优质的学习资源,巨杉数据库的技术大牛录制了一套视频教程,以简单直观的方式提供大家学习使用巨杉数据库。如果你是刚刚接触巨杉数据库的用户,本套教程会让你对巨杉产生一套完整的认知,并系统的掌握使用方法。 作为一个程序员 在经历了种种入门之后…showImg(https://segmentfault.com/img/bVMhAI?w=640&h=406); showImg(https...

    liujs 评论0 收藏0
  • 巨杉Tech | SequoiaDB虚机镜像正式上线

    摘要:针对快速部署和使用分布式数据库的需求,也为方便用户快速体验,巨杉数据库更新了基于虚拟机的数据库镜像。用户可以根据教程下载并使用预先安装配置好的巨杉数据库伪集群环境,快速了解数据库的功能和技术特点。 数据库云化架构需求随着云架构的发展和流行,在业务和应用进行云化的过程中,云数据库因为在整体架构中的重要地位,在云化改造中的重要性不言而喻。云数据库需要满足这些技术要求,除了在功能上的具体提升...

    2bdenny 评论0 收藏0
  • 操作教程】利用YCSB测试巨杉数据库性能

    摘要:一前言巨杉数据库是国内第一款新一代文档型分布式数据库,巨杉数据库由巨杉软件完全自主研发,拥有完全自主知识产权,不基于任何其它的开源项目。作为一款操作性数据库巨杉数据库在海量数据实时读写场景具有得天独厚的优势,拥有较高的读写性能。 一、前言 巨杉数据库(SequoiaDB)是国内第一款新一代文档型分布式数据库,巨杉数据库由巨杉软件完全自主研发,拥有完全自主知识产权,不基于任何其它的开源项...

    wuyangchun 评论0 收藏0
  • 巨杉Tech | 使用 SequoiaDB 布式数据库搭建JIRA流程管理系统

    摘要:通过阅读本文,用户可以了解到如何使用巨杉数据库的实例无缝替换标准数据库。巨杉数据库允许用户在不更改一行代码的情况下直接对已有应用进行后台数据库迁移。 介绍JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。很多企业与互联网公司都在使用Jira作为内部流程管理系统,进行团队协作与问题单管理。...

    sPeng 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<