12月29
一、所有库在同一节点上
当业务垂直拆分出很多业务库的时候,如果都部署在同一个源上(同一个机器节点上),那么这种情况是最好办的,直接库名+表名 join就可以。
二、不在一个节点
当不同的库来自不同的节点,那么就没办法直接join查询了,有以下方式和思路:
1.全局表
所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份。同时,这类数据通常也很少发生修改(甚至几乎不会),
所以也不用太担心“一致性”问 题。
2.字段冗余
这是一种典型的反范式设计,在互联网行业中比较常见,通常是为了性能来避免join查询。字段冗余能带来便利,是一种“空间换时间”的体现。但其适用场景也比较有限,比较适合依赖字段较少的情况。
最复杂的还是数据一致性问题,这点很难保证,可以借助数据库中的触发器或者在业务代码层面去保证。当然,也需要结合实际业务场景来看一致性的要求。
3.数据同步
定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步。当然,同步本来会对数据库带来一定的影响,需要性能影响和数据时效性中取得一个平衡。这样来避免复杂的跨库查询。笔者曾经在项目中是通过ETL工具来实施的。
4.第三方插件
1.cobar
2.MyCAT
3.shardding-jdbc
当业务垂直拆分出很多业务库的时候,如果都部署在同一个源上(同一个机器节点上),那么这种情况是最好办的,直接库名+表名 join就可以。
二、不在一个节点
当不同的库来自不同的节点,那么就没办法直接join查询了,有以下方式和思路:
1.全局表
所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份。同时,这类数据通常也很少发生修改(甚至几乎不会),
所以也不用太担心“一致性”问 题。
2.字段冗余
这是一种典型的反范式设计,在互联网行业中比较常见,通常是为了性能来避免join查询。字段冗余能带来便利,是一种“空间换时间”的体现。但其适用场景也比较有限,比较适合依赖字段较少的情况。
最复杂的还是数据一致性问题,这点很难保证,可以借助数据库中的触发器或者在业务代码层面去保证。当然,也需要结合实际业务场景来看一致性的要求。
3.数据同步
定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步。当然,同步本来会对数据库带来一定的影响,需要性能影响和数据时效性中取得一个平衡。这样来避免复杂的跨库查询。笔者曾经在项目中是通过ETL工具来实施的。
4.第三方插件
1.cobar
2.MyCAT
3.shardding-jdbc
12月29
最近在做项目时有一个这样需求,上传文件需要显示预览,当我了解之后,我以为和普通的下载一样呢,结果后台返回的是文件流格式,据说这是因为后台是分布式部署,不能持久化存储,没办法,只能前端来处理这个文件流了,用ajax请求图片资源,服务器以文件流的形式返回。
1、返回类型需要设置为“blob”,所以需要用原生ajax,不能使用jq(原因:jquery将返回的数据转换为了string,不支持blob类型)(当然,你也可以引入组件拓展jq的能力,我知道的有一个:jquery-ajax-blob-arraybuffer.js);
2、使用FileReader将文件流转换成base64格式;
3.1、然后通过模拟点击a标签下载该文件;
3.2、或者可以设置在img元素的src属性上,在当前页面显示出来。
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = 'data.xlsx';
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
}
};
// 发送ajax请求
xhr.send()
xhr.open('POST', CONTACT_ACTION_FILES_DOWNLOAD, true);
xhr.setRequestHeader("Accept", "application/json;q=0.5");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function () {
$("#imgTest").attr("src", reader.result);
}
}
};
// 发送ajax请求
xhr.send("filePath=" + filePath);
下载文件
export const downloadStream = (method = 'GET', url, downloadName) => {
const ctoken = getCookie('AIB_TOKEN')
if (ctoken) {
let xmlResquest = new XMLHttpRequest();
xmlResquest.open(method, url, true);
xmlResquest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
//这里需要在请求头添加该参数,已防止CSRF
xmlResquest.setRequestHeader("csrfToken", hashStr(ctoken));
xmlResquest.responseType = "blob";
xmlResquest.onload = function (oEvent) {
let content = xmlResquest.response;
let elink = document.createElement('a');
elink.download = downloadName;
elink.style.display = 'none';
let blob = new Blob([content]);
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
xmlResquest.send();
}
}
1、返回类型需要设置为“blob”,所以需要用原生ajax,不能使用jq(原因:jquery将返回的数据转换为了string,不支持blob类型)(当然,你也可以引入组件拓展jq的能力,我知道的有一个:jquery-ajax-blob-arraybuffer.js);
2、使用FileReader将文件流转换成base64格式;
3.1、然后通过模拟点击a标签下载该文件;
3.2、或者可以设置在img元素的src属性上,在当前页面显示出来。
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = 'data.xlsx';
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
}
};
// 发送ajax请求
xhr.send()
xhr.open('POST', CONTACT_ACTION_FILES_DOWNLOAD, true);
xhr.setRequestHeader("Accept", "application/json;q=0.5");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function () {
$("#imgTest").attr("src", reader.result);
}
}
};
// 发送ajax请求
xhr.send("filePath=" + filePath);
下载文件
export const downloadStream = (method = 'GET', url, downloadName) => {
const ctoken = getCookie('AIB_TOKEN')
if (ctoken) {
let xmlResquest = new XMLHttpRequest();
xmlResquest.open(method, url, true);
xmlResquest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
//这里需要在请求头添加该参数,已防止CSRF
xmlResquest.setRequestHeader("csrfToken", hashStr(ctoken));
xmlResquest.responseType = "blob";
xmlResquest.onload = function (oEvent) {
let content = xmlResquest.response;
let elink = document.createElement('a');
elink.download = downloadName;
elink.style.display = 'none';
let blob = new Blob([content]);
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
xmlResquest.send();
}
}




