解决办法:
Header("Content-type: application/octet-stream");
Header("Content-Disposition: inline; filename=aaa.xlsx");
Header("Pragma:public");
用httpwatch查看,内容实际已经输出了只是无法保存,由此断定和Https协议无关,
firefox也可以执行下载,所以断定是IE本身的机制所限制。
加上第三个header搞定了(前两个是下载文件必须的),跟证书和浏览器都没关系。
由于用户量激增,导致数据量猛增,此架构方案之前大概有2亿5000条数据。在此架构之前FriendFeed也采用普遍的做法,比如,读写分离的Mysql主从数据库,并对数据进行了sharding,读操作之外用memecache缓存。但是对于新特性的推出,还是有很多不方便。比如更改数据库的结构,或者增删索引,在如此大的数据量和访问量下,经常导致长时间锁表,虽然
他们也用过在一台从库上建立或删除索引,完成后,再交换成新主库。但这种做法,错误率很高,DBA维护成本也很高,并不是一个轻量级的解决方案,并且这些只能应对现有的功能,对于新需求,修改表结构或增删索引,也存在同样的问题,所以开发了这款基于关系数据库的结构无关性架构。下面详细介绍下具体实现:
两类数据,主数据primary data和主数据索引,类似MYISAM,把数据和索引分开存储,只不过不是数据库来维护索引,而是人工维护索引。主数据叫做Entity:由两部分组成,id+Body 。其中id是唯一需要的,一个16位的全局id(UUID),Body是用二进制压缩存储的对象属性集合,这些属性对于应用来说是不透明的,这有点类似文档数据库。这样的Entiy结构,是结构无关性的核心,它通过向entity内增加或删除属性来达到改变数据库结构的目的,从而应对需求变动或新功能。entity body,可以相同也可以不同,根据相应的需求或业务逻辑,用sql语句,通过实体索引表,查询得到entity,之后由业务逻辑去处理得到的这个或这些实体数据。
具体举例:假如要查询某个用户发布的所有内容。先要建立实体表,如下:
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;
由于InnoDB按照主键的顺序存储数据,所以用added_id做主键,这样可以保证新增的数据顺序的写入到硬盘上。id采用binary格式压缩(UUID是无序的)。
Entity示例,采用序列化的格式存储,比如JSON结构或Python dictionaries:
{
“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,
}
需要建立用户实体索引表,如下:
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)
(这里有两个对象Index对象和DataStore对象)
//根据实体id查询
entity = datastore.get(binascii.a2b_hex(”71f0c4d2291844cca2df6f486e96e37c”))
//通过索引查询
entities = user_id_index.get_all(datastore, user_id=binascii.a2b_hex(”f48b0440ca0c4f66991c4d5f6a078eaf”))
通过例子可以看出,对于新增数据,首先要转换成entity表所需的格式,存储一份实体记录,然后对于某类需求,为它新建一张索引表格,再插入索引。对于同一条数据,可能被多个业务逻辑使用的情况,应该相应的为每个需求建立索引表格,当业务变动或不再需要时,修改或删除相应索引表格就行。对于已知entity id的情况可以直接通过DataStore查询。
为了保证索引的正确性,friendfeed设计了一种cleaner机制,它按照时间顺序不间断的检查entities表,增加新索引,删除错误的索引。
此架构优点:基于关系数据库的结构无关性数据库持久化解决方案,可以很好的应对新需求和底层结构的改变,数据和索引分开存储,人工维护索引,增加删除索引不影响其他业务逻辑的访问。并且采用专门程序维护索引正确性(The Cleaner:重点优化用于索引维护的程序)
缺点:
表的数量比较大
对存储空间占用大
一张实体表,对于多业务频繁的写入操作,也许会成为性能瓶颈,应该按应用拆分成多entities表结构。
wget ftp://xmlsoft.org/libxml2/libxml2-2.7.3.tar.gz
sudo tar -zxvf libxml2-2.6.28.tar.gz
cd libxml2-2.6.28/
./configure
make
sudo make install
ifconfig lnc0 inet 192.168.1.99 up
id –make a note of your user id and groups. Do this with:
uname — display information about the system
ps -aux | more
sudo rsync -avz –delete -e “ssh -i /root/rsync/mirror-rsync-key” sync@61.243.110.80: