paulwong

#

铁路的售票系统来说明分库分表对架构的影响

一、问题:铁路的售票系统的数据量是海量吗?

不是。因为数据量不大,真不大。

每一个车次与车次间是独立的,每车次不超过2000张票,一天发车不超过50万车次;
以预售期15天来讲,15*0.1亿张不超过1.5亿笔的热线数据,称不上海量数据的。
再加上可以按线路分库,更是不到千万级的单表容量。已经发车完成的进入归档分析。
即数据库按路线使用不同的服务器,不同的车次放在不同的表中。并发量锁真不大。

当然,如果不分库分表,再加上不归档处理,铁路的售票系统的数据量看起来是海量的;
关键是这海量的数据没有意义。


二、如何分库分表?

2.1 分库,考虑数据间没有直接关系和服务器如何部署

铁路的售票系统为例来说,按路线分库,再按车次分表是合理的。
设路线有1万条,按每1000条需要两台服务器(一台热机沉余),不到20台服务器
如果使用SAN存储,则使用SAN作为存储,本机作为热机沉余,只需要10台。
当然使用mySQL这种经济型数据库,服务器需要更多来防灾;
即可以采用双写或多写的方式来保证数据的绝对安全。

2.2分表,考虑数据间不存在重叠,即数据满足二分原则

铁路的售票系统的任意两个车次是没有关系的,所以可以分表。
电信的某个用户的通话和其它用户的通话记录,也是没有关系,所以可以分表处理
(实际上电信的系统,分库分表后也是不大的,难在后台的计费、结算等规则)



三、数据库访问接口



1. 元数据:如何识别到当前要处理的数量在哪张表?

铁路的售票系统会有一个车次管理系统,例2012年2月12日 D3206 车次,
按预先设计的在哪台服务器的哪个库,建哪个表。

2.建立元数据的规则:即具体如何分库分表的规则

这个就是数据库的访问接口。

3.数据库访问接口的透明程度

即哪个层知道哪些元数据信息。
例,是否让窗口售票的客户端来解析元数据的规则然后缓存,还是通过中间件来解析缓存的

具体各层使用怎样透明程度,和业务性质、节点和数据中心的拓扑等有关。



四、历史数据归档与分析

1.使用分库分表后,数据需要归档,分析处理的程序变得复杂,但使联机交易变得简单
2.分析:要注意是针对热线数据分析、归档数据分析、混合分析有关,
通过分库分表和归档,更方便使用分布式的统计方案。

具体可以参考,淘宝的开放平台架构师写的文章:

结论:分库分表跟不分库分表,整个架构是完全不一样的。

像铁票的售票系统、淘宝、电信、银行等,绝对要采用分库分表的数据存储方案,

来解决数据量的增长而不影响性能的问题。

像淘宝等互联网应用还要解决带宽即CDN问题。

posted @ 2012-01-17 13:24 paulwong 阅读(600) | 评论 (0)编辑 收藏

JBoss下DataSource加密(下)

数据源文件:my-oracle-ds.xml

<datasources>
    
<local-tx-datasource>
        
<jndi-name>jdbc/my-local</jndi-name>
        <connection-url>
            jdbc:oracle:thin:@10.5.7.30:1521:orcl
        
</connection-url>
        
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
        <security-domain>EncryptedOracleDbRealm</security-domain>
        
<exception-sorter-class-name>
            org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter
        
</exception-sorter-class-name>
        
<metadata>
            
<type-mapping>Oracle10g</type-mapping>
        
</metadata>
        
<depends>
            jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword
        
</depends>
    
</local-tx-datasource>



    
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
        name
="jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword">
        
<constructor>
            
<arg type="java.lang.String" value="ServerMasterPassword"></arg>
        
</constructor>
        
<!-- The opaque master password file used to decrypt the encrypted
            database password key 
-->
        
<attribute name="KeyStorePass">
            {CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password
        
</attribute>
        
<attribute name="Salt">abcdefgh</attribute>
        
<attribute name="IterationCount">13</attribute>
    
</mbean>

</datasources>

在jboss4.3/jboss-as/server/default/conf/login-config.xml中增加节点:

<application-policy name="EncryptedOracleDbRealm">
    
<authentication>
        
<login-module
            
code="org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
            flag
="required">
            
<module-option name="username">username</module-option>
            
<module-option name="password">
                3wW33nIpavHK4pd3qoNTbA
            
</module-option>
            
<module-option name="managedConnectionFactoryName">
                jboss.jca:service=LocalTxCM,name=jdbc/my-local
            
</module-option>
            
<module-option name="jaasSecurityDomain">
                jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword
            
</module-option>
        
</login-module>
    
</authentication>
</application-policy>

以上的password由下面命令得出:

E:\JBOSS\jboss4.3\jboss-as\server\default\lib>java -cp jbosssx.jar
org.jboss.security.plugins.PBEUtils abcdefgh 
13 master mypassowrd
Encoded password:  2mqrIBSpp8JVWFAqCBklhf

生成server.password文件:

E:\JBOSS\jboss4.3\jboss-as\server\default\lib>java -cp jbosssx.jar
org.jboss.security.plugins.FilePassword abcdefgh 
13 master server.password

产生后拷贝到:${jboss.server.home.dir}/conf中。

posted @ 2012-01-16 18:58 paulwong 阅读(938) | 评论 (0)编辑 收藏

Java生成RSA非对称型加密的公钥和私钥(利用java API)

非对称型加密非常适合多个客户端和服务器之间的秘密通讯,客户端使用同一个公钥将明文加密,而这个公钥不能逆向的解密,密文发送到服务器后有服务器端用私钥解密,这样就做到了明文的加密传送。

非对称型加密也有它先天的缺点,加密、解密速度慢制约了它的发挥,如果你有大量的文字需要加密传送,建议你通过非对称型加密来把对称型‘密钥’分发到客户端,及时更新对称型‘密钥’。

package com.paul.module.common.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

import javax.crypto.Cipher;

public class RSASecurityUtil2 {
    
/** 指定加密算法为RSA */
    
private static final String ALGORITHM = "RSA";
    
/** 密钥长度,用来初始化 */
    
private static final int KEYSIZE = 1024;
    
/** 指定公钥存放文件 */
    
private static String PUBLIC_KEY_FILE = "PublicKey";
    
/** 指定私钥存放文件 */
    
private static String PRIVATE_KEY_FILE = "PrivateKey";

    
/**
     * 生成密钥对
     * 
@throws Exception
     
*/
    
private static void generateKeyPair() throws Exception {
        
//        /** RSA算法要求有一个可信任的随机数源 */
//        SecureRandom secureRandom = new SecureRandom();
        
        
/** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator keyPairGenerator 
= KeyPairGenerator.getInstance(ALGORITHM);
        
        
/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
//        keyPairGenerator.initialize(KEYSIZE, secureRandom);
        keyPairGenerator.initialize(KEYSIZE);
        
        
/** 生成密匙对 */
        KeyPair keyPair 
= keyPairGenerator.generateKeyPair();
        
        
/** 得到公钥 */
        Key publicKey 
= keyPair.getPublic();
        
        
/** 得到私钥 */
        Key privateKey 
= keyPair.getPrivate();
        
        ObjectOutputStream oos1 
= null;
        ObjectOutputStream oos2 
= null;
        
try {
            
/** 用对象流将生成的密钥写入文件 */
            oos1 
= new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
            oos2 
= new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
            oos1.writeObject(publicKey);
            oos2.writeObject(privateKey);
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            
/** 清空缓存,关闭文件输出流 */
            oos1.close();
            oos2.close();
        }
    }

    
/**
     * 加密方法
     * 
@param source 源数据
     * 
@return
     * 
@throws Exception
     
*/
    
public static String encrypt(String source) throws Exception {
        generateKeyPair();
        Key publicKey;
        ObjectInputStream ois 
= null;
        
try {
            
/** 将文件中的公钥对象读出 */
            ois 
= new ObjectInputStream(new FileInputStream(
                    PUBLIC_KEY_FILE));
            publicKey 
= (Key) ois.readObject();
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            ois.close();
        }
        
        
/** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        
byte[] b = source.getBytes();
        
/** 执行加密操作 */
        
byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder 
= new BASE64Encoder();
        
return encoder.encode(b1);
    }

    
/**
     * 解密算法
     * 
@param cryptograph    密文
     * 
@return
     * 
@throws Exception
     
*/
    
public static String decrypt(String cryptograph) throws Exception {
        Key privateKey;
        ObjectInputStream ois 
= null;
        
try {
            
/** 将文件中的私钥对象读出 */
            ois 
= new ObjectInputStream(new FileInputStream(
                    PRIVATE_KEY_FILE));
            privateKey 
= (Key) ois.readObject();
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            ois.close();
        }
        
        
/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        BASE64Decoder decoder 
= new BASE64Decoder();
        
byte[] b1 = decoder.decodeBuffer(cryptograph);
        
        
/** 执行解密操作 */
        
byte[] b = cipher.doFinal(b1);
        
return new String(b);
    }

    
public static void main(String[] args) throws Exception {
        String source 
= "恭喜发财!";// 要加密的字符串
        System.out.println("准备用公钥加密的字符串为:" + source);
        
        String cryptograph 
= encrypt(source);// 生成的密文
        System.out.print("用公钥加密后的结果为:" + cryptograph);
        System.out.println();

        String target 
= decrypt(cryptograph);// 解密密文
        System.out.println("用私钥解密后的字符串为:" + target);
        System.out.println();
    }
}


http://blog.sina.com.cn/s/blog_43b03c72010080t2.html
http://topic.csdn.net/t/20040510/14/3049788.html
http://yuanliyin.iteye.com/blog/853334

posted @ 2012-01-16 00:37 paulwong 阅读(14991) | 评论 (1)编辑 收藏

《1亿在线背后的技术挑战》视频放出

2011年10月31日,腾讯即通平台部高级总监庄泗华在北京航空航天大学的演讲《1亿在线背后的技术挑战》让许多听众变成了庄老师的粉丝。

腾讯大讲堂放出庄泗华的演讲视频,转载请注明来自腾讯大讲堂

演讲PPT下载:http://djt.open.qq.com/portal.php?mod=view&aid=19

视频:1.4亿在线背后的故事

第1部分:从十万级到百万级在线


第2部分:千万级在线


第3部分:亿级在线


第4部分:总结


posted @ 2012-01-15 21:40 paulwong 阅读(351) | 评论 (0)编辑 收藏

我们应当怎样做需求分析(转)

又到新年了,日历又要从2011年翻到2012年了,这使我有太多的感慨,进而勾起了对太大往事的回忆。过去的10年,毫无疑问是中国软件业发展最快的10年。当我们刚刚毕业的时候,还在使用VB、PB开发一些简单的数据库应用,而现在却几乎看不到它们的踪影,换来的是诸如J2EE和.NET这样的大型web应用。而这期间,RUP、XP、敏捷开发、持续集成••••••一个接一个的新概念层出不穷,令人眼花缭乱。现在想来,恍如隔世。

但更令我印象深刻而难以忘怀的,是我亲自经历的、亲眼目睹的、道听途说的一个又一个的软件项目,它们有的获得了成功,但更多的是令人沮丧的失败。套用一下大文豪托尔斯泰体:幸福的家庭都是一样的,不幸的家庭却各有各的不幸;幸福的软件项目都是一样的,不幸的软件项目却各有各的不幸;或者说,成功的软件项目都是一样的,失败的项目却各有各的问题。我常常在想,我们的项目开发到底怎么了,进而把它们一个一个的剥开来深入分析,竟然触目惊心。它们有的是需求的问题,有的是客户关系的问题,还有设计的问题、技术的问题、时间管理的问题、人员培养的问题••••••但归根到底更多的还是需求的问题。需求分析既是一份体力活儿,更是一份技术活儿,它既是人际交往的艺术,又是逻辑分析与严密思考的产物。正是我们在需求分析过程存在的巨大隐患,最终导致了那么多项目的失败。也许你认为我在危言耸听,好吧,我来举几个典型事例分析分析吧。

我的第一个故事来自大名鼎鼎的东软。我在2005年接一个项目的时候,听说这个项目之前是东软做的。当时东软在做这个项目的时候,整个过程经历了10多次结构性的大变更,局部性的调整更是不计其数。据说某天早上,客户对某个功能不满意,他们不得不对几百处程序进行修改。之后客户对修改的内容还是不满意,又不得不将几百处修改重新改回来。最后这个项目导致的结果是,整个这个项目组的所有成员都离开了东软,并似乎从此不愿涉足软件开发领域。多么惨痛的教训啊!我常常听到网友抱怨客户总是对需求改来改去,但客户对需求改来改去的真正原因是什么呢?当我们对客户的需求没有真正理解清楚时,我们做出来的东西客户必然不满意。客户只知道他不满意,但怎样才能使他满意呢?他不知道,于是就在一点儿一点儿试,于是这种反复变更就这样发生了。如果我们明白了这一点,深入地去理解客户的业务,进而想到客户的心坎儿上去,最后做出来的东西必然是客户满意的。记住,当客户提出业务变更的时候,我们一定不能被客户牵着走,客户说啥就是啥。我们要从业务角度深入的去分析,他为什么提出变更,提得合不合理,我有没有更合理的方案满足这个需求。当我们提出更加合理的方案时,客户是乐于接受的,变更也变得可控了。

第二个故事来自我自己的项目,一个早期的项目。在这个项目中,客户扔给了我们很多他们目前正在使用的统计报表,要我们按照报表的格式做出来。这些报表都是手工报表,许多格式既不规范,又很难于被计算机实现。这些报表令我耗费了不少闹细胞,直到最终项目失败都没法完成。这件事留给我的深刻教训是,不能客户怎么说软件就怎么做。客户提出的原始需求往往是不考虑技术实现,基于非计算机管理的操作模式提出来的。他们提出的很多需求常常比较理想而不切实际,毕竟人家是非技术的。但我们作为技术人员,需求分析必须实事求是地、基于技术可以实现的角度去考虑。那种“有条件要上,没有条件创造条件”的鲁莽行事,结果必然是悲惨的。所以我们必须要基于技术实现去引导客户的需求。同时,计算机信息化管理就是一次改革,对以往手工管理模式的改革。如果我们上了信息化管理系统,采用的管理模式却依然是过去的手工模式,新系统的优势从何而来呢?因此,我们做需求就应当首先理解现有的管理模式,然后站在信息化管理的角度去审视他们的管理模式是否合理,最后一步一步地去引导他们按照更加合理的方式去操作与管理。

2007年,我参与了一个集团信息化建设的项目。这个项目中的客户是一个庞大的群体,他们分别扮演着各种角色。从机构层次划分,有集团领导、二级机构人员、三级机构人员;从职能角色划分,有高层领导、财务人员、生产管理员、采购人员、销售人员,等等。在这样一个复杂场景中,不同人员对这个项目的需求是各自不同的。非常遗憾的是,我们在进行需求分析的时候没有认真分析清楚所有类型人员的需求。在进行需求调研的时候,总是集团领导带领我们到基层单位,然后基层单位将各方面的人员叫来开大会。这样的大会,各类型的人员七嘴八舌各说各自的需求,还有很多基层人员在大会上因为羞涩根本就没有提出自己的需求。这样经过数次开会,需求调研就草草收场。我们拿着一个不充分的需求分析结果就开始项目开发,最终的结果可想而知。直到项目上线以后,我们才发现许多更加细节的业务需求都没能分析到,系统根本没法运行,不得不宣告失败。一个软件项目的需求调研首先必须要进行角色分析,然后对不同的角色分别进行调研。需求调研的最初需要召开项目动员大会,这是十分必要的。但真正要完成需求分析,应该是一个一个的小会,1~3个业务专家,只讨论某个领域的业务需求,并且很多问题都不是能一蹴而就完成的,我们必须与专家建立联系,反复沟通后完成。需求分析必须遵从的是一定的科学方法,而不是盲目的大上快上。

我的最后一个故事可能典型到几乎每个人都曾经遇到过。我们的项目从需求分析到设计、开发、测试都十分顺利。但到了项目进行的后期,快到达最后期限时,我们将我们的开发成果提交给客户看,客户却对开发不满意,提出了一大堆修改,而且这些修改工作量还不小。怎么办呢?加班、赶工,测试时间被最大限度压缩。最后项目倒是如期上线了,但大家疲惫不堪,并且上线以后才发现许多的BUG。需求分析不是一蹴而就的,它应当贯穿整个开发周期,不断的分析确认的过程。以上这个事例,如果我们提早将开发成果给客户看,提早解决问题,后面的情况就将不再发生。这就是敏捷开发倡导的需求反馈。敏捷开发认为,需求分析阶段不可能解决所有的需求问题,因此在设计、开发、测试,直到最终交付客户,这整个过程都应当不停地用开发的成果与客户交流,及时获得反馈。只有这样才能及时纠正需求理解的偏差,保证项目的成功。

以上的故事各有各自的不幸,各自都在不同的开发环节出现了问题。但经过深入的分析,各自的问题最终都归结为需求分析出现了问题。为了使我们今后的软件项目不会重蹈覆辙,似乎真的有必要讨论一下我们应该怎样做需求分析。

posted @ 2012-01-15 20:24 paulwong 阅读(332) | 评论 (0)编辑 收藏

[转帖]建设一个靠谱的火车票网上订购系统

转自【 http://www.ifanr.com/68019
昨天,2012年1月11日,网友 @fenng 写了一篇文章,批评铁道部火车票网上订购系统,http://www.12306.cn [1]。同时在新浪发了一条言辞激烈的微博,“去你的‘海量事务高速处理系统’”,引起热议 [2]

春节将到,大家买不着车票,赶不上大年三十与家人团聚,急切心情可以理解。但是拍桌子开骂,只能宣泄情绪,解决不了实际问题。 开发一套订票系统并不难,难在应对春运期间,日均 10 亿级别的洪峰流量。日均 10 亿级别的洪峰请求,在中国这个人口全球第一大国,不算稀罕,不仅火车票订票系统会遇到,而且电子商务在促销时,也会遇到,社交网站遇到新闻热点时,也会遇到。 所以,能够在中国成功运行的云计算系统,推广到全球,一定也能成功。

但是在美国成功运行的云计算系统,移植到中国,却不一定成功。 如果我们能够设计建造一套,稳定而高效的铁路订票系统,不仅解决了中国老百姓的实际问题,而且在全球高科技业界,也是一大亮点,而且是贴着中国标签的前沿科技的亮点。 于是软件工程师们献计献策,讨论如何改进 12306 网上购票系统 [3]。其中比较有代表性的,有两篇 [4,5] 网友的评论中,有观点认为,[4] 利用“虚拟排队”的手段,将过程拉长负载降低,是网游的设计思路。而 [5] 利用缓存技术,一层层地降低系统负荷, 是互联网的设计思路。 个人认为,[4] 和 [5] 并不是相互排斥的两种路线,两者着重解决的问题不同,不妨结合起来使用,取长补短。

下面介绍一下我们的设计草案,追求实用,摈弃花哨。抛砖引玉,欢迎拍砖。
图一。12306.cn 网站系统架构设想图。
Courtesy http://i879.photobucket.com/albums/ab351/kan_deng/12306.png

图一是系统架构图,典型的“展现层”/ “业务层”/ “数据层”的三段论。 用户接入有两类,一个是运行在电脑里的浏览器,例如 IE,另一个是手机。 无论用户用电脑浏览器,还是手机访问 http://www.12306.cn 网站,用户请求首先被网站的负载均衡器接收。负载均衡器连接着一群门户服务器,根据各个门户服务器的负载轻重,负载均衡器把用户请求,转发到某一相对清闲的门户服务器。 门户服务器的任务类似于收发室老头儿,它只读每个用户请求的前几个 bytes,目的是确定用户请求的类型,然后把请求投放到相应类型的队列中去。门户服务器的处理逻辑非常简单,这样做的好处,是让它能够快速处理大批量用户请求。

根据 [5] 的分析,12306 处理的用户请求,大致分为三类,
1. 查询。用户订票前,查询车次以及余票。用户下订单后,查询是否已经订上票。
2. 订票,包括确定车次和票数,然后付款。用户付款时,需要在网银等网站上操作。
3. 第一次访问的用户,需要登记,包括姓名和信用卡等信息。

三类请求的业务处理过程,被分为两个阶段,
1. 运行于缓存中的任务队列。设置队列的目的,是防止处理过程耗时太长,导致大量用户请求拥塞于门户服务器,导致系统瘫痪。
2. 业务处理处理器,对于每一类业务,分别有一群业务服务器。不同业务的处理流程,各不相同。
图二。12306.cn 网站查询和订票业务流程设想图。
Courtesy http://i879.photobucket.com/albums/ab351/kan_deng/12306-1.png
图二描述了查询和订票,两个业务的处理流程。登记业务流程从略。 查询的业务流程,参见图二上半部,分五步。
这里有两个问题需要注意,
1. 用户发出请求后,经过短暂的等待时间,能够迅速看到结果。平均等待时间不能超过 1 秒。
2. 影响整个查询速度的关键,是“查询服务器”的设计。

查询任务可以进一步细化,大致分成三种。
1. 查询车次和时间表,这是静态内容,很少与数据库交互,数据量也不大,可以缓存在内存中。 车次和时间表的数据结构,不妨采用 Key-Value 的方式,开发简单,使用效率高。Key-Value 的具体实现有很多产品,[5] 建议使用 Redis。 这些是技术细节,不妨通过对比实验,针对火车票订票系统的实际流量,以及峰值波动,确定哪一个产品最合适。
2. 查询某一班次的剩余车票,这需要调用数据库中不断更新的数据。 [5] 建议把剩余车票只分为两种,“有”或“无”,这样减少调用访问数据库的次数,降低数据库的压力。但是这样做,不一定能够满足用户的需求,说不定会招致网友的批评讥讽。 [4] 建议在订票队列中,增加测算订票队列长度的功能,根据订票队列长度以及队列中每个请求的购票数量,可以计算出每个车次的剩余座位。如果 12306.cn 网站只有一个后台系统,这个办法行之有效。 但是假如 12306.cn 网站采用分布式结构,每个铁路分局设有子系统,分别管理各个铁路分局辖区内的各个车次。在分布式系统下,这个办法面临任务转发的麻烦。不仅开发工作量大,而且会延长查询流程处理时间,导致用户长久等待。
3. 已经下单的用户,查询是否已经成功地订上票。 每个用户通常只关心自己订的票。如果把每个用户订购的车票的所有内容,都缓存在内存里,不仅非常耗用内存空间,内存空间使用效率低下,更严重的问题是,访问数据库过于频繁,数据量大,增大数据库的压力。

解决上述分布式同步,以及数据库压力的两个问题,不妨从订票的流程设计和数据结构设计入手。
假如有个北京用户在网上订购了一套联票,途经北京铁路局和郑州铁路局辖区的两个车次。
用户从北京上网,由北京铁路局的子系统,处理他的请求。
北京铁路局的订票服务器把他的请求一分为二,北京铁路局的车次的订票,在北京子系统完成,郑州铁路局的车次在郑州子系统完成。
每个子系统处理四种 Key-Value 数据组。
1. 用户ID:多个 (订单ID)s。
2. 订单ID:多个 (订票结果ID)s。
3. 订票结果ID: 一个 (用户ID,车次ID)。
4. 车次ID:一个(日期),多个 (座位,用户ID)。
北京订票服务器完成订票后,把上述四个数据组,写入北京子系统的数据库,同时缓存进北京的查询服务器,参见图二下半部第6步和第7步。
郑州订票服务器完成订票后,把上述四个数据组,写入郑州子系统的数据库,同时缓存进北京的查询服务器,而不是郑州的服务器。 让订票服务器把订票数据,同时写入数据库和查询服务器的缓存,目的是让数据库永久保留订票记录,而让大多数查询,只访问缓存,降低数据库的压力。
北京用户的订票数据,只缓存在北京的查询服务器,不跨域缓存,从而降低缓存空间的占用,和同步的麻烦。这样做,有个前提假设,查询用户与订票用户,基本上是同一个人,而且从同一个城市上网。
 但是这里有个缺陷,某用户在北京上网订了票。过了几天,他在北京上网,输入用户ID和密码后,就会看到他订购的所有车票。可是又过了几天,他去了郑州,从郑州上网,同样输入用户ID和密码,却看不到他订购的所有车票。
 解决这个缺陷的办法并不麻烦,在用户查询订票信息时,需要注明订票地点,系统根据订票地点,把查询请求转发到相应区域的子系统。 另外,每次订票的时候,网站会给他的手机发送短信,提供订票信息,参见图二下半部第8步和第9步。

以上是一个初步设计,还有不少细节需要完善,例如防火墙如何布置等等。
这个设计不仅适用于单一的集中式部署,而且也适合分布式部署。
或许有读者会问,为什么没有用到云计算?其实上述架构设计,为将来向云计算演变,留下了伏笔。
在上述架构设计中,我们假定每个环节需要用多少服务器,需要多大容量的数据库,预先都已经规划好。
但是假如事先的规划,低于实际承受的流量和数据量,那么系统就会崩溃。
所以,事先的规划,只能以峰值为基准设立。 但是峰值将会是多少?
事先难以确定。即便能够确定峰值,然后以峰值为基准,规划系统的能力,那么春运过后,就会有大量资源冗余,造成资源浪费? 如何既能抗洪,又不造成资源浪费?解决方案是云计算,而且目前看来,除了云计算,没有别的办法。

Reference,
[1] 海量事务高速处理系统。 http://www.douban.com/note/195179318/
[2] 去你*的‘海量事务高速处理系统’。 http://weibo.com/1577826897/y0jGYcZfW
[3] 火车订票系统的设想。 http://weibo.com/1570303725/y0l9Y2mwE
[4] 铁路订票系统的简单设计。 http://blog.codingnow.com/2012/01/ticket_queue.html
[5] 铁路订票网站个人的设计浅见。 http://hi.baidu.com/caoz/blog/item/f4f1d7caee09b558f21fe780.html
题图来自 Designyoutrust

posted @ 2012-01-13 13:39 paulwong 阅读(318) | 评论 (0)编辑 收藏

台湾图书

 
http://www.tenlong.com.tw/items/9861811915?item_id=59633
 
商譽管理─看見危機,穿透危機,決勝於未戰之前
http://www.tenlong.com.tw/items/9861578269?item_id=375391
 
全面品質管理, 2/e
http://www.tenlong.com.tw/items/9866184560?item_id=390199
 
曼陀羅九宮格思考術─達成目標成功圓夢
http://www.tenlong.com.tw/items/9866151018?item_id=58621
 
六個標準差的品質管制─ 60 小時學會實務應用的手冊
http://www.tenlong.com.tw/items/9572182579?item_id=377554
 
在失業中創業:被炒魷魚又怎樣!
http://www.tenlong.com.tw/items/9868768004?item_id=382010
 
領導未來的 CEO-12 堂 EMBA 名師的管理必修課
http://www.tenlong.com.tw/items/9862720581?item_id=383127
 
早上 3 分鐘變身管理大師, 2/e
http://www.tenlong.com.tw/items/9866487997?item_id=384625
 
整合行銷傳播策略與企劃
http://www.tenlong.com.tw/items/9576598761?item_id=384636
 
Photoshop 視訊課程合集 (21)
http://www.tenlong.com.tw/items/4712839503?item_id=385316
 
DTP 視訊課程合集 (7)
http://www.tenlong.com.tw/items/4712839503?item_id=385314
 
3ds Max 視訊課程合集(22)
http://www.tenlong.com.tw/items/4712839503?item_id=348746
 
Photoshop 視訊課程合集 (22)
http://www.tenlong.com.tw/items/4712839503?item_id=395988
 
Photoshop 視訊課程合集 (21)
http://www.tenlong.com.tw/items/4712839503?item_id=385316
 
巴菲特 & 索羅斯聯手出擊─不看會後悔的投資策略
http://www.tenlong.com.tw/items/9862572752?item_id=387693
 
揭開肥貓經理人薪酬的黑盒子
http://www.tenlong.com.tw/items/9862572485?item_id=387694
 
圖解第一次看懂經濟指標就上手
http://www.tenlong.com.tw/items/9866434192?item_id=389815
 
把鳥事變好事的神奇手帳術
http://www.tenlong.com.tw/items/9862295635?item_id=390569
 
用 Please 換 Yes 的職場成功學
http://www.tenlong.com.tw/items/9866009017?item_id=390570
 
Pose 這樣擺最 OK ─人像攝影與場景的完美結合
http://www.tenlong.com.tw/items/9862015454?item_id=392624
 
寫給 SA 的 UML / UseCase 實務手冊
http://www.tenlong.com.tw/items/9861817786?item_id=51507
 
Thinking in Java 中文版 (Thinking in Java, 4/e)
http://www.tenlong.com.tw/items/9861815023?item_id=45896
 
jQuery 實戰手冊 (jQuery in Action, 2/e)
http://www.tenlong.com.tw/items/9861811915?item_id=59633
 
讓人不自覺說 YES 的交涉力
http://www.tenlong.com.tw/items/9866363368?item_id=54347
 
翻譯大師教你寫出好句子
http://www.tenlong.com.tw/items/9577297390?item_id=49007
 
日本超級店長首次公開讓客戶「好想再見到妳」的心機說話術
http://www.tenlong.com.tw/items/9866097250?item_id=352822
 
iPhone 基礎程式設計
http://www.tenlong.com.tw/items/9866649091?item_id=351448
 
圖解 NLP 惡魔說話術─實例篇
http://www.tenlong.com.tw/items/9866363872?item_id=248045
 
大膽想 出狠招 (Think Big And Kick Ass In Business And Life) http://www.tenlong.com.tw/items/9866662659?item_id=44764
 
3ds Max 視訊課程合集 1
http://www.tenlong.com.tw/items/4712839503?item_id=46426
 
寫給經理人的專案管理發達之路-使用 Project 2010
http://www.tenlong.com.tw/items/9572239325?item_id=371017
 
軟體測試專案實作-技術、流程與管理
http://www.tenlong.com.tw/items/9572239473?item_id=351121
 

posted @ 2012-01-10 14:55 paulwong 阅读(200) | 评论 (0)编辑 收藏

JBoss下DataSource加密(上)

1.先来看一个普通的数据源配置文件
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
   
<local-tx-datasource>
     
<!-- jndi名字 -->
     
<jndi-name>MySqlDS</jndi-name>
     
<!--URL地址 --> 
     
<use-java-context>false</use-java-context>
     
<connection-url>jdbc:mysql://10.16.175.137:3306/test</connection-url>
     
<!-- 驱动 --> 
     
<driver-class>com.mysql.jdbc.Driver</driver-class>
      
<!-- 用户名 --> 
     
<user-name>root</user-name>
      
<!-- 密码 --> 
    
<password>123456</password>
    
<exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </exception-sorter-class-name> 
     
<metadata> 
        
<type-mapping>mySQL</type-mapping> 
     
</metadata>
   
</local-tx-datasource>
</datasources>


看一下这个文件,里面用户名与密码都是以明文方式存储的,这样子对系统的安全而言带来了极大的威协。所以我们要为我们这个明文的密码加一下密,这就是本文的目的.

2.说到密码加密,这里我们用到了JBoss下的一个类org.jboss.resource.security.SedureIdentityLoginModule,看看我们该如何用它来帮我们的密码加密。
先看个配置数据源的例子(mysql-ds.xml)

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MySqlDS</jndi-name>
<use-java-context>false</use-java-context>
<connection-url>jdbc:mysql://192.168.1.91:3306/atteam</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<!--这里不用写上你的用户名与密码了,我们可以在login-config.xml里做点手脚,就OK了 -->
<security-domain>EncryptDBPassword</security-domain>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>

接着我们修改server\default\conf\login-config.xml文件,加上下面这一段配置文件

<application-policy name="EncryptDBPassword">
<!--这里的name应该是你在配置数据源时写的security-domain里的字符串-->
<authentication>
<login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
<!-- 数据库的用户名 -->
<module-option name="username">test</module-option>
<!--数据库的密码,不过是加密过的了 -->
<module-option name="password">64c5fd2979a86168</module-option>
<!-- 注意name等于你的数据源的jndi-name,这里是MySqlDS -->
<module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=MySqlDS</module-option>
</login-module>
</authentication>
</application-policy>

3.补充一下,这个加密的密码是哪来的

java -cp "D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\lib\jboss-jmx.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\lib\jboss-common.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\server\default\lib\jboss-jca.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\server\default\lib\jbosssx.jar" org.jboss.resource.security.SecureIdentityLoginModule 123456 Encoded password: 64c5fd2979a86168

posted @ 2012-01-09 00:51 paulwong 阅读(619) | 评论 (0)编辑 收藏

实战JBossMQ JMS集群

一、环境
数据库服务器:Oracle 9i2
操作系统:Windows XP SP2
JBoss版本:4.2.2
JDK:Sun 1.5.0.13
网络配置:同一机器的一个网卡上绑定两个ip地址192.168.1.18和192.168.1.147


二、配置
1.配置消息和事务日志持久保存的数据源,从JBoss安装位置的docs\examples\jca目录下拷贝到server\all\deploy目录下,并修改其中的连接配置,这里使用OracleDS作为持久保存的数据源。注意:别忘了把Oracle的jdbc驱动程序拷贝到server\all\lib目录下。

2.修改DestinationManager配置,删除server\all\deploy-hasingleton\jms目录下的hsqldb-jdbc2-service.xml文件,拷贝docs\examples\jms目录下的oracle-jdbc2-service.xml到server\all\deploy-hasingleton目录下,使用OracleDS作为DestinationManager的数据源。

3. 修改StateManager配置,将其中的数据源配置由
jboss.jca:service=DataSourceBinding,name=DefaultDS 
jboss.jca:service=DataSourceBinding,name=OracleDS

4. 配置测试的Topic,在server\all\deploy-hasingleton\jms目录下新建一个名为jbossweek-jms-service.xml文件,
<mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=jbossweekTopic">
        
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>

5. 创建node1的服务器配置,将server\all目录复制一份改名为node1

6. 配置完成。


三、验证
1. 分别以run –c all –b192.168.1.17和run –c node1–b192.168.1.148先后启动all和node1配置。此时192.168.1.17为主节点,浏览http://192.168.1.17:8080/jmx-console/。打开JNDIView可以看到jbossweekTopic的JNDI名称。此时192.168.1.17为主节点,浏览http://192.168.1.148:8080/jmx-console/。打开JNDIView就会发现没有jbossweekTopic的JNDI名称。

2. 关闭192.168.1.17上的all服务器,此时在192.168.1.148上的node服务器的控制台上会出现如下信息:
13:11:13,921 INFO [TreeCache] viewAccepted(): [192.168.1.17:2292|2] [192.168.1.148:2327]
13:11:14,015 INFO [TreeCache] viewAccepted(): [192.168.1.17:2288|2] [192.168.1.148:2321]
13:11:14,218 INFO [DefaultPartition] New cluster view for partition DefaultPartition (id: 2, delta: -1) : [192.168.1.148:1099]
13:11:14,218 INFO [DefaultPartition] I am (192.168.1.148:1099) received members hipChanged event: 13:11:14,218 INFO [DefaultPartition] Dead members: 1 ([192.168.1.17:1099])
13:11:14,218 INFO [DefaultPartition] New Members : 0 ([])
13:11:14,218 INFO [DefaultPartition] All Members : 1 ([192.168.1.148:1099])
13:11:14,453 INFO [TreeCache] viewAccepted(): [192.168.1.17:2279|2] [192.168.1.148:2306]
13:11:16,218 INFO [TomcatDeployer] deploy, ctxPath=/jbossmq-httpil, warUrl=.../deploy-hasingleton/jms/jbossmq-httpil.sar/jbossmq-httpil.war/
13:11:17,406 INFO [jbossweekTopic] Bound to JNDI name: topic/jbossweekTopic
13:11:17,453 INFO [A] Bound to JNDI name: queue/A
13:11:17,453 INFO [B] Bound to JNDI name: queue/B
13:11:17,468 INFO [C] Bound to JNDI name: queue/C
13:11:17,468 INFO [D] Bound to JNDI name: queue/D
13:11:17,468 INFO [ex] Bound to JNDI name: queue/ex
13:11:17,484 INFO [testTopic] Bound to JNDI name: topic/testTopic
13:11:17,500 INFO [securedTopic] Bound to JNDI name: topic/securedTopic
13:11:17,500 INFO [testDurableTopic] Bound to JNDI name: topic/testDurableTopic
13:11:17,500 INFO [testQueue] Bound to JNDI name: queue/testQueue
13:11:17,562 INFO [UILServerILService] JBossMQ UIL service available at : /192.168.1.148:8093 13:11:17,609 INFO [DLQ] Bound to JNDI name: queue/DLQ

3. JMS集群的主节点自动切换到192.168.1.148上的node1节点,浏览http://192.168.1.148:8080/jmx-console/。打开JNDIView就会找到jbossweekTopic的JNDI名称。


http://linliangyi2007.iteye.com/blog/316997
http://docs.redhat.com/docs/zh-CN/JBoss_Enterprise_Application_Platform/5/html/JBoss_Messaging_User_Guide/index.html

posted @ 2012-01-08 23:58 paulwong 阅读(795) | 评论 (0)编辑 收藏

jboss-4.2.x运行多个instance

找到你运行的instance的conf/jboss-service.xml, eg: $JBOSS_HOME/server/default/conf/jboss-service.xml
找到
mbean服务中,名字为 ServiceBindingManager 的,里面有个叫做ports-01的内容,打开这个注释,就可以了。

如果你要运行多个,那么就需要有多个ServiceBindingManager ports-02,这是第三个,ports-03这是地四个,

这个文件,对应${jboss.home.url}/docs/examples/binding-manager/sample-bindings.xml里面的ports-01部分,ports-02部分,只不过需要在这里启用,启动的同时,$JBOSS_HOME/server/default/deploy/jboss-web.deployer/server.xml里面的就不起作用了。

posted @ 2012-01-08 21:33 paulwong 阅读(307) | 评论 (0)编辑 收藏

仅列出标题
共112页: First 上一页 87 88 89 90 91 92 93 94 95 下一页 Last