1、为什么需要主从复制

  • 在业务中 有一条sql需要锁表 就会导致其他读业务不能执行 ,那么就很影响业务,使用主从复制,让主库写,从库读。这样即使主库出现锁表情况,从库也可以正常使用,保证业务正常进行
  • 做数据热备
  • 架构的扩展 ,业务量越来越大,I/O访问频率过高,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能

2、什么是主从复制

Mysql主从复制是指数据可以从一个Mysql数据库服务器主节点中复制到另一个或多个从节点中Mysql默认采用异步复制的方式,这样从节点不用一直访问主服务器来更新自己的数据,数据更新可以在远程连接上操作,从节点可以复制主数据库的所有数据库或者特定的数据库,或者特定的表

3、Mysql复制原理

(1) 主节点将数据改变放入binlog日志

(2) 从节点会定时去检测binlog是否改变,如果发生改变,则开始一个I/O Thread 请求主节点二进制事件

(3) 同时主节点每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制事件,在本地重放,使得其数据与主节点保持一致,最后I/O Thread 和SQLThread 将进入休眠状态 等待下一次唤醒

也就是说:

  • 从库会生成两个线程 一个 I/O Thread 、一个SQL Thread
  • I/O Thead 会去请求主节点的binlog 并将得到的binlog写到本地的replay-log(中继日志)中
  • 主节点会生成一个log dump 线程,用来给从节点的I/O 线程传递binlog
  • SQL线程会读取replay-log 文件中的日志,并解析成sql 语句 主句执行

注意:

  1. 主节点将操作语句记录到binlog中,然后授予从节点远程连接权限,(主节点一定要开启binlog日志,为了安全起见,从节点一般也开启binlog日志)
  2. 从节点开启两个线程 :I/O 线程 、 SQL 线程 。
    其中I/O线程负责读取主节点的binlog内容到replay-log中
    Sql线程负责从replay-log中读取内容 并更新到从节点中
  3. Mysql复制至少需要两个Mysql服务,当然Mysql 服务可以分布在不同服务器上,也可以再同一台服务器上启动多个服务
  4. Mysql主从复制最好保证主节点与从节点的Mysql版本一致,如果不能保证版本一致,那么要保证主节点版本低于从节点版本
  5. 主节点和从节点间时间需要同步

具体步骤:

  1. 从库通过手动执行 change master to 语句连接主库,提供了连接的用户一切条件(user password port ip) 并且让从库知道二进制日志的起点位置(file名 position号); start slave
  2. 从库的I/O线程和主库的dump 线程建立连接
  3. 从库根据change master to语句提供的file名 和 position号,I/O线程向主库发送IO线程
  4. 从库I/O线程接受binlog events 并存入本地replay-log中 传送过来的信息会记录到master.info中
  5. 从库SQL线程应用replay-log,并把应用过的记录到replay-log.info中,默认情况下,已经应用过的replay会自动被清理purge

4、Mysql主从复制形式

  1. 一主一从

  2. 主主复制

  3. 一主多从

  4. 多主一从

  5. 联级复制

5、主从复制安装配置

  1. 两台虚拟机
主节点:192.168.2.125
从节点:192.168.2.126
  1. 创建数据库
-- 主节点  从节点  都要创建
create database hhei;
  1. 主节点配置
vi /etc/my.cnf
#在mysqld模块中添加如下配置信息
log-bin=master-bin #二进制文件名称
binlog-format=ROW  #二进制日志格式,有row、statement、mixed三种格式
-- row指的是把改变的内容复制过去,而不是把命令在从服务器上执行一遍,
-- statement指的是在主服务器上执行的SQL语句,在从服务器上执行同样的语句。
-- MySQL默认采用基于语句的复制,效率比较高。mixed指的是默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
server-id=1           #要求各个服务器的id必须不一样 各个节点是通过server-id来区分彼此
binlog-do-db=hhei#同步的数据库名称
  1. 配置从节点登录主节点账号 授权
mysql -uroot -p  输入密码
执行:
--授权操作
set global validate_password_policy=0;
set global validate_password_length=1;
grant replication slave on *.* to 'root'@'%' identified by '123456';
--刷新权限
flush privileges;
  1. 从节点配置
#修改配置文件,执行以下命令打开mysql配置文件
vi /etc/my.cnf
#在mysqld模块中添加如下配置信息
log-bin=master-bin #二进制文件的名称
binlog-format=ROW  #二进制文件的格式
server-id=2            #服务器的id
  1. 重启主服务器mysqld 服务
service mysqld restart ;-- 进入
mysql -uroot -p123456
-- 执行
show master status;
+-------------------+----------+--------------+-
| File              | Position | Binlog_Do_DB |
+-------------------+----------+--------------+-
| master-bin.000002 |      154 | hhei         |
+-------------------+----------+--------------+-

  1. 重启从服务器 进行相关配置
service mysqld restart-- 登录
mysql -uroot -p123456#连接主服务器 这里的master_log_file master_log_pos 要和上一步执行的show master syatus的输出结构一致
change master to master_host='192.168.2.125',master_user='root',master_password='123456',master_port=3306,master_log_file='master-bin.000002',master_log_pos=154;#启动slave
start slave;#查看slave的状态
show slave status\G(注意没有分号)*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 192.168.2.125Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-bin.000002Read_Master_Log_Pos: 589Relay_Log_File: centosminimal-relay-bin.000004Relay_Log_Pos: 321Relay_Master_Log_File: master-bin.000002Slave_IO_Running: Yes  # 这个必须是YesSlave_SQL_Running: Yes #这个也必须是YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 589Relay_Log_Space: 536Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 48ca9699-866b-11ea-aaef-000c2972c314Master_Info_File: /var/lib/mysql/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 

如果 Slave_IO_Running Slave_SQL_Running 不是yes可以考虑是不是防火墙没有关闭
我操作关闭了主节点和从节点的防火墙 service iptables stop
7、此时可以在主服务器进行相关的数据添加删除工作,在从服务器看相关的状态

主节点:
--切换数据库use hhei;
-- 创建表
CREATE TABLE `tt` (`id` bigint(20) NOT NULL,`name` varchar(255) DEFAULT NULL);
-- 插入数据
insert into  tt values (1,'a'),(2,'bb');从节点:
-- 切换数据库
use hhei
--查看数据select * from tt;+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | bb   |
+----+------+

5、Mysql主从同步延时分析

  • mysql的主从复制都是单线程操作,主库对所有的DDL和DML产生的日志写进binlog,
  • 由于binlog是顺序写的,所以效率很高
  • slave的sql thread 将主库的DDL DML 操作事件在slave中重放,DML和DDL 的IO 操作是随机的,不是顺序的,所以成本高
  • 由于sql thread 也是单线程的,当主数据库并发较高时,产生的DML 数据量超过slave的SQL thread 所处理的的速度,或者当slave中有大型的query语句产生了等待,那么延时就产生了

解决方案:
mysql5.7之前

  1. 业务的持久化层采用分库架构 mysql服务可以平行扩展 分散压力
  2. 单个库读写分离,一主多从,主写从读,分散压力,这样从库压力比主库高,保护主库
  3. 服务的基础架构业务和数据库之间加缓存降低mysql读压力
  4. 不同业务的mysql物理机放在不同的机器上,分散压力
  5. 使用比主库更好的硬件设备作为从库,mysql压力小,延时自然变小
  6. 使用性能更好的硬件设备

mysql5.7之后 不存在了 MTS enhanced multi-threaded slave 号称解决了延时问题
具体技术没有看

6、读写分离

读写分离介绍:

Mysql读写分离基本原理是让master数据库处理写操作,slave数据库处理读操作
master将写操作变更到各个slave节点

Mysql读写分离提高性能的原因在于 :
(1) 物理服务器增加 机器处理能力提升,拿硬件换性能
(2) 主从只负责各自的读和写 极大程度缓解了共享锁和排它锁争用
(3)slave可以配置myisam引擎 提升查询性能以及节约系统开销
(4)master直接写是并发的,slave通过主库发送过来的binlog恢复数据是异步的
(5)slave可以单独设置一些属性来提升性能
(6)增加冗余 提高可用性

  • Mysql Proxy
    使用比较少
master:192.168.2.125
slave:192.168.2.126
proxy:192.168.2.127
  1. 下载压缩包
官网地址:https://downloads.mysql.com/archives/proxy/#downloadscd /opt
wget https://downloads.mysql.com/archives/get/p/21/file/mysql-proxy-0.8.5-linux-glibc2.3-x86-32bit.tar.gz
  1. 解压
cd /opt
ls
mysql-proxy-0.8.5-linux-glibc2.3-x86-32bit.tar.gz
-- 解压
tar -zxvf mysql-proxy-0.8.5-linux-glibc2.3-x86-32bit.tar.gz
-- 名字太长 重命名一下
mv mysql-proxy-0.8.5-linux-glibc2.3-x86-32bit mysql-proxy
  1. 创建目录
cd /opt/mysql-proxy
mkdir conf
mkdir logs
  1. 添加环境变量
#打开/etc/profile文件
vi /etc/profile
#在文件的最后面添加一下命令
export PATH=$PATH:/opt/mysql-proxy/bin
-- 保存退出
#执行命令让环境变量生效
source /etc/profile

5.创建文件 并添加内容 mysql-proxy.conf

cd /opt/mysql-proxy/conf
vim mysql-proxy.conf
--添加
[mysql-proxy]
user=root
proxy-address=192.168.2.127:4040
proxy-backend-addresses=192.168.2.125:3306
proxy-read-only-backend-addresses=192.168.2.126:3306
proxy-lua-script=/opt/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
log-file=/opt/mysql-proxy/logs/mysql-proxy.log
log-level=debug
daemon=true

给mysql-proxy.conf 660权限

chmod 660 mysql-proxy.conf

6.开启mysql-proxy

 mysql-proxy --defaults-file=/opt/mysql-proxy/conf/mysql-proxy.conf

报错:

/opt/mysql-proxy/bin/mysql-proxy: /opt/mysql-proxy/libexec/mysql-proxy:
/lib/ld-linux.so.2: bad ELF interpreter: 没有那个文件或目录

解决:

 yum install glibc.i686 -y
 mysql-proxy --defaults-file=/opt/mysql-proxy/conf/mysql-proxy.confcd /opt/mysql-proxy/logstail -f -n100 mysql-proxy.log


这个时候可以连接
host:192.168.2.127
port:4040
user:root
password:123456

做实验:
在126(从节点)插入一条数据  在proxy查询发现没有这条数据
停掉125 再查询发现有这条数据了 说明125(主节点) 是既读也写的  但是主节点挂了 从节点还可以接着读
但是主节点挂了 就不能写了 只能读 也就是说如果刚起来 从节点只做数据备份  读&写 还是主节点
  • amoeba
  1. 什么是amoeba
    ​ Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库、可并发请求多台数据库合并结果。

    主要解决:
    • 降低 数据切分带来的复杂多数据库结构
    • 提供切分规则并降低 数据切分规则 给应用带来的影响
    • 降低db 与客户端的连接数
    • 读写分离

  2. 为什么要用Amoeba
    目前要实现mysql的主从读写分离,主要有以下几种方案:
    1、 通过程序实现,网上很多现成的代码,比较复杂,如果添加从服务器要更改多台服务器的代码。
    2、 通过mysql-proxy来实现,由于mysql-proxy的主从读写分离是通过lua脚本来实现,目前lua的脚本的开发跟不上节奏,而写没有完美的现成的脚本,因此导致用于生产环境的话风险比较大,据网上很多人说mysql-proxy的性能不高。
    3、 自己开发接口实现,这种方案门槛高,开发成本高,不是一般的小公司能承担得起。
    4、 利用阿里巴巴的开源项目Amoeba来实现,具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库,并且安装配置非常简单。
    3.amoeba安装

1、首先安装jdk,直接使用rpm包安装即可
2、下载amoeba对应的版本https://sourceforge.net/projects/amoeba/,直接解压即可
yum install zip unzip
unzip amoeba-mysql-3.0.5-RC-distribution.zip 

3、配置amoeba的配置文件

cd /opt/amoeba-mysql-3.0.5-RC/conf
vim dbServers.xml
删除所有内容(d+G(大写G)) 复制下边内容到文件中

dbServers.xml

<?xml version="1.0" encoding="gbk"?><!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/"><!--abstractServer 名字随便起 下边会用 --><dbServer name="abstractServer" abstractive="true"><factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory"><property name="connectionManager">${defaultManager}</property><property name="sendBufferSize">64</property><property name="receiveBufferSize">128</property><!-- mysql port --><property name="port">3306</property><!-- mysql schema --><property name="schema">hhei</property><!-- mysql user --><property name="user">root</property><property name="password">123456</property></factoryConfig><poolConfig class="com.meidusa.toolkit.common.poolable.PoolableObjectPool"><property name="maxActive">500</property><property name="maxIdle">500</property><property name="minIdle">1</property><property name="minEvictableIdleTimeMillis">600000</property><property name="timeBetweenEvictionRunsMillis">600000</property><property name="testOnBorrow">true</property><property name="testOnReturn">true</property><property name="testWhileIdle">true</property></poolConfig></dbServer><!--parent 会继承abstractServer的所有属性 writedb也是随便写的名字 后边配置文件会用 --><dbServer name="writedb"  parent="abstractServer"><factoryConfig><!-- mysql ip  --><property name="ipAddress">192.168.2.125</property></factoryConfig></dbServer><!--parent 会继承abstractServer的所有属性 slave也是随便写的名字 后边配置文件会用 --><dbServer name="slave"  parent="abstractServer"><factoryConfig><!-- mysql ip --><property name="ipAddress">192.168.2.126</property></factoryConfig></dbServer><!-- 配置节点属性 这个 myslave会在下边配置成读节点 --><dbServer name="myslave" virtual="true"><poolConfig class="com.meidusa.amoeba.server.MultipleServerPool"><!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA--><property name="loadbalance">1</property><!----><property name="poolNames">slave</property></poolConfig></dbServer>
</amoeba:dbServers>

amoeba.xml

cd /opt/amoeba-mysql-3.0.5-RC/conf
vim amoeba.xml
删除所有内容(d+G(大写G)) 复制下边内容到文件中
<?xml version="1.0" encoding="gbk"?><!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/"><proxy><service name="Amoeba for Mysql" class="com.meidusa.amoeba.mysql.server.MySQLService"><!-- port --><property name="port">8066</property><property name="connectionFactory"><bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory"><property name="sendBufferSize">128</property><property name="receiveBufferSize">64</property></bean></property><property name="authenticateProvider"><bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator"><property name="user">root</property><property name="password">123456</property><property name="filter"><bean class="com.meidusa.toolkit.net.authenticate.server.IPAccessController"><property name="ipFile">${amoeba.home}/conf/access_list.conf</property></bean></property></bean></property></service><runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext"><!-- proxy server client process thread size --><property name="executeThreadSize">128</property><!-- per connection cache prepared statement size  --><property name="statementCacheSize">500</property><!-- default charset --><property name="serverCharset">utf8</property><!-- query timeout( default: 60 second , TimeUnit:second) --><property name="queryTimeout">60</property></runtime></proxy><!-- Each ConnectionManager will start as threadmanager responsible for the Connection IO read , Death Detection--><connectionManagerList><connectionManager name="defaultManager" class="com.meidusa.toolkit.net.MultiConnectionManagerWrapper"><property name="subManagerClassName">com.meidusa.toolkit.net.AuthingableConnectionManager</property></connectionManager></connectionManagerList><!-- default using file loader --><dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader"><property name="configFile">${amoeba.home}/conf/dbServers.xml</property></dbServerLoader><queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter"><property name="ruleLoader"><bean class="com.meidusa.amoeba.route.TableRuleFileLoader"><property name="ruleFile">${amoeba.home}/conf/rule.xml</property><property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property></bean></property><property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property><property name="LRUMapSize">1500</property><property name="defaultPool">writedb</property><!--写节点--><property name="writePool">writedb</property><!--读节点--><property name="readPool">myslave</property><property name="needParse">true</property></queryRouter>
</amoeba:configuration>

启动

cd /opt/amoeba-mysql-3.0.5-RC/bin
./launcher
报错:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=16m; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=96m; support was removed in 8.0The stack size specified is too small, Specify at least 228k (至少228)解决:
cd /opt/amoeba-mysql-3.0.5-RC
vim jvm.properties
修改-Xss265k
JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss265k -XX:PermSize=16m -XX:MaxPermSize=96m"

安装成功 测试

连接:
mysql -h192.168.2.127 -uroot -p123456  -P8066
开始为所欲为: 在这里 写会走master 读会走slave 测试方式:
查询 数据来自slave(可以提前在slave库上新增几条与master不一样数据)
新增数据是走的master(关闭master就不能新增了)这个是真正的 master写   slave读

Mycat

Mycat数据库分库分表中间件
活跃的、性能好的开源数据库中间件!
http://www.mycat.org.cn/

后续再写Mycat使用方式

mysql优化 个人笔记 (mysql 主从复制 ) 非礼勿扰 -m11相关推荐

  1. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m14

    查询优化 1. 查询慢的可能原因 网络 CPU (时间片) IO (磁盘) 上下文切换 (线程切换) 系统调用 生成统计信息 锁等待时间 2. 优化数据访问 查询性能低的主要原因是访问的数据太多,某些 ...

  2. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m15

    一. limit 1. 测试案例 -- 创建表 ![在这里插入图片描述](https://img-blog.csdnimg.cn/cover1/248667912046641316.jpg?x-oss ...

  3. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m13

    接上一篇 一.union all .in .or -- 还是老朋友 dd DROP TABLE IF EXISTS `dd`; CREATE TABLE `dd` (`d1` varchar(255) ...

  4. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m12

    索引优点 减少服务器需要扫描的数据量 帮助服务器避免排序和临时表 将随机IO编程顺序IO 应用场景 快速匹配where字句的行 从consideration中消除行,如果可以在多个索引之间进行选择,m ...

  5. mysql优化 个人笔记 (mysql锁机制 ) 非礼勿扰 -m10

    锁机制 A : undolog 实现 C : I :锁实现 D :redolog实现 1. mysql锁基本介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制 在数据库中 除了传统的计算机资源( ...

  6. mysql数据库优化课程---15、mysql优化步骤(mysql中最常用最立竿见影的优化是什么)...

    mysql数据库优化课程---15.mysql优化步骤(mysql中最常用最立竿见影的优化是什么) 一.总结 一句话总结:索引优化最立竿见影 索引优化:不然有多少行要扫描多少次,1亿行大概是5到10分 ...

  7. Mysql 优化(学习笔记二十)

    https://blog.csdn.net/steven_liwen/article/details/53188411 运维角度mysql优化:https://www.cnblogs.com/shen ...

  8. mysql 优化_常用MySQL优化

    1.大批量插入数据优化 (1)对于MyISAM存储引擎的表,可以使用:DISABLE KEYS 和 ENABLE KEYS 用来打开或者关闭 MyISAM 表非唯一索引的更新. ALTER TABLE ...

  9. 关于mysql优化_MYSQL---关于MYSQL优化

    1. 慢查询,规定查询超过2秒的为慢查询(救火) 1)mysql> show full processlist; 2)用explain查看查询语句是否经过索引,如果没有就要建立索引 long_q ...

最新文章

  1. 0基础学python难吗-零基础入门学习Python技术难不难?
  2. 搭建Docker环境---私有仓库registry搭建
  3. Vue + Element UI——滚动条el-scrollerbar和无限滚动指令v-infinite-scroll整合解决方案
  4. 手写自己的MyBatis框架-MapperProxy
  5. ZooKeeper的安装与部署
  6. C++ 的几个for 循环,范围for语句
  7. rm linux 复制目录,linux学习(四)复制(cp)移动(mv)删除(rm)查找(find)文件、文件夹操作、软硬链接的区别...
  8. 六元均匀直线阵的各元间距为_小间距led显示屏的封装方式有哪些?本文带你了解!...
  9. 有哪些讽刺性极强的文案?
  10. 走进我的交易室01_引子
  11. oracle ora 16014,ORA-16014 ORA-00312错误解决
  12. MapReduce框架Hadoop应用(一)
  13. 经典图像分割方法总结
  14. 弱电工程施工规划实施
  15. Exadata一体机故障回顾
  16. 西安交大计算机2000年山西专业录取分数,西安交通大学分数线-2017年各省各专业录取分数线(历年分数线查询)...
  17. 前端之CSS篇(一)——CSS入门及基础选择器和字体文本属性
  18. php ip138获取,php通过调用ip138数据库获取IP及网络类型
  19. MIT molecular Biology 笔记11 位点特异性重组 和 DNA转座
  20. 微信小程序基础(一) 文件结构配置项

热门文章

  1. ​Spring Cloud中统一异常处理是怎么做的?
  2. 数学建模----LaTex排版使用速成
  3. 【火炉炼AI】机器学习023-使用层次聚类算法构建模型
  4. 机动战士高达观影顺序
  5. commit节点号 git_Git调整commit之间顺序
  6. 深度学习的hand-crafted和end-to-end的一些概念和区别
  7. OpenDaylight是什么?
  8. 烟沙浮生 | 曾几何时,还是游吟长安的醉客 1
  9. 读《470个建筑设计创意发想》
  10. 极米H5值得入手吗?极米H5实际体验如何?画面对比实测