分类 Java 下的文章

MiB和MB,KiB和KB等的区别

MiB和MB,KiB和KB等的区别:

1KB(kilobyte)=1000byte,    1KiB(kibibyte)=1024byte
1MB(megabyte)=1000000byte, 1MiB(mebibyte)=1048576byte

硬盘生产商是以GB(十进制,即10的3次方=1000,如1MB=1000KB)计算的,而电脑(操作系统)是以GiB(2进制,即2的10次方,如1MiB=1024KiB)计算的,但竖内用户一般理解为1MB=1024KB, 所以为了便于中文化的理解,翻译MiB为MB也是可以的。
同样根据硬盘厂商与用户对于1MB大小的不同理解,所以好多160G的硬盘实际容量按计算机实际的1MB=1024KB算都不到160G,这也可以解释为什么新买的硬盘“缺斤短两”并没有它所标示的那么大。

宽带网络中,运营商们所说的1M带宽是指1Mbps(megabits per second,兆比特每秒)。bps是bit per Second的缩写,也就是每秒多少“位”(bit)的意思。是用来计算资料传输速率的单“位”。举例来说,电信局通常说的1M的宽,所使用的单位就是bps,我们都知道一个字节等于8位,而我们电脑的存储单位使用的是字节,也就是理论上每秒可以向硬盘下载1X1024/8=128KB/sec的数据。但这也只是理论上的速度。实际上则要再扣约12%的数据头信息(包Ethernet Header,IP Header,TCP Header,ATM Header等),各种各样的控制讯号。所以传输速度上限应112KB/sec左右,而不应该望文生义地理解为“每秒钟可以传送1M字节的数据。所以千万不要迷信广告,传输单位的写法上,B和b分别代表Bytes和bits,两者定义不同,差距是8倍

html元素代码原样显示,而不解析为dom结构

碰到的问题:
title中存在html代码,在浏览器中会被直接解析成为dom元素,希望是原样显示code才行;

转码修改前

转码修改前


转码修改后

转码修改后


实现方法:

//html元素原样显示,而不解析为dom结构
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
 }

JS调用:

var title = Base64.decode(video.title);
title = escapeHtml(title);
if(title.length > 24){
   title = title.substring(0,10);
}

http://stackoverflow.com/questions/6234773/can-i-escape-html-special-chars-in-javascript

Java源代码阅读

1、技术基础
在阅读源码之前,我们要有一定程度的技术基础的支持。
假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃《Core Java》,那样是很难有收获的,尤其是《深入Java虚拟机》这类书,或许别人觉得好,但是未必适合现在的你。
比如设计模式,许多Java源码当中都会涉及到。再比如阅读Spring源码的时候,势必要先对IOC,AOP,Java动态代理等知识点有所了解。
2、强烈的求知欲
强烈的求知欲是阅读源码的核心动力!
大多数程序员的学习态度分为如下几个层次:
完成自己的项目就可以了,遇到不懂的地方就百度一下。
不仅做好项目,还会去阅读一些和项目有关的书籍。
除了阅读和项目相关的书籍之外,还会阅读一些IT行业相关的书籍。
平时会经常逛逛GitHub,找一些开源项目看看。
阅读基础框架、J2EE规范、源码。
大多数程序员的层次都是在第一层,到第五层的人就需要有强烈的求知欲了。
3、足够的耐心
通过阅读源码我们可以学习大佬的设计思路,技巧。还可以把我们一些零碎的知识点整合起来,从而融会贯通。总之阅读源码的好处多多,想必大家也清楚。
但是真的把那么庞大复杂的代码放到你的眼前时,肯定会在阅读的过程中卡住,就如同陷入了一个巨大的迷宫,如果想要在这个巨大的迷宫中找到一条出路,那就需要把整个迷宫的整体结构弄清楚,比如:API结构、框架的设计图。而且还有理解它的核心思想,确实很不容易。
刚开始阅读源码的时候肯定会很痛苦,所以,没有足够的耐心是万万不行的。
如何读Java源码:
团长也是经历过阅读源码种种痛苦的人,算是有一些成功的经验吧,今天来给大家分享一下。
如果你已经有了一年左右的Java开发经验的话,那么你就有阅读Java源码的技术基础了。
1、建议从JDK源码开始读起,这个直接和eclipse集成,不需要任何配置。
可以从JDK的工具包开始,也就是我们学的《数据结构和算法》Java版,如List接口和ArrayList、LinkedList实现,HashMap和TreeMap等。这些数据结构里也涉及到排序等算法,一举两得。
面试时,考官总喜欢问ArrayList和Vector的区别,你花10分钟读读源码,估计一辈子都忘不了。
然后是core包,也就是String、StringBuffer等。 如果你有一定的Java IO基础,那么不妨读读FileReader等类。
建议大家看看《Java In A Nutshell》,里面有整个Java IO的架构图。Java IO类库,如果不理解其各接口和继承关系,则阅读始终是一头雾水。
Java IO 包,我认为是对继承和接口运用得最优雅的案例。如果你将来做架构师,你一定会经常和它打交道,如项目中部署和配置相关的核心类开发。
读这些源码时,只需要读懂一些核心类即可,如和ArrayList类似的二三十个类,对于每一个类,也不一定要每个方法都读懂。像String有些方法已经到虚拟机层了(native方法),如hashCode方法。
当然,如果有兴趣,可以对照看看JRockit的源码,同一套API,两种实现,很有意思的。
如果你再想钻的话,不妨看看针对虚拟机的那套代码,如System ClassLoader的原理,它不在JDK包里,JDK是基于它的。JDK的源码Zip包只有10来M,它像是有50来M,Sun公司有下载的,不过很隐秘。我曾经为自己找到、读过它很兴奋了一阵。
2、Java Web项目源码阅读
步骤:表结构 → web.xml → mvc → db → spring ioc → log→ 代码
① 先了解项目数据库的表结构,这个方面是最容易忘记的,有时候我们只顾着看每一个方法是怎么进行的,却没有去了解数据库之间的主外键关联。其实如果先了解数据库表结构,再去看一个方法的实现会更加容易。
② 然后需要过一遍web.xml,知道项目中用到了什么拦截器,监听器,过滤器,拥有哪些配置文件。如果是拦截器,一般负责过滤请求,进行AOP等;如果是监听器,可能是定时任务,初始化任务;配置文件有如 使用了spring后的读取mvc相关,db相关,service相关,aop相关的文件。
③ 查看拦截器,监听器代码,知道拦截了什么请求,这个类完成了怎样的工作。有的人就是因为缺少了这一步,自己写了一个action,配置文件也没有写错,但是却怎么调试也无法进入这个action,直到别人告诉他,请求被拦截了。
④ 接下来,看配置文件,首先一定是mvc相关的,如springmvc中,要请求哪些请求是静态资源,使用了哪些view策略,controller注解放在哪个包下等。然后是db相关配置文件,看使用了什么数据库,使用了什么orm框架,是否开启了二级缓存,使用哪种产品作为二级缓存,事务管理的处理,需要扫描的实体类放在什么位置。最后是spring核心的ioc功能相关的配置文件,知道接口与具体类的注入大致是怎样的。当然还有一些如apectj等的配置文件,也是在这个步骤中完成。
⑤ log相关文件,日志的各个级别是如何处理的,在哪些地方使用了log记录日志。
⑥ 从上面几点后知道了整个开源项目的整体框架,阅读每个方法就不再那么难了。
⑦ 当然如果有项目配套的开发文档也是要阅读的。
3、Java框架源码阅读
当然了,就是Spring、MyBatis这类框架。
在读Spring源码前,一定要先看看《J2EE Design and Development》这本书,它是Spring的设计思路。注意,不是中文版,中文版完全被糟蹋了。
想要阅读MyBatis的源码就要先了解它的一些概念,否则云里来雾里去的什么也不懂。有很多人会选择去买一些书籍来帮助阅读,当然这是可取的。那么如果不想的话,就可以去官网查看它的介绍(MyBatis网站:http://www.mybatis.org/mybatis-3/zh/getting-started.html),团长也是按照官网上面的介绍来进行源码阅读的。团长认为MyBatis的亮点就是管理SQL语句。
总结
没有人一开始就可以看得懂那些源码,我们都是从0开始的,而且没有什么捷径可寻,无非就是看我们谁愿意花时间去研究,谁的求知欲更强烈,谁更有耐心。阅读源码的过程中我们的能力肯定会提升,可以从中学到很多东西。在我们做项目的时候就会体现出来了,的确会比以前顺手很多。
原文:https://blog.csdn.net/fygu18/article/details/81295187

利用iframe解决跨域问题

利用iframe解决跨域问题

iframe跨域

iframe跨域


该图要解决的问题说明如下:
在AAA.com域名下的index.htm页面中内嵌了BBB.com域名下的一个页面index.htm,正常情况下iframe内部的index.htm页面是无法访问父页面index.htm中的任何dom对象或者js函数的,因为跨域,但我们经常又需要做一些参数回传的事情怎么办呢?以上的这种实现方式就很好的解决了这个问题;
解决方案的关键优雅之处在于:浏览器虽然会禁止js跨域访问页面中的对象,但对于iframe的层级关系引用并没有做限制,即parent仍然可用;该方案就是利用了2层内嵌iframe、使用第二级iframe中的页面与parent.parent的页面是同域名的关系,从而避免跨域问题实现两个页面间相关数据的传递,本质上就是利用parent.parent实现对父父页面中js的回调!
A域下的页面 enter.jsp

<script type="text/javascript" src="<%=basePath%>userindex/js/ui/jquery.js"></script>
<script type="text/javascript">
function process(par){
	//种cookie
	var strs = par.split("="); //字符分割
	setCookie("cookiename",strs[1],'d30');
}
//程序代码
function setCookie(name,value,time)
{
    var strsec = getsec(time);
    var exp = new Date();
    exp.setTime(exp.getTime() + strsec*1);
    document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString()+";path=/;domain=youku.com";
}
function getsec(str)
{
   var str1=str.substring(1,str.length)*1;
   var str2=str.substring(0,1);
   if (str2=="s")
   {
        return str1*1000;
   }
   else if (str2=="h")
   {
       return str1*60*60*1000;
   }
   else if (str2=="d")
   {
       return str1*24*60*60*1000;
   }
}
</script>
<iframe id="aframe" src="http://www.BBB.com/getCookie.jsp" width="320" height="240"></iframe>

B域下的页面:getCookie.jsp

<script type="text/javascript" language="javascript">
	function getCookie(c_name){
		if(document.cookie.length>0){
		   c_start=document.cookie.indexOf(c_name + "=");
		   if(c_start!=-1){
		     c_start=c_start + c_name.length+1;
		     c_end=document.cookie.indexOf(";",c_start);
		     if(c_end==-1) c_end=document.cookie.length;
		     //alert(unescape(document.cookie.substring(c_start,c_end)));
		     return unescape(document.cookie.substring(c_start,c_end));
		   }
		}
	}
	(function(){
		 //动态创建iframe,利用iframe的src传递cookie值
		 var ifr = document.createElement("IFRAME");
		 document.body.appendChild(ifr);
		 ifr.src = 'http://www.AAA.com/pass.jsp?p='+getCookie("yktk");
	})();
</script>

A域下的页面:pass.jsp

<script type="text/javascript" src="<%=basePath%>userindex/js/ui/jquery.js"></script>
<script type="text/javascript">
(function(){
	//获取iframe的src中的参数
	var paramUrl = window.location.search;
	//调用iframe中的A域中的process方法,把参数传入,完成跨域
	parent.parent.process(paramUrl);
})();
</script>

参考资料: http://blog.csdn.net/sfdev/article/details/5807045

cookie和session的区别

这些都是基础知识,不过有必要做深入了解。先简单介绍一下。
二者的定义:
当你在浏览网站的时候,WEB服务器会先送一小小资料放在你的计算机上,Cookie会帮你在网站上所打的文字或是一些选择,都纪录下来。当下次你再光临同一个网站,WEB服务器会先看看有没有它上次留下的Cookie资料,有的话,就会依据Cookie里的内容来判断使用者,送出特定的网页内容给你。Cookie的使用很普遍,许多有提供个人化服务的网站,都是利用Cookie来辨认使用者,以方便送出使用者量身定做的内容,像是Web接口的免费email网站,都要用到Cookie。
具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择
cookie机制。正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。
cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。
session机制。
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。
但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:

<form name="testform" action="/xxx">;
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"/>;
<input type="text"/>;
</form>;

实际上这种技术可以简单的用对action应用URL重写来代替。
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
转自:http://www.cnblogs.com/shiyangxt/archive/2008/10/07/1305506.html

Jackson和json-lib效率比较

Jackson 和 json-lib
这两个json工具转换json的效率差的不是一点半点的,Jackson转换9万条json的字符串基本上在毫秒级完成,而同样的字符串解析json-lib则需要400多秒;
所以Jackson适合解析大量数据;json-lib并不是一点优点都没有,在web系统中传递的数据都是“小数据”,使用json-lib方便在字符串和json之间转换;

利用redis的Sorted Set实现分页

redis命令:

ZADD key score member [[score member] [score member] ...]
ZRANGE key start stop [WITHSCORES]

练习下redis ZADD ZRANGE命令:

redis&gt; ZADD myzset 1 "one"
(integer) 1redis&gt; ZADD myzset 2 "two"
(integer) 1redis&gt; ZADD myzset 3 "three"
(integer) 1redis&gt; ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"redis&gt; ZRANGE myzset 2 3
1) "three"redis&gt; ZRANGE myzset -2 -1
1) "two"
2) "three"redis&gt;

如果明白了 这两个命令的含义,实际上分页的原理就已经弄明白了。
现在的场景是:
要进行分页的数据是以json的格式写在hdfs上的,每条记录中有createtime这个字段(2013-02-19 01:23:50),将其变成10位的时间戳,把时间戳作为score,就可以按照时间从早到晚来排列,start stop参数决定着分页的大小!
java客户端jedis对应的方法:
读取:

Set set = jedis.zrange("tv-videos_102599699", 0, 9);
for (Object str : set) {
     System.out.println(str);
}

返回的是有序的LinkedHashSet,而不是hashset
批量写入,而不是单条写入:

Pipeline pipeline = RedisCon.getJeidsConForPipLine();//getJeidsConForPipLine自定义函数
pipeline.zadd("tv-videos_"+key.toString(), Long.parseLong(str), jsonArray.getString(i));
pipeline.sync();

其他命令参考:http://www.redis.cn/commands/zrange.html

Java Thread State 相关术语

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。
一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程状态有:
1.死锁,Deadlock(重点关注)
2.执行中,Runnable
3.等待资源,Waiting on condition(重点关注)
4.等待获取监视器,Waiting on monitor entry(重点关注)
5.暂停,Suspended
6.对象等待中,Object.wait() 或 TIMED_WAITING
7.阻塞,Blocked(重点关注)
8.停止,Parked
Deadlock:死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。
Runnable:一般指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能正在传递SQL到数据库执行,有可能在对某个文件操作,有可能进行数据类型等转换
Waiting on condition:等待资源,或等待某个条件的发生。具体原因需结合 stacktrace来分析。
如果堆栈信息明确是应用代码,则证明该线程正在等待资源。一般是大量读取某资源,且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取。
又或者,正在等待其他线程的执行等。
如果发现有大量的线程都在处在 Wait on condition,从线程 stack看,正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。
一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;
另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。
 
Blocked:线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。
Waiting for monitor entry 和 in Object.wait():Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图1中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。
 

数据库sharding(scale up to scale out)

sharding是将一个大数据库按照一定规则拆分成多个小数据库的一门技术.
当我们的应用数据量越来越多,访问量越来越大的时候,我们会作何选择?继续提升数据库服务器的性能还是采用一项技术让数据库平滑扩展?虽然伴随着服务器的更新换代,性能越来越好,更换更加豪华的服务器能暂时解决这个问题,但是无论是从花费和可控都无法让人满意。这时数据库sharding是一个更加可行的方案。
常用的sharding方案有以下几种,
1。按功能划分(垂直切分)
将不同功能相关的表放到不同的数据库中,譬如将用户管理相关表放到shard 1上,将blog相关表放到shard 2上。。。这样做的好处是非常直观,当需要用户列表时,我就到shard 1上获取。。。。这样也有一个问题,当某一部分的功能其数据量或性能要求超出了可控的范围,我们就需要继续对其进行深入的sharding。
2。按表中某一字段值的范围划分(水平切分)
当伴随着某一个表的数据量越来越大,以至于不能承受的时候,就需要对她进行进一步的切分。一种选择是根据key的范围来做切分,譬如userID为1-10000的放到shard 10上,userID为10000到20000的放到shanrd 11上。。。这样的扩展就是可预见的。另一种是根据某一字段值得来划分,譬如根据用户名的首字母,如果是a-d,就属于shard 20,e-h就属于shard 21。。。这样做也存在不均衡性,当某个范围超出了shard所能承受的范围就需要继续切分。还有按日期切分等等,
3。基于hash的切分
类似于memcached的key hash算法,一开始确定切分数据库的个数,通过hash取模来决定使用哪台shard。这种方法能够平均的来分配数据,但是伴随着数据量的增大,需要进行扩展的时候,这种方式无法做到在线扩容。每增加节点的时候,就需要对hash算法重新运算,数据需要重新割接。
4。基于路由表的切分
前面的几种方式都是跟据应用的数据来决定操作的shard,基于路由表的切分是一种更加松散的方法。它单独维护一张路由表,根据用户的某一属性来查找路由表决定使用哪个shard,这种方式是一种更加通用的方案。譬如我们在系统中维护一张表-(用户所属省-〉shard),这样每个用户我们知道是哪个省的,去路由表查找,就知道它所在的shard。因为每次数据操作的时候都需要进行路由的查找,所以将这些内容存储到一台独立cache上是一个非常好的方式,譬如memcached。这种切分的方式同时也带来了另一个好处,当需要增加shard的时候,可以在不影响在线应用的情况下来执行,当然这也跟应用程序的架构设计相关,你的设计必须适用这种增加。
虽然应用sharding会带来显而易见的好处,但是它也有一些固有的问题需要我们了解,这些问题大致分成以下几类,
1。shard的扩容
当当前的shard已经不能适用当前的应用需求时,就需要对shard数据库进行扩容,增加shard意味着需要对原有的shard数据进行迁移,这个过程是非常复杂,而且可能会导致数据的不一致(一边写、一边迁移)或者其他应用问题,因此扩容一般选择在凌晨等时间进行。
2。联合多个shard的表数据查询
这个是shard固有的问题,当遇到这样的问题时,你需要获取各个shard的数据,然后对这些数据进行汇总,很多时候因为现在的网络速度比较发达这个问题可以几乎被忽略掉。但是如果要进行数据的分析或挖掘,shard就会存在问题,通常面对这种对于数据要求不是那么实时的情况下,可以采用将shard数据同步到汇总数据库的方案,olap可以在这台汇总数据库上进行,这就需要在每台shard上进行数据的定时同步,这增加了程序的复杂性;如果要求实时的情况下,采用sharding方案会是一个毁灭性打击。
3。其他
我们现在做的系统就是采用的按照路由表切分的sharding方案,而且我们需要要求不是那么实时的汇总数据以提供数据的分析和挖掘,同时我们的基础数据都是在汇总数据库中进行管理,通过oracle的高级复制到shard节点上。在shard数据库向汇总数据库同步数据的时候,我们是通过oracle数据库的存储过程实现的,这种架构方式导致了数据库非常的复杂,同时还存在了一些其他问题,譬如同步会无缘无故的断掉。。。这就需要采用一些其他手段来维持数据的延迟一致性。
我们的sharding还在改进,我们的shard还在增加,我们还需要不断努力使我们的应用更加高效。
有时候觉得我们的社会就像一个巨大的多层sharding方案,中央、省(自治区)、市。。。
————————————————————-
还有一种数据库方案是master-slave,一台master主要负责数据的更新,然后通过高级复制等手段将数据复制到各个slave节点,slave节点负责查询。这种结构是不管master和slave都拥有全部的数据,master到slave的数据存在一定的延迟。可以跟sharding方案结合使用。
http://eddysheng.iteye.com/blog/461393