使用FriendFeed来提升MySQL性能的方法

2019-01-05 09:48:52于海丽

最终,虽然我们的数据表增多了,但添加和删除索引却变得简单了。我们大力改善了添加索引数据的进程(我们称之为“清洁工")使其在快速添加索引的同时不会影响站点。我们可以在一天内完成新属性的保存和索引,并且我们不需要对调主从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"))