专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

海量数据解决方案分区分表分库

  对于一个大型的互联网应用,海量数据的存储和访问成为了系统设计的瓶颈问题,对于系统的稳定性和扩展性造成了极大的问题。通过数据切分来提高网站性能,横向扩展数据层已经成为架构研发人员首选的方式。
  问题描述
  1、单个表数据量越大,读写锁,插入操作重新建立索引效率越低。
  2、单个库数据量太大(一个数据库数据量到1T2T就是极限)
  3、单个数据库服务器压力过大
  4、读写速度遇到瓶颈(并发量几百)
  解决思路:根据自己的实际情况,当单表过大的时候进行分表,数据库过大的时候进行分库,高并发的情况考虑读写分离和集群。
  数据拆分方案
  分区:就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的。
  分表:就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表名,然后操作它。
  上述的分区和分表这两种数据拆分方式主要有以下几点的区别:
  (1)实现方式上:mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完整的一张表,都对应三个文件(MyISAM引擎:一个。MYD数据文件,。MYI索引文件,。frm表结构文件)。分区则是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上。
  (2)数据处理上:分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。分区则不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表还是一张表,数据处理还是由自己来完成。
  (3)提高性能上:分表后,单表的并发能力提高了,磁盘IO性能也提高了。分区突破了磁盘IO瓶颈,想提高磁盘的读写能力,来增加mysql性能。在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。
  (4)实现难易度上:分表的方法有很多,用merge来分表,是最简单的一种方式。这种方式和分区难易度差不多,并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。分区实现是比较简单的,建立分区表,跟建平常的表没什么区别,并且对代码端来说是透明的。
  (5)适用场景上:分区一般适用于表数据是分段的,数据操作往往只涉及一部分数据,而不是所有的数据。分表一般适用于频繁插入和联合查询时速度变慢的情况,分表的实现需要业务结合实现和迁移,较为复杂。
  分库:就是把一个库按照一定规则分解成多个库。与分表策略类似,分库可以采用通过关键字取模的方式来对数据库访问进行路由。
  数据拆分方式
  垂直(纵向)拆分:是指按功能模块拆分,以解决表与表之间的io竞争。比如分为订单库、商品库、用户库。。。这种方式多个数据库之间的表结构不同。
  水平(横向)拆分:比如:将同一个表的数据进行分块保存到不同的数据库中,来解决单表中数据量增长出现的压力。这些数据库中的表结构完全相同。
  不管是分表还是分库都可以选择垂直拆分和水平拆分的方式进行。
  分区
  mysql支持的分区类型包括Range、List、Hash、Key,其中Range比较常用:
  RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。
  LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
  HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式。
  KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
  案例:
  建立一个user表以id进行分区,id小于10的在user1分区,id小于20的在user2分区
  createtableuser(
  idintnotnullautoincrement,
  usernamevarchar(10),
  primarykey(id)
  )engineinnodbcharsetutf8
  partitionbyrange(id)(
  partitionuser1valueslessthan(10),
  partitionuser2valueslessthan(20)
  );
  建立后添加分区:
  maxvalue表示最大值这样大于等于20的id都存储在user3分区
  altertableuseraddpartition(
  partitionuser3valueslessthanmaxvalue
  );
  删除分区:
  altertableuserdroppartitionuser3;
  现在打开mysql的数据目录
  可以看见多了userPuser1。ibd和userPuser2。ibd这两个文件。
  如果表使用的存储引擎是MyISAM类型,就是:
  userPuser1。MYD,userPuser1。MYI和userPuser2。MYD,userPuser2。MYI
  由此可见,mysql通过分区把数据保存到不同的文件里,同时索引也是分区的。相对于未分区的表来说,分区后单独的数据库文件索引文件的大小都明显降低,效率则明显的提示了。可以插入一条数据然后分析查询语句验证一下:
  insertintouservalues(null,测试);
  explainpartitionsselectfromuserwhereid1;
  可以看见仅仅在user1分区执行了这条查询。
  具体分区的效率是多少还需要看数据量。在分区时可以通过DATADIRECTORY和INDEXDIRECTORY选项把不同的分区放到不同的磁盘上进一步提高系统的IO吞吐量。
  分区类型的选择,通常使用Range类型,不过有些情况,比如主从结构中,主服务器很少使用‘select’查询,在主服务器上使用Range类型分区通常没有太大的意义,此时使用Hash类型分区更好例如:
  partitionbyhash(id)partitions10;
  当插入数据时,根据id把数据平均散到各个分区上,由于文件小,效率高,更新操作变得更快。
  在分区时使用的字段,通常情况下按时间字段分区,具体情况以需求而定。划分应用的方式有很多种,比如按时间或用户,哪种用的多,就选择哪种分区。如果使用主从结构可能就更加灵活,有的从服务器使用时间,有的使用用户。不过如此一来当执行查询时,程序应该负责选择真确的服务器查询,写个mysqlproxy脚本应该可以透明的实现。
  分区的限制:
  1。主键或者唯一索引必须包含分区字段,如primarykey(id,username),不过innoDB的大组建性能不好。
  2。很多时候,使用分区就不要在使用主键了,否则可能影响性能。
  3。只能通过int类型的字段或者返回int类型的表达式来分区,通常使用year或者todays等函数(mysql5。6对限制开始放开了)。
  4。每个表最多1024个分区,而且多分区会大量消耗内存。
  5。分区的表不支持外键,相关的逻辑约束需要使用程序来实现。
  6。分区后,可能会造成索引失效,需要验证分区可行性。
  分区模式详解:
  Range(范围)这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980s)的数据,90年代(1990s)的数据以及任何在2000年(包括2000年)后的数据。
  CREATETABLEusers(
  idINTUNSIGNEDNOTNULLAUTOINCREMENTPRIMARYKEY,
  usersnameVARCHAR(30)NOTNULLDEFAULT,
  emailVARCHAR(30)NOTNULLDEFAULT
  )
  PARTITIONBYRANGE(id)(
  PARTITIONp0VALUESLESSTHAN(3000000),
  PARTITIONp1VALUESLESSTHAN(6000000),
  PARTITIONp2VALUESLESSTHAN(9000000),
  PARTITIONp3VALUESLESSTHANMAXVALUE
  );
  在这里,将用户表分成4个分区,以每300万条记录为界限,每个分区都有自己独立的数据、索引文件的存放目录。还可以将这些分区所在的物理磁盘分开完全独立,可以提高磁盘IO吞吐量。
  CREATETABLEusers(
  idINTUNSIGNEDNOTNULLAUTOINCREMENTPRIMARYKEY,
  usersnameVARCHAR(30)NOTNULLDEFAULT,
  emailVARCHAR(30)NOTNULLDEFAULT
  )
  PARTITIONBYRANGE(id)(
  PARTITIONp0VALUESLESSTHAN(3000000)
  DATADIRECTORYdata0data
  INDEXDIRECTORYdata0index,
  PARTITIONp1VALUESLESSTHAN(6000000)
  DATADIRECTORYdata1data
  INDEXDIRECTORYdata1index,
  PARTITIONp2VALUESLESSTHAN(9000000)
  DATADIRECTORYdata2data
  INDEXDIRECTORYdata2index,
  PARTITIONp3VALUESLESSTHANMAXVALUE
  DATADIRECTORYdata3data
  INDEXDIRECTORYdata3index
  );
  List(预定义列表)这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA根据用户的类型进行分区。
  CREATETABLEuser(
  idINTUNSIGNEDNOTNULLAUTOINCREMENTPRIMARYKEY,
  nameVARCHAR(30)NOTNULLDEFAULT,
  usertypeintnotnull
  )
  PARTITIONBYLIST(usertype)(
  PARTITIONp0VALUESIN(0,4,8,12),
  PARTITIONp1VALUESIN(1,5,9,13),
  PARTITIONp2VALUESIN(2,6,10,14),
  PARTITIONp3VALUESIN(3,7,11,15)
  );
  分成4个区,同样可以将分区设置的独立的磁盘中。
  Hash(哈希)这种模式允许DBA通过对表的一个或多个列的HashKey进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。
  CREATETABLEuser(
  idINTUNSIGNEDNOTNULLAUTOINCREMENTPRIMARYKEY,
  usernameVARCHAR(30)NOTNULLDEFAULT,
  emailVARCHAR(30)NOTNULLDEFAULT
  )
  PARTITIONBYHASH(id)PARTITIONS4(
  PARTITIONp0,
  PARTITIONp1,
  PARTITIONp2,
  PARTITIONp3
  );
  分成4个区,同样可以将分区设置的独立的磁盘中。
  Key(键值)上面Hash模式的一种延伸,这里的HashKey是MySQL系统产生的。
  CREATETABLEuser(
  idINTUNSIGNEDNOTNULLAUTOINCREMENTPRIMARYKEY,
  nameVARCHAR(30)NOTNULLDEFAULT,
  emailVARCHAR(30)NOTNULLDEFAULT
  )
  PARTITIONBYKEY(id)PARTITIONS4(
  PARTITIONp0,
  PARTITIONp1,
  PARTITIONp2,
  PARTITIONp3
  );
  分区管理(1)删除分区
  ALERTTABLEusersDROPPARTITIONp0;
  (2)重建分区
  RANGE分区重建
  ALTERTABLEusersREORGANIZEPARTITIONp0,p1INTO(PARTITIONp0VALUESLESSTHAN(6000000));
  将原来的p0,p1分区合并起来,放到新的p0分区中。
  LIST分区重建
  ALTERTABLEusersREORGANIZEPARTITIONp0,p1INTO(PARTITIONp0VALUESIN(0,1,4,5,8,9,12,13));
  将原来的p0,p1分区合并起来,放到新的p0分区中。
  HASHKEY分区重建
  ALTERTABLEusersREORGANIZEPARTITIONCOALESCEPARTITION2;
  用REORGANIZE方式重建分区的数量变成2,在这里数量只能减少不能增加。想要增加可以用ADDPARTITION方法。
  (3)新增分区
  新增RANGE分区
  altertableuseraddpartition(partitionuser3valueslessthanmaxvalue);
  新增LIST分区
  ALTERTABLEcategoryADDPARTITION(PARTITIONp4VALUESIN(16,17,18,19));
  新增HASHKEY分区
  ALTERTABLEusersADDPARTITIONPARTITIONS8;
  将分区总数扩展到8个。
  给已有的表加分区
  altertableresultspartitionbyRANGE(month(ttime))
  (PARTITIONp0VALUESLESSTHAN(1),
  PARTITIONp1VALUESLESSTHAN(2),PARTITIONp2VALUESLESSTHAN(3),
  PARTITIONp3VALUESLESSTHAN(4),PARTITIONp4VALUESLESSTHAN(5),
  PARTITIONp5VALUESLESSTHAN(6),PARTITIONp6VALUESLESSTHAN(7),
  PARTITIONp7VALUESLESSTHAN(8),PARTITIONp8VALUESLESSTHAN(9),
  PARTITIONp9VALUESLESSTHAN(10),PARTITIONp10VALUESLESSTHAN(11),
  PARTITIONp11VALUESLESSTHAN(12),
  PARTITIONP12VALUESLESSTHAN(13));
  分表
  分表和分区类似,区别是,分区是把一个逻辑表文件分成几个物理文件后进行存储,而分表则是把原先的一个表分成几个表。进行分表查询时可以通过union或者视图。
  分表又分垂直分割和水平分割,其中水平分分割最为常用。水平分割通常是指切分到另外一个数据库或表中。例如对于一个会员表,按对3的模进行分割:
  tableid3
  如果id30则将用户数据放入到user0表中,如id31就放入user1表中,依次类推。
  在这里有个问题,这个uid应该是所有会员按序增长的,可他是怎么得到的呢?使用autoincrement是不行的,这样就用到序列了。
  对于一些流量统计系统,其数据量比较大,并且对过往数据的关注度不高,这时按年、月、日进行分表,将每日统计信息放到一个以日期命名的表中;或者按照增量进行分表,如每个表100万数据,超过100万就放入第二个表。还可以按Hash进行分表,但是按日期和取模余数分表最为常见,也容易扩展。
  分表后可能会遇到新的问题,那就是查询,分页和统计。通用的方法是在程序中进行处理,辅助视图。
  使用分表案例1:
  对会员数据对5取模,放在5个表中,如何查询会员数据?已知id查询会员数据,代码如下:
  lt;?php查询单个会员数据
  customertablecustomer。id5;
  sqlselectfrom。customertable。wherecustomerid。id;查询全部会员数据
  sql;
  tbale〔customer0,customer1,customer2,customer3,customer4〕;foreach(tableasv){
  sql。selectfrom。v。union;
  }
  sqlsubstr(sql,0,5);
  ?
  这样就可以查询某一个会员的数据或者全部会员的数据了。同理,分页的话在这个大集合中使用limit就可以了。但是这样做又会有一个疑问,把所有的表连起来查询和部分表没有什么区别,其实在实际的应用中,不可能查看所有的会员资料,一次查看20个然后分页。完全没有必要做union,仅查询一个表就可以了,唯一需要考虑的是在分页零界点时的衔接。其实,这个衔接是否那么重要?即使偶尔出现几条数据的差异,也不会对业务有任何的影响。
  2。和其它表进行关联和1类似。
  3。根据会员姓名搜索用户信息。在这种需求下,需要搜索所有的表,并对结果进行汇总。虽然这样做产生了多次的查询,但并不代表效率低。好的sql语句执行10次也比差的sql语句执行一次快。
  使用分表案例2:
  在一个流量监控系统中,由于网络流量巨大,统计数据很庞大,需要按天分表。先要得到任意日,周,月的数据。
  1。需要任意一天的数据。直接查询当天的数据表即可。
  2。需要几天的数据。分别查询这几天的数据,然后进行汇总。
  3。需要查询一周的数据。对一周的数据定期汇总到一个week表,从这个表里面查询。这个汇总过程可以由一个外部程序完成,也可以由定期的脚本完成。
  4。查询一个月的数据。汇总本月所有的数据到month表,在此表查询。
  5。查询5个月内的详细数据。不支持。仅支持最多3个月的详细数据。数据没3个月已归档一次。在大数据的处理中,必须做出一些牺牲。对于超出3个月的数据,仅提供统计数据,详细数据需要查看归档。90天或者180天,给数据保存设个界限,也是大部分这类系统的常规做法,超出90天的数据就不再提供数据详单了。比如,移动的通话记录最多保存半年,即180天,超过这个范围的数据不在提供查询。如果你实在需要,可能就要联系移动的工程师了。
  分表前应该尽量按照实际业务来分表,参考依据就是哪些字段在查询中起到作用,那就这些字段来分表,并且需要在分表前就估算好规模,也就是先确定好规则在分表。
  对于分表后的操作,依然是联合查询,视图等基本操作,或者使用merge引擎合并数据并在此表中查询。复杂一些操作需要借助存储过程来完成,借助外部工具实现对分表的管理。
  对于比较庞大的数据,不论是否进行分表,都必须考虑功能和效率的平衡性,并在功能上做出让步。我们不能事事迁就用户,而应该对某些影响效率的功能做出限制。例如移动公司的180天限制、论坛禁止对老帖进行回复等。
  分库分表存在的问题
  (1)事务问题:在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
  (2)跨库跨表的join问题:在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。
  (3)额外的数据管理负担和数据运算压力:额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个orderby语句就可以搞定,但是在进行分表之后,将需要n个orderby语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。

王莽篡汉后对新朝政权的改革,造成的社会危机王莽(前45一公元23),字巨君,是元帝皇后王政君的侄子。因其父早死,早年生活恭俭,勤奋博学,终于在贵族官僚中博得了声誉。成帝绥和元年(前8),他继其诸叔父之后,出任大司马大将军辅陕西出台50条措施推动经济社会平稳健康发展3月2日,陕西省委陕西省人民政府印发进一步提振信心恢复活力推动经济社会平稳健康发展的若干措施,涉及十方面50条具体举措,进一步提振市场信心恢复市场活力。扎实开展高质量项目推进年营商演技烂全靠父母硬捧?星二代霸屏,娱圈畸形世袭制该改了文海利编辑海利前言现在好看的电视剧似乎越来越少了,这可不单单是因为生活好了,所以审美也随之提高。而是实打实的很多电视剧越拍越烂。其中很大一部分原因就是因为主角们都被被一些演技堪忧的内心缺爱的孩子,身上这3个特征很明显,父母要引起重视爱往往是贯穿着人们一生的,任何人的生活,就不能缺少爱的温暖。尤其是对于孩子来说,给予足够的关爱,往往能让他们更加健康顺利的成长。如果孩子在孩童时代,缺乏来自父母的关爱,那么就很容易童年漫游者父母给孩子最珍贵的遗产,是他们面对生命的态度他用书写进行自我疗愈童年漫游者(Childhood)的作者安德烈亚力克西斯(加拿大)在中国读者听来可能有一点陌生,而且他的作品不多,只有两本书,另一部叫做十五条狗。然而这两本书都是苏联驸马爷落马老丈人去世了,保护伞没有了1988年12月30日,莫斯科最高法院军事审判庭内气氛肃穆。在被告席上,一个背部微驼呆若木鸡的50多岁男人正在等待审判。这个人就是苏联驸马爷勃列日涅夫的女婿丘尔巴诺夫,他还有个身份云上黄河大集莘县水源新能源科技有限公司市政协委员县人大常委董事长胡志忠莘县水源新能源科技有限公司下设聊城市水源糠醛有限公司巨野鲁源两糠生化有限公司商丘聚源化工有限公司三个分公司。固定资产3。2亿元,近3年销售金额5亿多ChatGPT到底有多懂准格尔黄河大峡谷?一起来看看它的回答!最近很火的话题人工智能实验室OpenAI发布的ChatGPT一定榜上有名ChatGPT拥有强大的信息整合能力自然语言处理能力而且还能根据要求进行聊天撰写论文创作诗歌就连生成游戏剧本黄河三峽(原创)文字编辑制作李义所小浪底黄河三峡景区位于河南省洛阳市孟津县济源市边界,地跨黄河南北两岸。小浪底黄河三峡景区总面积1262平方公里(其中水面296平方公里),峡谷河流为主要特色,属于清代陕西行政区划(公元16441911年)清王朝系女真族(满族祖先)建立。女真族世居我国东北地区,16世纪80年代到17世纪初,女真族杰出领袖努尔哈赤,统一女真各部,创立八旗制度。于明朝万历四十四Chat学问如何打造中国式现代化的黄河样本?编者按学术中原提问,专家来回答。在全国两会到来之前,学术中原开启学问聊天模式,联合河南大学黄河文明与可持续发展研究中心,围绕黄河文明和中国式现代化两个热词,立足中原,放眼全国,问答
一棵白杨生众目睽睽望新开2023游戏新春创作纪兔逢新春开启了春日的聊吧才知道你是我的课堂不知不觉活过了衔接岁月的冬天。万象更新,跟随一曲曲循序渐进的自然小调,兴味至浓地挺进繁衍盛达的时节大调中,跌宕起伏启那些因为日元贬值蜂拥而来的国际游客,日本人不了解他们在不了解如何应对外国人的情况下,想要提高日本观光水准我认为是天方夜谭我是在中国创业的日本人佐藤峻,今天想谈谈日本正在加拉帕戈斯化(化)的服务,即像加拉帕戈斯群岛般,只在特定地区扎根教你在家做小黄鱼,外酥里软,连鱼刺都很酥脆,大人小孩都爱吃教你在家做小黄鱼,外酥里软,连鱼刺都很酥脆,大人小孩都爱吃最近吃了不少鱼了。我自己不太喜欢吃鱼的,因为从小没吃太多次,导致实在不太会吐刺,当然如果让我吃咸鱼我倒是可以的。只是现在感日本武士的剖腹现场,尼日利亚的鬣狗训练师,39张图看世界01世界上唯一幸存的大象盔甲,16世纪后期在印度制造。021949年8月29日,苏联首次成功引爆核武器的场景。这颗20千吨的原子弹,绰号第一闪电,是使用德国籍原子物理学家的克劳斯福赛事蓬勃开展,球迷越来越多三人篮球秀出青春潮流(竞技观察)来源人民日报2月5日,三人篮球国家男队在上海崇明训练基地举行队内对抗赛。三人篮球国家队供图2022年7月9日,一场三人篮球比赛在湖南长沙一商场举行,球员积极攻防。杨华峰摄(影像中国村界杯火了!江浙农村里的足球赛,凭啥吸引国足队员观赛?国足队员来了市里县里的足球队来了周边的足球爱好者们来了村界杯是八堡村今年春节期间最火热的活动,没有之一,从大年初一到初七,全村男女老少都是忠实的观众。每天下午,早早搬上小板凳,在村习作天地我是一名光荣的仪仗队队员我是师大附中博才实验中学初中三年级的学生,是一名光荣的校仪仗队队员。校仪仗队主要负责我们学校日常升旗降旗每周一早上的升旗仪式和执行各种大型典礼的礼仪任务。能够站在红旗下展现我校风貌02!网坛爆大冷00后大满贯冠军出局,中国选手传来好消息北京时间2023年2月8日,WTA500级别的阿布扎比站决出女单16强,00后大满贯冠军安德莱斯库以6726不敌普丁塞娃,再次遭遇一轮游。中国选手传来不少好消息,同样出战阿布扎比站河南省首次公开披露16家豫酒生产企业销售成绩单企业排序发生显著变化排名前列的豫酒大河报豫视频记者霍坤峰文图近日,河南省商务厅发布了16家豫酒生产企业流通数据统计情况,其中包括2022年全年销售数据和2022年12月份单月销售数据。据统计,16家豫立春后,最该给家人吃这肉,比猪肉还便宜,补足营养度过春季立春节气之后,我们正式迈入到春季,现在正处于初春阶段,慢慢从寒冷到暖和,风和日暖,气温慢慢升高,万物生发,大自然充满了生机勃勃的气息。立春过后,我们要顺应季节的变化,调整我们的作息你的头发健康吗?这是个看颜值的时代,拥有一头乌黑亮丽的秀发应该是每个人心中的诉求,尤其作为女性,当在社交平台中晒出自己长发飘飘的照片时,总是会赢来一片称赞。可在日常生活中,很多人的头发状态都称不上
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网