澳门皇冠金沙网站-澳门皇冠844网站

热门关键词: 澳门皇冠金沙网站,澳门皇冠844网站

使用java实现数据库编程,使用FriendFeed来提升My

第一章:

 背景

利用FriendFeed来升高MySQL品质的法子,friendfeedmysql

 背景

咱俩选拔MySQL存款和储蓄了FriendFeed的具有数据。数据库随着顾客基数的增高而抓实了过多。今后一度积累了凌驾2.5亿条记下与一群包蕴了从评价和“喜欢”到相知列表的别样数据。

乘胜数据的增进,我们也曾迭代地消除了乘胜那样高效的加强而带来的扩展性难点。大家的品尝很有代表性,比方使用只读mysql从节点和memcache来充实读取吞吐量,对数据库实行分片来提升写入吞吐量。不过,随着事情的增加,加多新职能比扩展既有功力以迎合越来越多的流量变得特别困难。

特意的,对 schema 做改造或为超过 1000-三千万行记录的数据库增添索引会将数据库锁住多少个小时。删除旧索引也要占用这么多时光,但不删除它们会耳熏目染属性;因为数据库要持续地在种种INSERT上读写那些没用的区块,并将重视的区块挤出了内部存款和储蓄器。为制止那个难题供给运用一些繁杂的章程(比方在从节点上安装新的目录,然后将从节点与主节点对调),但这么些主意会引发错误并且实施起来比较困难,它们阻碍了索要退换schema/索引技艺兑现的新效用。由于数据库的不得了分散,MySQL 的涉嫌性子(如join)对大家没用,所以大家决定脱离 GL450DBMS。

尽管已有非常多用以化解灵活 schema 数据存储和周转时营造索引的标题(比如CouchDB)的花色。但在大站点中却未曾丰硕广泛地用到来讲服大家使用。在大家见到和平运动作的测量检验中,这一个项目依旧不牢固,要么贫乏丰裕的测量试验(参见那个略带过时的有关 CouchDB 的小说)。MySQL 不错,它不会破坏数据;复制也没难点,大家早就通晓了它的受制。大家欣赏将 MySQL 用于存款和储蓄,仅仅是非关系型的积累。

几经怀想,大家决定在 MySQL 上应用一种无方式的积存系统,实际不是利用多少个通通没接触过的囤积系统。本文试图描述那么些种类的高端级细节。我们很奇异别的大型网站是怎么着管理这么些题指标,别的也盼望我们成功的一些设计会对别的开采者有所协助。

综述

大家在数据库中存款和储蓄的是无格局的属性集(譬如JSON对象或python字典)。存款和储蓄的笔录只需几个名称为id的16字节的UUID属性。对数据库来说实体的其余一些是不可知的。我们得以差非常的少地存入新属性来退换schema(能够简轻巧单精晓为数据表中唯有七个字段:id,data;个中data存款和储蓄的是实体的属性集)。

大家通过保留在差异表中的目录来搜索数据。假如想搜寻各样实体中的多个性情,大家就必要多个数据表-每一个表用于检索某一一定属性。假若不想再用某一索引了,大家要在代码中结束该索引对应表的写操作,并可选地删除那三个表。假若想增多个新索引,只要求为该索引新建个MySQL表,并运转三个进程异步地为该表增添索引数据(不影响运转中的服务)。

最后,即使大家的多少表增加了,但丰盛和删除索引却变得简单了。大家着力革新了增加索引数据的历程(大家誉为“清洁工")使其在全速增添索引的同一时候不会潜濡默化站点。大家得以在一天内达成新属性的保存和目录,並且大家不要求对调主从MySQL数据库,也无需任何另外可怕的操作。

细节

MySQL 使用表保存我们的实体,三个表就如这么 :  

CREATE TABLE entities (
  added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  id BINARY(16) NOT NULL,
  updated TIMESTAMP NOT NULL,
  body MEDIUMBLOB,
  UNIQUE KEY (id),
  KEY (updated)
) ENGINE=InnoDB;

所以选拔 added_id 个字段是因为 InnoDB 按物理主键顺序存款和储蓄数据,自拉长主键确定保障新实例在磁盘上按梯次写到老实体之后,那样有助于分区读写(绝对老的实体,新实体往往读操作更频仍,因为 FriendFeed 的 pages 是按期间逆序排列)。实体本人经 python 字典体系化后使用 zlib 压缩存款和储蓄。

目录单独存在一张表里,借使要成立索引,大家创制一张新表存款和储蓄大家想要索引的数量分片的具有属性。举例,二个FriendFeed 实体通过看上去是这么的:  

{
  "id": "71f0c4d2291844cca2df6f486e96e37c",
  "user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
  "feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
  "title": "We just launched a new backend system for FriendFeed!",
  "link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
  "published": 1235697046,
  "updated": 1235697046,
}

我们索引实体的习性 user_id,那样我们得以渲染多个页面,包括二个已提交客户的有所属性。大家的索引表看起来是这么的:

CREATE TABLE index_user_id (
  user_id BINARY(16) NOT NULL,
  entity_id BINARY(16) NOT NULL UNIQUE,
  PRIMARY KEY (user_id, entity_id)
) ENGINE=InnoDB;

我们的数据存储会活动为您维护索引,所以一旦你要在大家存款和储蓄上述组织实体的数目存款和储蓄里张开三个实例,你能够写一段代码(用 python):  

user_id_index = friendfeed.datastore.Index(
  table="index_user_id", properties=["user_id"], shard_on="user_id")
datastore = friendfeed.datastore.DataStore(
  mysql_shards=["127.0.0.1:3306", "127.0.0.1:3307"],
  indexes=[user_id_index])

new_entity = {
  "id": binascii.a2b_hex("71f0c4d2291844cca2df6f486e96e37c"),
  "user_id": binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"),
  "feed_id": binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"),
  "title": u"We just launched a new backend system for FriendFeed!",
  "link": u"http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
  "published": 1235697046,
  "updated": 1235697046,
}
datastore.put(new_entity)
entity = datastore.get(binascii.a2b_hex("71f0c4d2291844cca2df6f486e96e37c"))
entity = user_id_index.get_all(datastore, user_id=binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"))

地点的 Index 类在具备实体中寻觅 user_id,自动珍惜 index_user_id 表的目录。大家的数据库是切分的,参数 shard_on 是用来明确索引是积存在哪个分片上(这种情景下使用 entity["user_id"] % num_shards)。

你能够选拔索引实例(见上边的 user_id_index.get_all)查询一个目录,使用 python 写的数据存款和储蓄代码将表 index_user_id 和表 entities 合併。首先在全数数据库分片中查询表 index_user_id 获取实体 ID 列,然后在 entities 提议数据。

新建贰个索引,举个例子,在性质 link 上,大家能够创设三个新表:  

CREATE TABLE index_link (
  link VARCHAR(735) NOT NULL,
  entity_id BINARY(16) NOT NULL UNIQUE,
  PRIMARY KEY (link, entity_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

咱俩得以修改数据存款和储蓄的最早化代码以带有大家的新索引:  

user_id_index = friendfeed.datastore.Index(
  table="index_user_id", properties=["user_id"], shard_on="user_id")
link_index = friendfeed.datastore.Index(
  table="index_link", properties=["link"], shard_on="link")
datastore = friendfeed.datastore.DataStore(
  mysql_shards=["127.0.0.1:3306", "127.0.0.1:3307"],
  indexes=[user_id_index, link_index])

自家得以异步塑造索引(非常是实时传输服务):  

./rundatastorecleaner.py --index=index_link

一致性与原子性

由于使用分区的数据库,实体的目录恐怕存款和储蓄在与实业分化的分区中,那引起了一致性难题。假若经过在写入全部索引表前崩溃了会如何?

不胜枚举有野心的 FriendFeed 技术员援助于塑造一个事务性构和,但大家愿意尽量地维持系统的简练。咱们决定放宽限制:

  •     保存在主实体表中的属性集是标准完整的
  •     索引不会对真实实体值发生震慑

故而,往数据库中写入实体时大家采纳如下步骤:

  •     使用 InnoDB 的 ACID 属性将实体写入 entities 表。
  •     将引得写入全体分区中的索引表。

咱们要牢记从索引表中收取的数目或然是不确切的(举个例子假使写操作未有水到渠成步骤2大概会听得多了就能说的详细旧属性值)。为保证采纳地点的限制能重回正确的实业,大家用索引表来调整要读取哪些实体,但不用相信索引的完整性,要利用查询条件对这一个实体举办再过滤:

1.基于查询条件从索引表中获取 entity_id

2.根据 entity_id 从 entities 表中读取实体

3.依照实体的诚实属性(用 Python)过滤掉不相符查询条件的实业

为保险索引的悠久性和一致性,上文提到的“清洁工”进程要持续运转,写入错失的目录,清理失效的旧索引。它预先清理近日更新的实体,所以实际维护索引的一致性异常的快(几分钟).
 
性能

作者们对新系统的主索引举行了优化,对结果也很乐意。以下是本月 FriendFeed 页面包车型大巴加载延时总括图(大家在后天开发银行了新的后端,你可以依靠延时的醒目收缩找到那一天)。

足球皇冠官网 1

特意地,系统的延时现行反革命也很牢固(哪怕是在午高峰时期)。如下是过去24小时FriendFeed页面加载延时图。

足球皇冠官网 2

与上周的某天相比较:

足球皇冠官网 3

系统到近年来截至使用起来很有利。大家在安顿之后也退换了五回索引,况且大家也起初将这种格局应用于 MySQL 中那多少个一点都不小的表,那样大家在以往能够轻便地转移它们的结构。

背景 大家利用MySQL存储了FriendFeed的有所数据。数据库随着客商基数的抓牢而升高了繁多。...

entity  实体

我们利用MySQL存款和储蓄了FriendFeed的全体数据。数据库随着客商基数的巩固而滋长了多数。未来已经积存了超越2.5亿条记下与一批包蕴了从评价和“喜欢”到相知列表的其余数据。

relationship  关系

乘胜数据的升高,大家也曾迭代地消除了乘胜这样高效的增高而带来的扩大性难题。大家的尝试很有代表性,比方利用只读mysql从节点和memcache来充实读取吞吐量,对数据库实行分片来升高写入吞吐量。可是,随着事情的巩固,增多新功能比增添既有效果以迎合越来越多的流量变得愈加困难。

diagram  图表 

特意的,对 schema 做改造或为抢先 一千-2000万行记录的数据库增加索引会将数据库锁住多少个钟头。删除旧索引也要侵吞这么多日子,但不删除它们会影响属性;因为数据库要不停地在每一个INSERT上读写这几个没用的区块,并将重大的区块挤出了内部存款和储蓄器。为制止这么些难题亟待采纳一些繁杂的方法(例如在从节点上安装新的目录,然后将从节点与主节点对调),但这个方法会掀起错误而且施行起来相比较不方便,它们阻碍了急需改换schema/索引手艺达成的新效用。由于数据库的要紧分散,MySQL 的关联天性(如join)对大家没用,所以大家决定脱离 酷威DBMS。

model 模型

虽说已有为数相当的多用以缓慢解决灵活 schema 数据存款和储蓄和平运动作时创设索引的主题材料(举个例子CouchDB)的体系。但在大站点中却未曾丰硕布满地用到来讲服大家使用。在我们看到和平运动行的测量检验中,那些项目恐怕不安宁,要么缺少丰硕的测验(参见那个略带过时的有关 CouchDB 的作品)。MySQL 不错,它不会损坏数据;复制也没难点,大家曾经理解了它的局限。大家欣赏将 MySQL 用于存款和储蓄,仅仅是非关系型的仓库储存。

normal   规范的

几经牵记,我们决定在 MySQL 上行使一种无形式的蕴藏系统,实际不是采纳八个一心没接触过的储存系统。本文试图描述这么些系统的高档细节。我们很惊叹其余大型网址是何等管理那一个题目标,别的也期待大家成功的一点设计会对其他开荒者有所支持。

formate  形式

综述

hotel  旅馆

大家在数据库中寄放的是无形式的属性集(比如JSON对象或python字典)。存款和储蓄的记录只需几个名叫id的16字节的UUID属性。对数据库来说实体的另外界分是不可知的。大家能够简简单单地存入新属性来更动schema(能够老妪能解为数据表中只有三个字段:id,data;个中data存储的是实业的属性集)。

guest  客人

咱俩由此保留在分裂表中的目录来寻找数据。若是想寻觅各个实体中的八个属性,我们就须求多个数据表-种种表用于检索某一一定属性。假设不想再用某一索引了,大家要在代码中甘休该索引对应表的写操作,并可选地删除那二个表。借使想加多个新索引,只须要为该索引新建个MySQL表,并运行二个历程异步地为该表增添索引数据(不影响运转中的服务)。

promation 提升 推广

末尾,即使大家的数目表增加了,但增进和删除索引却变得轻便了。我们全力创新了加多索引数据的长河(大家誉为“清洁工")使其在飞速增添索引的同期不会影响站点。大家能够在一天内完结新属性的保留和目录,何况大家无需对调主从MySQL数据库,也无需别的另外可怕的操作。

state  状态

细节

type  类型

MySQL 使用表保存大家的实体,叁个表就像这样 :  

 

CREATE TABLE entities (
  added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  id BINARY(16) NOT NULL,
  updated TIMESTAMP NOT NULL,
  body MEDIUMBLOB,
  UNIQUE KEY (id),
  KEY (updated)
) ENGINE=InnoDB;

第二章:

据此选拔 added_id 个字段是因为 InnoDB 按物理主键顺序存款和储蓄数据,自增加主键确定保证新实例在磁盘上按梯次写到老实体之后,那样有利于分区读写(相对老的实体,新实体往往读操作更频仍,因为 FriendFeed 的 pages 是按期间逆序排列)。实体本人经 python 字典体系化后使用 zlib 压缩存款和储蓄。

networking 网络

目录单独存在一张表里,若是要成立索引,大家创建一张新表存款和储蓄大家想要索引的多少分片的享有属性。例如,一个FriendFeed 实体通过看上去是这么的:  

option 选择的

{
  "id": "71f0c4d2291844cca2df6f486e96e37c",
  "user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
  "feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
  "title": "We just launched a new backend system for FriendFeed!",
  "link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
  "published": 1235697046,
  "updated": 1235697046,
}

port   端口号

咱俩索引实体的属性 user_id,那样我们得以渲染叁个页面,包蕴贰个已交由顾客的具有属性。大家的索引表看起来是那样的:

firewall  防火墙

CREATE TABLE index_user_id (
  user_id BINARY(16) NOT NULL,
  entity_id BINARY(16) NOT NULL UNIQUE,
  PRIMARY KEY (user_id, entity_id)
) ENGINE=InnoDB;

engine   引擎

我们的数额存款和储蓄会自行为您维护索引,所以要是你要在大家存款和储蓄上述组织实体的多寡存款和储蓄里开启一个实例,你能够写一段代码(用 python):  

standard  标准

user_id_index = friendfeed.datastore.Index(
  table="index_user_id", properties=["user_id"], shard_on="user_id")
datastore = friendfeed.datastore.DataStore(
  mysql_shards=["127.0.0.1:3306", "127.0.0.1:3307"],
  indexes=[user_id_index])

new_entity = {
  "id": binascii.a2b_hex("71f0c4d2291844cca2df6f486e96e37c"),
  "user_id": binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"),
  "feed_id": binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"),
  "title": u"We just launched a new backend system for FriendFeed!",
  "link": u"http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
  "published": 1235697046,
  "updated": 1235697046,
}
datastore.put(new_entity)
entity = datastore.get(binascii.a2b_hex("71f0c4d2291844cca2df6f486e96e37c"))
entity = user_id_index.get_all(datastore, user_id=binascii.a2b_hex("f48b0440ca0c4f66991c4d5f6a078eaf"))

character  字符

地点的 Index 类在具有实体中研究 user_id,自动珍贵 index_user_id 表的目录。大家的数据库是切分的,参数 shard_on 是用来分明索引是积攒在哪些分片上(这种意况下使用 entity["user_id"] % num_shards)。

collation  校对

你能够利用索引实例(见上边的 user_id_index.get_all)查询二个索引,使用 python 写的多少存款和储蓄代码将表 index_user_id 和表 entities 合併。首先在具有数据库分片中询问表 index_user_id 获取实体 ID 列,然后在 entities 建议数据。

storage   存储

新建三个索引,比如,在质量 link 上,我们能够创造三个新表:  

create  创建

CREATE TABLE index_link (
  link VARCHAR(735) NOT NULL,
  entity_id BINARY(16) NOT NULL UNIQUE,
  PRIMARY KEY (link, entity_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

drop  删除

笔者们得以修改数据存款和储蓄的起头化代码以包涵我们的新索引:  

comment  注释

user_id_index = friendfeed.datastore.Index(
  table="index_user_id", properties=["user_id"], shard_on="user_id")
link_index = friendfeed.datastore.Index(
  table="index_link", properties=["link"], shard_on="link")
datastore = friendfeed.datastore.DataStore(
  mysql_shards=["127.0.0.1:3306", "127.0.0.1:3307"],
  indexes=[user_id_index, link_index])

variables  可变的、变量

小编能够异步营造索引(特别是实时传输服务):  

 

./rundatastorecleaner.py --index=index_link

 

一致性与原子性

 

是因为使用分区的数据库,实体的目录或许存款和储蓄在与实业分歧的分区中,那引起了一致性难题。假如经过在写入全体索引表前崩溃了会什么?

本文由澳门皇冠金沙网站发布于数据库研究,转载请注明出处:使用java实现数据库编程,使用FriendFeed来提升My