<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢(mèng)蝶

    生活、程序、未來(lái)
       :: 首頁(yè) ::  ::  :: 聚合  :: 管理

        典型的J2EE項(xiàng)目,package的設(shè)計(jì)有成熟的套路可循,如分為domain、dao、service、action等等,職責(zé)已經(jīng)分解的比較單一和清晰,循環(huán)依賴這樣的情況出現(xiàn)并不多。而在一般的java項(xiàng)目,如服務(wù)器程序、客戶端程序和通用性框架的開(kāi)發(fā)中,包的設(shè)計(jì)并沒(méi)有套路可循,畢竟由于應(yīng)用和業(yè)務(wù)種類的不同,想得出通用性的設(shè)計(jì)套路是不大可能的。這時(shí)候遵循一些原則比之生搬硬套更為重要。在《敏捷軟件開(kāi)發(fā)》一書(shū)中對(duì)包的設(shè)計(jì)有深入的討論,雖然針對(duì)的是發(fā)布的二進(jìn)制包而言,但是對(duì)于java package的設(shè)計(jì)同樣有借鑒意義,如對(duì)包的內(nèi)聚性、可重用性、穩(wěn)定性的強(qiáng)調(diào),對(duì)于依賴的探討,這些都是比較籠統(tǒng)的概念,不是那么直觀,需要在實(shí)際運(yùn)用中認(rèn)真歸納和重構(gòu),向這些原則靠攏。
       我所想到一個(gè)比較直觀的方法就是:對(duì)于一個(gè)包的描述,你是否能用一句簡(jiǎn)明扼要的話概括,也就是包的功能或者說(shuō)介紹能否做到簡(jiǎn)明扼要,這是衡量一個(gè)包的設(shè)計(jì)是否合理的最簡(jiǎn)單的方法。如果可以,顯然這個(gè)包的內(nèi)聚性很好,所有的類都服務(wù)于一個(gè)目的,從而帶來(lái)了重用的可能(其實(shí)我對(duì)重用性并不感冒,除了工具類外真正能重用的東西少之又少,內(nèi)聚性才是需要關(guān)注的);反之,這個(gè)包可能承擔(dān)了太多的職責(zé)或者依賴過(guò)多,仔細(xì)的重構(gòu)和分離是需要做的。包的設(shè)計(jì)同樣要遵循接口分離的原則,將接口與實(shí)現(xiàn)隔離在不同的包之中,客戶程序就不會(huì)知道具體的實(shí)現(xiàn),并且也保證了實(shí)現(xiàn)對(duì)接口的單向依賴。當(dāng)然,這時(shí)就需要引入工廠類、插件或者IOC容器來(lái)負(fù)責(zé)實(shí)例化實(shí)現(xiàn)類。

    posted @ 2008-09-06 00:15 dennis 閱讀(2999) | 評(píng)論 (3)編輯 收藏

        這個(gè)題目比較怪,聽(tīng)俺道來(lái)。俺一直在負(fù)責(zé)公司游戲服務(wù)器的開(kāi)發(fā)和維護(hù),日積月累下來(lái)終于將原本混亂的代碼和結(jié)構(gòu)重構(gòu)的比較清晰了,在此過(guò)程中的體會(huì)就是,重構(gòu)啊,不僅僅是技術(shù)活,更多是要克服不情愿的、得過(guò)且過(guò)的心理去做,去做了才發(fā)現(xiàn)麻煩并沒(méi)有想象中的大。
        改造過(guò)程中遇到這么個(gè)問(wèn)題,我想將對(duì)某個(gè)創(chuàng)建的游戲的操作都固定在一個(gè)線程執(zhí)行,與其他游戲可以并發(fā)地處理;或者說(shuō)依據(jù)游戲id派發(fā)到某個(gè)固定的線程處理,對(duì)此游戲的操作都是串行化。不是俺不想徹底并行化,但是要將現(xiàn)有的代碼改造成適應(yīng)并行化相當(dāng)困難,俺嘗試的結(jié)果是問(wèn)題百出,因此就想了這么個(gè)折中策略,不同游戲之間的操作可以并行,單個(gè)游戲內(nèi)操作串行。怎么派發(fā)呢?很簡(jiǎn)單的機(jī)制,根據(jù)id%size結(jié)果來(lái)處理就好,size就是你準(zhǔn)備開(kāi)的線程數(shù)。因此可以很容易地模擬一個(gè)生產(chǎn)者消費(fèi)者模型的線程池,根據(jù)游戲id%size的結(jié)果將任務(wù)塞到隊(duì)列中,讓生產(chǎn)者線程順序處理。已經(jīng)有部分代碼是這樣處理的,不過(guò)是自己實(shí)現(xiàn)的模型(BlockingQueue),比較不適合俺想要的任務(wù)式的處理過(guò)程,靈機(jī)一動(dòng),jdk5引入的線程池不是有個(gè)單線程的版本嗎?俺將這個(gè)線程池再做個(gè)池不就OK了?說(shuō)起來(lái)不好理解,看代碼:
    public interface Task extends Runnable {
        
    public int getCode();
    }
        嗯,定義一個(gè)Task接口,繼承Runnable,多了個(gè)getCode方法用于決定派發(fā)任務(wù)到哪個(gè)ExecutorService執(zhí)行。線程池池登場(chǎng):
    public class SingleThreadPoolPool {
        
    private Map<Integer, ExecutorService> threadPoolMap = new HashMap<Integer, ExecutorService>();

        
    private int size;

        
    public SingleThreadPoolPool(int size) {
            
    this.size = size;
            
    for (int i = 0; i < size; i++) {
                ExecutorService executor 
    = Executors.newSingleThreadExecutor();
                threadPoolMap.put(i, executor);
            }
        }

        
    public void execute(Task task) {
            
    if (task == null)
                
    return;
            threadPoolMap.get(getIndex(task.getCode())).execute(task);
        }

        
    public void execute(int code, Runnable r) {
            
    if (r == null)
                
    return;
            threadPoolMap.get(getIndex(code)).execute(r);
        }

        
    private int getIndex(int code) {
            
    int index = -1;
            
    if (code < 0)
                index 
    = 0;
            
    else
                index 
    = code % this.size;
            
    return index;
        }

        
    public void shutdown() {
            
    for (int i = 0; i < size; i++) {
                threadPoolMap.get(i).shutdown();
            }
            threadPoolMap.clear();
        }

        
    public int size() {
            
    return this.size;
        }
    }

        哇靠,這也太簡(jiǎn)單了,這就能保證code相同的任務(wù)會(huì)被排隊(duì)順序執(zhí)行。是啊,很簡(jiǎn)單,不是啥高科技,但簡(jiǎn)單明了地實(shí)現(xiàn)了俺的需求。需要注意的是,只有通過(guò)Executor的execute方法提交的任務(wù)才會(huì)被排到隊(duì)列中哦。
        補(bǔ)充一個(gè)線程安全測(cè)試:
    import java.util.concurrent.CountDownLatch;
    import com.xlands.game.lobby.util.SingleThreadPoolPool;

    import junit.framework.TestCase;

    class Counter {
        
    int i;

        
    public void incr() {
            i
    ++;
        }
    }

    class IncrTask implements Runnable {
        Counter counter;
        CountDownLatch latch;

        
    public IncrTask(Counter counter, CountDownLatch latch) {
            
    this.counter = counter;
            
    this.latch = latch;
        }

        
    public void run() {
            
    try {
                counter.incr();

            } 
    finally {
                latch.countDown();
            }
        }
    }

    public class SingleThreadPoolPoolTest extends TestCase {
        
    static final int NUM = 10000;
        SingleThreadPoolPool singleThreadPoolPool;

        @Override
        
    protected void setUp() throws Exception {
            singleThreadPoolPool 
    = new SingleThreadPoolPool(2);
            
    super.setUp();
        }

        @Override
        
    protected void tearDown() throws Exception {
            singleThreadPoolPool.shutdown();
            
    super.tearDown();
        }

        
    public void testThreadSafe() throws Exception {
            Counter c1 
    = new Counter();
            Counter c2 
    = new Counter();
            assertEquals(singleThreadPoolPool.size(), 
    2);
            CountDownLatch latch 
    = new CountDownLatch(NUM * 2);
            
    for (int i = 0; i < NUM; i++) {
                singleThreadPoolPool.execute(
    0new IncrTask(c1, latch));
                singleThreadPoolPool.execute(
    1new IncrTask(c2, latch));
            }
            latch.await();
            assertEquals(NUM, c1.i);
            assertEquals(NUM, c2.i);
        }
    }


    posted @ 2008-09-01 19:38 dennis 閱讀(2396) | 評(píng)論 (2)編輯 收藏

        從8月14日請(qǐng)假開(kāi)始到現(xiàn)在,俺已經(jīng)堅(jiān)持跑步12天了,除了臺(tái)風(fēng)那天沒(méi)法跑之外。一開(kāi)始跑步是想改善自己的精神狀態(tài),工作太容易疲倦,心理疲憊,然后跟老婆打賭說(shuō)我要堅(jiān)持跑步至少3天,如果輸了就回家不碰電腦一個(gè)星期。俺都是繞著天河公園跑,要么是沿著最外圈的四個(gè)大門跑,要么繞著天河湖跑三圈,每天都在四公里左右,最后幾百米沖刺跑。跑完了之后做做壓腿、踢腿,散步下回家,大概要花一個(gè)多小時(shí),然后洗澡、吃飯、上班,差不多時(shí)間。
        一開(kāi)始跑挺吃力,基本沒(méi)有堅(jiān)持跑完一整圈的,中途都得走上一段緩緩氣,從第四天開(kāi)始就比較輕松了,腳步開(kāi)始不吃力,但是呼吸還是比較嗆。堅(jiān)持兩個(gè)星期后,呼吸也跟上來(lái)了,現(xiàn)在可以快速地繞天河湖跑上兩圈,或者跑大圈的時(shí)候也比較輕松啦,特別是腳步感覺(jué)很輕松,俺計(jì)劃著加大運(yùn)動(dòng)量,看看五公里怎么樣。
        大多時(shí)候是早上6點(diǎn)半起床跑,起不來(lái)就晚上去跑。早上好多老大爺老大媽練太極的,還有個(gè)小孩天天看到,比俺猛多了,不知道繞天河湖跑多少圈,基本上是去的時(shí)候遇到他在跑,俺回來(lái)他還在跑。早上跑感覺(jué)挺好,鍛煉的人多,挺有氛圍,一早上看看綠色也比較舒適。晚上跑人比較少點(diǎn),特別是8、9點(diǎn)以后,可以脫了上衣跑,那感覺(jué)爽啊。不過(guò)俺不大建議晚上跑,一是晚上吃飯比較晚,跑步的時(shí)候還沒(méi)完全消化容易肚子痛,另外就是別跑大圈,聽(tīng)說(shuō)晚上那邊也有搶劫的。跑步路線可以時(shí)常換換,俺現(xiàn)在比較熱衷穿樹(shù)林,特別是那邊有片竹林,穿梭其間感覺(jué)不是一般的妙。
        俺自己感覺(jué)身體狀態(tài)好了不少,過(guò)去常常感覺(jué)的胸悶的現(xiàn)象沒(méi)有了,下午精神也好多了。不過(guò)俺的工作狀態(tài)沒(méi)多大改善,看來(lái)不是身體問(wèn)題,還是出在其他問(wèn)題上,需要刺激下自己了。

    posted @ 2008-08-27 07:40 dennis 閱讀(825) | 評(píng)論 (2)編輯 收藏

        前兩天在公司內(nèi)網(wǎng)上搭了個(gè)2個(gè)節(jié)點(diǎn)hadoop集群,暫時(shí)沒(méi)有多大實(shí)際意義,僅用作自己的測(cè)試。遇到的問(wèn)題在阿里巴巴這位仁兄的《Hadoop集群配置和使用技巧》都有提到的。也遇到了reduce任務(wù)卡住的問(wèn)題,只需要在每個(gè)節(jié)點(diǎn)的/etc/hosts將集群中的機(jī)器都配置上即可解決。
       今天將一個(gè)日志統(tǒng)計(jì)任務(wù)用Hadoop MapReduce框架重新實(shí)現(xiàn)了一次,數(shù)據(jù)量并不大,每天分析一個(gè)2G多的日志文件罷了。先前是用Ruby配合cat、grep命令搞定,運(yùn)行一次在50多秒左右,如果純粹采用Ruby的話CPU占用率非常高而且慢的無(wú)法忍受,利用IO.popen調(diào)用linux的cat、grep命令先期處理就好多了。看看這個(gè)MapReduce任務(wù):
    public class GameCount extends Configured implements
            org.apache.hadoop.util.Tool {
        
    public static class MapClass extends MapReduceBase implements
                Mapper
    <LongWritable, Text, Text, IntWritable> {

            
    private Pattern pattern;

            
    public void configure(JobConf job) {
                String gameName 
    = job.get("mapred.mapper.game");
                pattern 
    = Pattern.compile("play\\sgame\\s" + gameName
                        
    + ".*uid=(\\d+),score=(-?\\d+),money=(-?\\d+)");
            }

            @Override
            
    public void map(LongWritable key, Text value,
                    OutputCollector
    <Text, IntWritable> output, Reporter reporter)
                    
    throws IOException {
                String text 
    = value.toString();
                Matcher matcher 
    = pattern.matcher(text);
                
    int total = 0// 總次數(shù)
                while (matcher.find()) {
                    
    int record = Integer.parseInt(matcher.group(2));
                    output.collect(
    new Text(matcher.group(1)), new IntWritable(
                            record));
                    total 
    += 1;
                }
                output.collect(
    new Text("total"), new IntWritable(total));
            }
        }

        
    public static class ReduceClass extends MapReduceBase implements
                Reducer
    <Text, IntWritable, Text, IntWritable> {

            @Override
            
    public void reduce(Text key, Iterator<IntWritable> values,
                    OutputCollector
    <Text, IntWritable> output, Reporter reporter)
                    
    throws IOException {
                
    int sum = 0;
                
    while (values.hasNext()) {
                    sum 
    += values.next().get();
                }
                output.collect(key, 
    new IntWritable(sum));
            }

        }

        
    static int printUsage() {
            System.out
                    .println(
    "gamecount [-m <maps>] [-r <reduces>] <input> <output> <gamename>");
            ToolRunner.printGenericCommandUsage(System.out);
            
    return -1;
        }

       
    public int run(String[] args) throws Exception {
            JobConf conf 
    = new JobConf(getConf(), GameCount.class);
            conf.setJobName(
    "gamecount");

          
    conf.setOutputKeyClass(Text.class);
            conf.setOutputValueClass(IntWritable.class);

            conf.setMapperClass(MapClass.
    class);
            conf.setCombinerClass(ReduceClass.
    class);
            conf.setReducerClass(ReduceClass.
    class);

            List
    <String> other_args = new ArrayList<String>();
            
    for (int i = 0; i < args.length; ++i) {
                
    try {
                    
    if ("-m".equals(args[i])) {
                        conf.setNumMapTasks(Integer.parseInt(args[
    ++i]));
                    } 
    else if ("-r".equals(args[i])) {
                        conf.setNumReduceTasks(Integer.parseInt(args[
    ++i]));
                    } 
    else {
                        other_args.add(args[i]);
                    }
                } 
    catch (NumberFormatException except) {
                    System.out.println(
    "ERROR: Integer expected instead of "
                            
    + args[i]);
                    
    return printUsage();
                } 
    catch (ArrayIndexOutOfBoundsException except) {
                    System.out.println(
    "ERROR: Required parameter missing from "
                            
    + args[i - 1]);
                    
    return printUsage();
                }
            }
            
    // Make sure there are exactly 2 parameters left.
            if (other_args.size() != 3) {
                System.out.println(
    "ERROR: Wrong number of parameters: "
                        
    + other_args.size() + " instead of 2.");
                
    return printUsage();
            }
            FileInputFormat.setInputPaths(conf, other_args.get(
    0));
            FileOutputFormat.setOutputPath(conf, 
    new Path(other_args.get(1)));
            conf.set(
    "mapred.mapper.game", args[2]);
            JobClient.runJob(conf);
            
    return 0;
        }

        
    public static void main(String[] args) throws Exception {
            
    long start = System.nanoTime();
            
    int res = ToolRunner.run(new Configuration(), new GameCount(), args);
            System.out.println(
    "running time:" + (System.nanoTime() - start)
                    
    / 1000000 + " ms");
            System.exit(res);
        }

    }
        代碼沒(méi)啥好解釋的,就是分析類似"play game DouDiZhu result:uid=1871653,score=-720,money=0"這樣的字符串,分析每天玩家玩游戲的次數(shù)、分?jǐn)?shù)等。打包成GameCount.jar,執(zhí)行:
    hadoop jar GameCount.jar test.GameCount /usr/logs/test.log /usr/output GameName

       統(tǒng)計(jì)的運(yùn)行時(shí)間在100多秒,適當(dāng)增加map和reduce任務(wù)個(gè)數(shù)沒(méi)有多大改善,不過(guò)CPU占用率還是挺高的。


    posted @ 2008-08-23 11:08 dennis 閱讀(2660) | 評(píng)論 (0)編輯 收藏

        我對(duì)佛教的了解很淺薄。近段時(shí)間一直在讀圣莊嚴(yán)法師的《佛學(xué)入門》。我覺(jué)的法師對(duì)佛學(xué)因果與因緣講的很好,在此按自己的理解說(shuō)下。佛教的基本教義都可以歸 結(jié)于這兩個(gè)詞。因果說(shuō)的是善有善報(bào)、惡有惡報(bào),因此人人都該多行善、勿做惡,這一步是信佛學(xué)佛的第一步。因緣說(shuō)的是無(wú)常,世間萬(wàn)事萬(wàn)物皆是無(wú)常,悟了并踐 履這一點(diǎn)才有可能超越自我成佛成圣。
       
    說(shuō)因果,很多人就要說(shuō)了,為什么現(xiàn)實(shí)中很多人多行善舉,卻遭惡報(bào),而壞人卻是逍遙自在未得報(bào)應(yīng)?佛教給出的解答是“ 三世因果說(shuō)” 。看因果不能只看現(xiàn)世,要 看的是前世、今世、來(lái)世,因此前世造因,今世受果,今世造因,來(lái)世受果。俗話說(shuō)的好,不是不報(bào),時(shí)候未到罷了。也許你要說(shuō)佛教在狡辯,因?yàn)樗坪鯖](méi)人知道到 底有沒(méi)有這三世,特別是對(duì)于經(jīng)過(guò)系統(tǒng)科學(xué)教育的人也更難接受。可宗教沒(méi)有真假的問(wèn)題,只有信與不信的問(wèn)題。
      
    因果,因就是因素。世間事物都是由因素和因緣組成,所謂因緣就是因素之間的聯(lián)系、關(guān)系。當(dāng)因素被打散、分解、重組,也就是因緣發(fā)生變化的時(shí)候,事物也變化 了,消失了,產(chǎn)生了。因而,事物是無(wú)常的,是沒(méi)有恒定的。世間的財(cái)、色、名、食、睡都是虛幻的,無(wú)常的,不值的留戀的。如果能參透了萬(wàn)物,參透了人之本來(lái) 面目,超越了物我的二元對(duì)立,那才是真的悟了,有了成佛的基礎(chǔ)。然而能放下五欲出家修行終究是少數(shù)人,這少數(shù)人按佛教的說(shuō)法是修了前世的深厚福緣才由此機(jī) 緣出家。
      
    道理很簡(jiǎn)單,但是,知而不行卻是不知。因此對(duì)于我這個(gè)自控力并不是很好的人,在此妄談因果因緣倒是貽笑大方了

    posted @ 2008-08-23 09:17 dennis 閱讀(504) | 評(píng)論 (0)編輯 收藏

        遠(yuǎn)程調(diào)用由于涉及到服務(wù)器和客戶端等多個(gè)節(jié)點(diǎn)以及需要通過(guò)網(wǎng)絡(luò)通訊等,會(huì)引入更多的故障可能。本地調(diào)用的語(yǔ)義都是恰好一次,不會(huì)多也不會(huì)少。而遠(yuǎn)程調(diào)用的語(yǔ)義就比較復(fù)雜,依據(jù)三個(gè)選擇將產(chǎn)生不同的語(yǔ)義:
    1)重發(fā)請(qǐng)求消息:客戶端是否重發(fā)請(qǐng)求,直到收到應(yīng)答或者認(rèn)定服務(wù)器故障為止
    2)過(guò)濾重復(fù)消息:當(dāng)客戶端重發(fā)請(qǐng)求時(shí)候,服務(wù)器是否過(guò)濾重復(fù)的請(qǐng)求
    3)重傳結(jié)果:服務(wù)器是否保存結(jié)果消息的歷史,以便服務(wù)器不用重新執(zhí)行操作就能重傳結(jié)果。

    對(duì)這三個(gè)選擇的不同組合將產(chǎn)生三種可能的遠(yuǎn)程調(diào)用語(yǔ)義:
    重發(fā)請(qǐng)求消息 過(guò)濾重復(fù)消息 重傳結(jié)果            語(yǔ)義

    否            不適用       不適用             或許
    是            否           重新執(zhí)行操作       至少一次
    是            是           重傳結(jié)果           至多一次

    或許調(diào)用語(yǔ)義
    :遠(yuǎn)程方法可能執(zhí)行一次,或者根本不執(zhí)行(在消息遺漏或者服務(wù)器崩潰的情況下)

    至少一次調(diào)用語(yǔ)義:遠(yuǎn)程方法要嘛至少執(zhí)行一次并返回結(jié)果,要嘛返回一個(gè)異常。因?yàn)閱⒂昧酥匕l(fā)請(qǐng)求消息,服務(wù)器也重新執(zhí)行操作,因此遠(yuǎn)程調(diào)用至少執(zhí)行一次,除非服務(wù)器崩潰;但是,由于服務(wù)器重新執(zhí)行操作,如果調(diào)用不是冪等的,那么多次重復(fù)執(zhí)行將產(chǎn)生副作用疊加,可能不符合預(yù)期需求。對(duì)于冪等操作,至少一次調(diào)用語(yǔ)義是可以接受的。

    至多一次調(diào)用語(yǔ)義:在此語(yǔ)義下,服務(wù)器會(huì)過(guò)濾重復(fù)的請(qǐng)求,并且緩存執(zhí)行的結(jié)果重傳而非重新執(zhí)行。因此遠(yuǎn)程調(diào)用同樣也是返回調(diào)用結(jié)果,或者一個(gè)異常。在返回結(jié)果的情況下,可以確認(rèn)服務(wù)器恰好執(zhí)行一次,與本地調(diào)用語(yǔ)義一樣,不會(huì)有副作用疊加。如果返回異常,就是通知調(diào)用者沒(méi)有返回結(jié)果,遠(yuǎn)程調(diào)用要嘛執(zhí)行了一次,要嘛根本沒(méi)有執(zhí)行。總之,遠(yuǎn)程調(diào)用至多執(zhí)行一次。

    Java RMI的調(diào)用語(yǔ)義是至多一次。


    posted @ 2008-08-19 23:47 dennis 閱讀(1716) | 評(píng)論 (1)編輯 收藏

        分布式文件系統(tǒng)的設(shè)計(jì)需求大概是這么幾個(gè):透明性、并發(fā)控制、可伸縮性、容錯(cuò)以及安全需求等。我想試試從這幾個(gè)角度去觀察HDFS的設(shè)計(jì)和實(shí)現(xiàn),可以更清楚地看出HDFS的應(yīng)用場(chǎng)景和設(shè)計(jì)理念。
        首先是透明性,如果按照開(kāi)放分布式處理的標(biāo)準(zhǔn)確定就有8種透明性:訪問(wèn)的透明性、位置的透明性、并發(fā)透明性、復(fù)制透明性、故障透明性、移動(dòng)透明性、性能透明性和伸縮透明性。對(duì)于分布式文件系統(tǒng),最重要的是希望能達(dá)到5個(gè)透明性要求:
    1)訪問(wèn)的透明性:用戶能通過(guò)相同的操作來(lái)訪問(wèn)本地文件和遠(yuǎn)程文件資源。HDFS可以做到這一點(diǎn),如果HDFS設(shè)置成本地文件系統(tǒng),而非分布式,那么讀寫 分布式HDFS的程序可以不用修改地讀寫本地文件,要做修改的是配置文件。可見(jiàn),HDFS提供的訪問(wèn)的透明性是不完全的,畢竟它構(gòu)建于java之上,不能 像NFS或者AFS那樣去修改unix內(nèi)核,同時(shí)將本地文件和遠(yuǎn)程文件以一致的方式處理。
    2)位置的透明性:使用單一的文件命名空間,在不改變路徑名的前提下,文件或者文件集合可以被重定位。HDFS集群只有一個(gè)Namenode來(lái)負(fù)責(zé)文件系 統(tǒng)命名空間的管理,文件的block可以重新分布復(fù)制,block可以增加或者減少副本,副本可以跨機(jī)架存儲(chǔ),而這一切對(duì)客戶端都是透明的。
    3)移動(dòng)的透明性,這一點(diǎn)與位置的透明性類似,HDFS中的文件經(jīng)常由于節(jié)點(diǎn)的失效、增加或者replication因子的改變或者重新均衡等進(jìn)行著復(fù)制或者移動(dòng),而客戶端和客戶端程序并不需要改變什么,Namenode的edits日志文件記錄著這些變更。
    4)性能的透明性和伸縮的透明性:HDFS的目標(biāo)就是構(gòu)建在大規(guī)模廉價(jià)機(jī)器上的分布式文件系統(tǒng)集群,可伸縮性毋庸置疑,至于性能可以參考它首頁(yè)上的一些benchmark。

        其次是并發(fā)控制,客戶端對(duì)于文件的讀寫不應(yīng)該影響其他客戶端對(duì)同一個(gè)文件的讀寫。要想實(shí)現(xiàn)近似原生文件系統(tǒng)的單個(gè)文件拷貝語(yǔ)義,分布式文件系統(tǒng)需要做出復(fù) 雜的交互,例如采用時(shí)間戳,或者類似回調(diào)承諾(類似服務(wù)器到客戶端的RPC回調(diào),在文件更新的時(shí)候;回調(diào)有兩種狀態(tài):有效或者取消。客戶端通過(guò)檢查回調(diào)承 諾的狀態(tài),來(lái)判斷服務(wù)器上的文件是否被更新過(guò))。HDFS并沒(méi)有這樣做,它的機(jī)制非常簡(jiǎn)單,任何時(shí)間都只允許一個(gè)寫的客戶端,文件經(jīng)創(chuàng)建并寫入之后不再改 變,它的模型是write-one-read-many, 一次寫,多次讀。這與它的應(yīng)用場(chǎng)合是一致,HDFS的文件大小通常是兆至T級(jí)的,這些數(shù)據(jù)不會(huì)經(jīng)常修改,最經(jīng)常的是被順序讀并處理,隨機(jī)讀很少,因此 HDFS非常適合MapReduce框架或者web crawler應(yīng)用。HDFS文件的大小也決定了它的客戶端不能像某些分布式文件系統(tǒng)那樣緩存常用到的幾百個(gè)文件。

        第三,文件復(fù)制功能,一個(gè)文件可以表示為其內(nèi)容在不同位置的多個(gè)拷貝。這樣做帶來(lái)了兩個(gè)好處:訪問(wèn)同個(gè)文件時(shí)可以從多個(gè)服務(wù)器中獲取從而改善服務(wù)的伸縮 性,另外就是提高了容錯(cuò)能力,某個(gè)副本損壞了,仍然可以從其他服務(wù)器節(jié)點(diǎn)獲取該文件。HDFS文件的block為了容錯(cuò)都將被備份,根據(jù)配置的 replication因子來(lái),默認(rèn)是3。副本的存放策略也是很有講究,一個(gè)放在本地機(jī)架的節(jié)點(diǎn),一個(gè)放在同一機(jī)架的另一節(jié)點(diǎn),另一個(gè)放在其他機(jī)架上。這 樣可以最大限度地防止因故障導(dǎo)致的副本的丟失。不僅如此,HDFS讀文件的時(shí)候也將優(yōu)先選擇從同一機(jī)架乃至同一數(shù)據(jù)中心的節(jié)點(diǎn)上讀取block。

        第四,硬件和操作系統(tǒng)的異構(gòu)性。由于構(gòu)建在java平臺(tái)上,HDFS的跨平臺(tái)能力毋庸置疑,得益于java平臺(tái)已經(jīng)封裝好的文件IO系統(tǒng),HDFS可以在不同的操作系統(tǒng)和計(jì)算機(jī)上實(shí)現(xiàn)同樣的客戶端和服務(wù)端程序。

        第五,容錯(cuò)能力,在分布式文件系統(tǒng)中,盡量保證文件服務(wù)在客戶端或者服務(wù)端出現(xiàn)問(wèn)題的時(shí)候能正常使用是非常重要的。HDFS的容錯(cuò)能力大概可以分為兩個(gè)方面:文件系統(tǒng)的容錯(cuò)性以及Hadoop本身的容錯(cuò)能力。文件系統(tǒng)的容錯(cuò)性通過(guò)這么幾個(gè)手段:
    1)在Namenode和Datanode之間維持心跳檢測(cè),當(dāng)由于網(wǎng)絡(luò)故障之類的原因,導(dǎo)致Datanode發(fā)出的心跳包沒(méi)有被Namenode正常收 到的時(shí)候,Namenode就不會(huì)將任何新的IO操作派發(fā)給那個(gè)Datanode,該Datanode上的數(shù)據(jù)被認(rèn)為是無(wú)效的,因此Namenode會(huì)檢 測(cè)是否有文件block的副本數(shù)目小于設(shè)置值,如果小于就自動(dòng)開(kāi)始復(fù)制新的副本并分發(fā)到其他Datanode節(jié)點(diǎn)。
    2)檢測(cè)文件block的完整性,HDFS會(huì)記錄每個(gè)新創(chuàng)建的文件的所有block的校驗(yàn)和。當(dāng)以后檢索這些文件的時(shí)候,從某個(gè)節(jié)點(diǎn)獲取block,會(huì)首先確認(rèn)校驗(yàn)和是否一致,如果不一致,會(huì)從其他Datanode節(jié)點(diǎn)上獲取該block的副本。
    3)集群的負(fù)載均衡,由于節(jié)點(diǎn)的失效或者增加,可能導(dǎo)致數(shù)據(jù)分布的不均勻,當(dāng)某個(gè)Datanode節(jié)點(diǎn)的空閑空間大于一個(gè)臨界值的時(shí)候,HDFS會(huì)自動(dòng)從其他Datanode遷移數(shù)據(jù)過(guò)來(lái)。
    4)Namenode上的fsimage和edits日志文件是HDFS的核心數(shù)據(jù)結(jié)構(gòu),如果這些文件損壞了,HDFS將失效。因而,Namenode可以配置成支持維護(hù)多 個(gè)FsImageEditlog的拷貝。任何對(duì)FsImage或者Editlog的修改,都將同步到它們的副本上。它總是選取最近的一致的FsImageEditlog使用。NamenodeHDFS是單點(diǎn)存在,如果Namenode所在的機(jī)器錯(cuò)誤,手工的干預(yù)是必須的。
    5)文件的刪除,刪除并不是馬上從Namenode移出namespace,而是放在/trash目錄隨時(shí)可恢復(fù),直到超過(guò)設(shè)置時(shí)間才被正式移除。
        再說(shuō)Hadoop本身的容錯(cuò)性,Hadoop支持升級(jí)和回滾,當(dāng)升級(jí)Hadoop軟件時(shí)出現(xiàn)bug或者不兼容現(xiàn)象,可以通過(guò)回滾恢復(fù)到老的Hadoop版本。
        最后一個(gè)就是安全性問(wèn)題,HDFS的安全性是比較弱的,只有簡(jiǎn)單的與unix文件系統(tǒng)類似的文件許可控制,未來(lái)版本會(huì)實(shí)現(xiàn)類似NFS的kerberos驗(yàn)證系統(tǒng)。

        總結(jié)下:HDFS作為通用的分布式文件系統(tǒng)并不適合,它在并發(fā)控制、緩存一致性以及小文件讀寫的效率上是比較弱的。但是它有自己明確的設(shè)計(jì)目標(biāo),那就是支 持大的數(shù)據(jù)文件(兆至T級(jí)),并且這些文件以順序讀為主,以文件讀的高吞吐量為目標(biāo),并且與MapReduce框架緊密結(jié)合。



      

    posted @ 2008-08-15 22:38 dennis 閱讀(5913) | 評(píng)論 (3)編輯 收藏

    HDFS用戶指南
    原文地址:http://hadoop.apache.org/core/docs/current/hdfs_user_guide.html
    譯者:dennis zhuang(killme2008@gmail.com),有錯(cuò)誤請(qǐng)指正,多謝。

    目的

    本文檔可以作為使用Hadoop分布式文件系統(tǒng)用戶的起點(diǎn),無(wú)論是將HDFS應(yīng)用在一個(gè)Hadoop集群中還是作為一個(gè)單獨(dú)的分布式文件系統(tǒng)使用。HDFS被設(shè)計(jì)成可以馬上在許多環(huán)境中工作起來(lái),那么一些HDFS的運(yùn)行知識(shí)肯定能大大地幫助你對(duì)一個(gè)集群做配置改進(jìn)和診斷。

    概覽

    HDFS是Hadoop應(yīng)用的主要分布式存儲(chǔ)。一個(gè)HDFS集群由一個(gè)管理文件系統(tǒng)元數(shù)據(jù)的NameNode,和存儲(chǔ)實(shí)際 數(shù)據(jù)的一些Datanode組成。HDFS的架構(gòu)在這里有詳細(xì)描述。這個(gè)用戶指南主要提供給需要跟HDFS集群打交道的用戶或者管理員。HDFS架構(gòu)文章 中的圖描繪了Namenode、Datanode和客戶端們之間的基本交互。本質(zhì)上,客戶端與Namenode通訊獲取或者修改文件的元數(shù)據(jù),與 Datanode進(jìn)行實(shí)際的IO操作。

    下面的列表應(yīng)該是大多數(shù)用戶關(guān)心的HDFS突出特點(diǎn)。斜體字的術(shù)語(yǔ)將在后面詳細(xì)描述。

    1)Hadoop,包括HDFS,非常適合廉價(jià)機(jī)器上的分布式存儲(chǔ)和分布式處理。它是容錯(cuò)的、可伸縮的,并且非常易于擴(kuò)展。并且,以簡(jiǎn)單性和適用性著稱的Map-Reduce是Hadoop不可或缺的組成部分。

    2)HDFS的默認(rèn)配置適合于大多數(shù)安裝的應(yīng)用。通常情況下,只有在一個(gè)非常大規(guī)模的集群上才需要修改默認(rèn)配置。

    3)HDFS是用java編寫的,支持大多數(shù)平臺(tái)。

    4)支持shell命令行風(fēng)格的HDFS目錄交互。

    5)Namenode和Datanode都內(nèi)建了web服務(wù)器,可以方便地查看集群的狀態(tài)

    6)HDFS經(jīng)常性地實(shí)現(xiàn)新的特性和改進(jìn),下面是HDFS中的一些有用特性的子集:

       文件許可和授權(quán)

       Rack awareness:當(dāng)調(diào)度任務(wù)和分配存儲(chǔ)的時(shí)候?qū)⒐?jié)點(diǎn)的物理位置考慮進(jìn)去。

       Safemode(安全模式):用于維護(hù)的一個(gè)管理狀態(tài)

       fsck: 診斷文件系統(tǒng)的一個(gè)工具,用來(lái)查找丟失的文件或者block

       Rebalancer:當(dāng)數(shù)據(jù)在Datanode間沒(méi)有均勻分布的時(shí)候,用于重新平衡集群的工具

       升級(jí)和回滾:當(dāng)Hadoop軟件升級(jí),在升級(jí)遇到不可預(yù)期的問(wèn)題的時(shí)候,可以回滾到HDFS升級(jí)前的狀態(tài)

       二級(jí)Namenode:幫助Namenode維持包含了HDFS修改的日志的文件(edits日志文件,下文談到)大小在限制范圍內(nèi)。

    前提條件

    下面的文檔描述了一個(gè)Hadoop集群的安裝和設(shè)置:


    本文檔的剩余部分假設(shè)你已經(jīng)搭設(shè)并運(yùn)行了一個(gè)至少擁有一個(gè)Datanode的HDFS。基于本文檔的目的,Namenode和Datanode可以運(yùn)行在同一臺(tái)機(jī)器上。

    Web接口

    Namenode和Datanode分別跑了一個(gè)內(nèi)置的web服務(wù)器,來(lái)展現(xiàn)集群當(dāng)前狀態(tài)的一些基本信息。在默認(rèn)配置 下,Namenode的首頁(yè)地址是http://namenode:50070(namenode就是Namenode節(jié)點(diǎn)所在機(jī)器IP或者名稱)。這個(gè) 頁(yè)面列出了集群中的所有datanode以及集群的基本統(tǒng)計(jì)。web接口同樣可以用于瀏覽文件系統(tǒng)(點(diǎn)擊Namenode首頁(yè)上的“Browse the file system"鏈接)。

    Shell命令

    Hadoop包括了多種shell風(fēng)格的命令,用于跟HDFS或者Hadoop支持的其他文件系統(tǒng)交互。命令 bin/hadoop fs -help 可以列出Hadoop shell支持的命令。更進(jìn)一步,bin/hadoop fs -help command 可以展現(xiàn)特定命令command的幫助細(xì)節(jié)。這些命令支持一般文件系統(tǒng)的操作,例如拷貝文件、修改文件權(quán)限等。同時(shí)也支持了部分HDFS特有的命令,例如 修改文件的replication因子。

    DFSAdmin命令

    'bin/hadoop dfsadmin' 命令支持一些HDFS管理功能的操作。'bin/hadoop dfsadmin -help'可以列出所有當(dāng)前支持的命令。例如:

    • -report : 報(bào)告HDFS的基本統(tǒng)計(jì)信息。部分信息同時(shí)展現(xiàn)在Namenode的web首頁(yè)上。 
    • -safemode : 盡管通常并不需要,管理員還是可以通過(guò)手工操作進(jìn)入或者離開(kāi)safemode狀態(tài)
    • -finalizeUpgrade : 移除上一次升級(jí)時(shí)集群所做的備份。

    二級(jí)Namenode

    Namenode將對(duì)文件系統(tǒng)的修改存儲(chǔ)在一個(gè)原生文件系統(tǒng)文件中(名為edits的文件)。當(dāng)Namenode啟動(dòng)的時(shí) 候,它從映像文件(fsimage)讀取HDFS的狀態(tài),然后將edits日志文件中的修改作用在此內(nèi)存狀態(tài)上,接著將得到的新的HDFS狀態(tài)寫回 fsimage,后續(xù)的正常操作開(kāi)始于一個(gè)空的edits日志文件。由于Namenode僅僅在啟動(dòng)的時(shí)候?qū)simage和edits合并,因此在一個(gè) 大的集群上經(jīng)過(guò)一定時(shí)間操作后,edits文件將會(huì)非常大。由此帶來(lái)的一個(gè)副作用就是下次Namenode的重新啟動(dòng)將花費(fèi)很長(zhǎng)時(shí)間。二級(jí) Namenode就是為了解決這個(gè)問(wèn)題,它會(huì)周期性地合并fsimage和edits日志文件,并且將edits日志文件的大小保持在限制范圍內(nèi)。通常它 會(huì)跑在另一個(gè)機(jī)器上,因?yàn)樗膬?nèi)存要求跟主namenode一樣。二級(jí)Namenode可以通過(guò)'bin/start-dfs.sh'啟動(dòng)在conf /masters配置文件里配置的節(jié)點(diǎn)上。

    Rebalancer

    HDFS的數(shù)據(jù)可能不會(huì)總是在Datanode之間分布得很一致。一個(gè)常見(jiàn)的原因是往現(xiàn)有的集群中加入了新的Datanode。當(dāng)分配block的時(shí)候,Namenode依據(jù)幾個(gè)參數(shù)來(lái)決定哪個(gè)datanode來(lái)接受這些block。一些需要考慮的因素如下:

    1)一個(gè)block的副本存放在正在寫該block的節(jié)點(diǎn)上

    2)需要將一個(gè)block的副本擴(kuò)展到其他機(jī)架上,防止因?yàn)檎麄€(gè)機(jī)架故障導(dǎo)致的數(shù)據(jù)丟失。

    3)副本之一通常放在同一個(gè)機(jī)架的另一個(gè)節(jié)點(diǎn)上,減少跨機(jī)架的網(wǎng)絡(luò)IO

    4)將HDFS數(shù)據(jù)均勻一致地分布在集群中的datanode上。

        基于這些相互競(jìng)爭(zhēng)的因素,數(shù)據(jù)可能不會(huì)在Datanode之間擴(kuò)展得一致。HDFS給管理員提供了一個(gè)工具,用來(lái)分析block的分配情況和在datanode之間重新平衡數(shù)據(jù)。這個(gè)功能暫未實(shí)現(xiàn),它的描述可以在這個(gè) PDF文檔中看到,記錄編號(hào)HADOOP-1652.

    Rack Awareness

    典型的大規(guī)模Hadoop集群是部署在數(shù)個(gè)機(jī)架上的,那么顯然同一個(gè)機(jī)架內(nèi)的節(jié)點(diǎn)間的網(wǎng)絡(luò)通訊比之不同機(jī)架間節(jié)點(diǎn)間的網(wǎng) 絡(luò)通訊更可取。另外,Namenode會(huì)嘗試將block的副本分布在數(shù)個(gè)機(jī)架中以提高容錯(cuò)性。Hadoop讓集群管理員來(lái)決定某個(gè)節(jié)點(diǎn)從屬于哪個(gè)機(jī)架, 通過(guò)配置變量dfs.network.script來(lái)實(shí)現(xiàn)。當(dāng)這個(gè)腳本有配置的時(shí)候,每個(gè)節(jié)點(diǎn)都運(yùn)行該腳本來(lái)決定它的rackid。默認(rèn)安裝假設(shè)所有的節(jié) 點(diǎn)從屬于同一個(gè)機(jī)架。這個(gè)特性和配置進(jìn)一步的闡述在這個(gè)PDF文檔,編號(hào)為 HADOOP-692

    Safemod(安全模式)

    當(dāng)Namenode啟動(dòng)的時(shí)候,它從fsimage和edits日志兩個(gè)文件中加載文件系統(tǒng)的狀態(tài)。然后等待 datanode報(bào)告他們的block信息,以便防止Namenode在確認(rèn)block副本是否足夠前過(guò)早地開(kāi)始復(fù)制block。這段時(shí)間的 Namenode就是處于所謂safemode狀態(tài)。處于safemode的Namenode也是HDFS集群的只讀模型,此時(shí)不允許任何對(duì)文件系統(tǒng)或者 block的修改。正常情況下,Namenode會(huì)在開(kāi)始后自動(dòng)退出safemode。如果有需要,HDFS可以通過(guò)'bin/hadoop dfsadmin -safemode'命令顯式地進(jìn)入safemode狀態(tài)。Namenode的web首頁(yè)顯示當(dāng)前的safemode是否打開(kāi)。更詳細(xì)的描述和配置可以參 考setSafeMode()方法的JavaDoc。

    譯 注:詳細(xì)介紹下safemode的配置參數(shù),在safemode狀態(tài),Namenode會(huì)等待所有的datanode報(bào)告他們自己的block信息,看看 所有的block的副本是否達(dá)到最低要求的數(shù)目,這個(gè)數(shù)目可以通過(guò)dfs.replication.min參數(shù)配置,默認(rèn)是1,也就是至少要求有一個(gè)副 本。當(dāng)報(bào)告合格的Datanode的數(shù)目達(dá)到一定百分比,Namenode才會(huì)離開(kāi)safemode狀態(tài)。這個(gè)百分比也是可配置的,通過(guò) dfs.safemode.threshold.pct參數(shù),默認(rèn)是0.999f(也就是要求99.9%的Datanode 合格)。Namenode在合格的datanode數(shù)目達(dá)到要求的時(shí)候,并不是馬上離開(kāi)safemode狀態(tài),會(huì)有一個(gè)擴(kuò)展時(shí)間,讓剩余的 datanode來(lái)報(bào)告block信息,這個(gè)擴(kuò)展時(shí)間默認(rèn)是30秒,可以通過(guò)dfs.safemode.extension參數(shù)配置,單位是毫秒。

    Fsck

    HDFS提供了fsck命令用來(lái)檢測(cè)各種各樣的不一致性。fsck被設(shè)計(jì)用來(lái)報(bào)告各種文件的問(wèn)題,例如某個(gè)文件丟失的 block,block的副本數(shù)目是否低于設(shè)置等。不同于傳統(tǒng)的一般原生文件系統(tǒng)的fsck命令,hdfs的fsck命令并不修正所檢測(cè)到的錯(cuò)誤。通常情 況下,Namenode會(huì)自動(dòng)修正大多數(shù)可以被修復(fù)的錯(cuò)誤,HDFS的fsck不是Hadoop shel的命令,可以通過(guò)'bin/hadoop fsck'執(zhí)行,可以運(yùn)行在整個(gè)文件系統(tǒng)上或者一個(gè)文件子集上。

    升級(jí)和回滾

    當(dāng)升級(jí)某個(gè)集群的Hadoop的時(shí)候,正如任何軟件的升級(jí)一樣,可能會(huì)引入新的bug或者不兼容的修改導(dǎo)致現(xiàn)有的應(yīng)用出 現(xiàn)過(guò)去沒(méi)有發(fā)現(xiàn)的問(wèn)題。在所有重要的HDFS安裝應(yīng)用中,是不允許出現(xiàn)因丟失任何數(shù)據(jù)需要從零開(kāi)始重啟HDFS的情況。HDFS允許管理員恢復(fù)到 Hadoop的早期版本,并且將集群的狀態(tài)回滾到升級(jí)前。HDFS的升級(jí)細(xì)節(jié)請(qǐng)參考 upgrade wiki。HDFS在任何時(shí)間只能有一個(gè)備份,因此在升級(jí)前,管理員需要通過(guò)'bin/hadoop dfsadmin -finalizeUpgrade'命令移除現(xiàn)有的備份。下面簡(jiǎn)要描述了典型的升級(jí)過(guò)程:

    1)在升級(jí)Hadoop前,如果已經(jīng)存在備份,需要先結(jié)束(finalize)它。可以通過(guò)'dfsadmin -upgradeProgress status'命令查詢集群是否需要執(zhí)行finalize

    2)停止集群,分發(fā)部署新版本的Hadoop

    3)執(zhí)行新版本的hadoop,通過(guò)添加 -upgrade 選項(xiàng),例如/bin/start-dfs.sh -upgrade

    4)大多數(shù)情況下,集群在升級(jí)后可以正常運(yùn)行。一旦新的HDFS在運(yùn)行若干天的操作后沒(méi)有出現(xiàn)問(wèn)題,那么就可以結(jié)束(finalize)這次升級(jí)。請(qǐng)注意,在升級(jí)前刪除的文件并不釋放在datanode上的實(shí)際磁盤空間,直到集群被結(jié)束(finalize)升級(jí)前。

    5)如果有需要回到老版本的Hadoop,那么可以:

       a)停止集群,分發(fā)部署老版本的Hadoop

       b)通過(guò)rollback選項(xiàng)啟動(dòng)集群,例如bin/start-dfs.sh -rollback

    文件許可和安全

    文件許可的設(shè)計(jì)與其他平臺(tái)(如linux) 的文件系統(tǒng)類似。在當(dāng)前實(shí)現(xiàn),安全被限制在簡(jiǎn)單的文件許可上。啟動(dòng)Namenode的用戶被作為HDFS的超級(jí)用戶。HDFS的未來(lái)版本將支持網(wǎng)絡(luò)驗(yàn)證, 例如Kerberos方案(譯注:MIT開(kāi)發(fā)的一個(gè)驗(yàn)證系統(tǒng))的用戶驗(yàn)證以及數(shù)據(jù)傳輸?shù)募用堋8敿?xì)的討論參考Permissions User and Administrator Guide

    伸縮性

    Hadoop正運(yùn)行在成千上萬(wàn)個(gè)節(jié)點(diǎn)的集群上。 PoweredBy Hadoop列 出了一些部署Hadoop在大規(guī)模集群上的組織和機(jī)構(gòu)。HDFS在每個(gè)集群上只有一個(gè)Namenode節(jié)點(diǎn),Namenode節(jié)點(diǎn)上可用內(nèi)存是當(dāng)前伸縮性 的主要限制。在非常大規(guī)模的集群上,增加HDFS中存儲(chǔ)的文件的平均大小,將可以幫助提高集群的大小而不用增加Namenode的內(nèi)存需求。默認(rèn)的配置可 能不適合非常大規(guī)模的集群應(yīng)用。Hadoop FAQ頁(yè)列出了對(duì)于大規(guī)模Hadoop集群的配置改進(jìn)建議。

    關(guān)聯(lián)文檔

     本用戶指南可作為使用HDFS很好的一個(gè)起點(diǎn),在本文檔持續(xù)改進(jìn)的同時(shí),有一些非常有價(jià)值的關(guān)于Hadoop和HDFS的文檔資料可供參考。下列資料可作為進(jìn)一步探索的起點(diǎn):


    posted @ 2008-08-14 20:24 dennis 閱讀(7070) | 評(píng)論 (2)編輯 收藏


        memcached 1.2新增加了幾個(gè)參數(shù),試著做下總結(jié),有錯(cuò)誤請(qǐng)指正:
    -U <num> 監(jiān)聽(tīng)UDP端口,默認(rèn)是11211端口

    -f <factor> 這個(gè)參數(shù)很重要,用于設(shè)置chunk大小的遞增因子。memcached的存儲(chǔ)模型類似一個(gè)二維數(shù)組:slab->chunk->item,每個(gè)slab大小是1M,slab中的chunk的大小等于chunk的初始大小乘以f^sid(f的sid次方),其中sid是當(dāng)前slab的id,chunk的默認(rèn)大小在1.1是1字節(jié),在1.2是80字節(jié)。f就是chunk的遞增倍數(shù),在1.1固定為2,在1.2可通過(guò)-f參數(shù)設(shè)置,默認(rèn)為1.25。memcachd存儲(chǔ)的item大小一般會(huì)比存儲(chǔ)的chunk size小,那么就有部分空間被浪費(fèi),為了盡量節(jié)省內(nèi)存,正確設(shè)置-f參數(shù)就顯的非常重要,通過(guò)計(jì)算盡量讓chunk的大小接近或者略大于存儲(chǔ)的item的大小。

    -M 這個(gè)參數(shù)在1.1中就有了。這個(gè)參數(shù)用于在內(nèi)存溢出的時(shí)候,禁止自動(dòng)移除緩存數(shù)據(jù)(LRU),替代的是返回一個(gè)error。

    -s <size> 設(shè)置分配給item的key、value和flag的最小字節(jié)數(shù),默認(rèn)是48字節(jié)。根據(jù)你存儲(chǔ)的item大小適當(dāng)調(diào)整這個(gè)值,可以更有效地利用內(nèi)存。

    -t <num> 設(shè)置處理請(qǐng)求的線程數(shù)。這個(gè)參數(shù)僅在編譯memcached啟用線程時(shí)有效。這個(gè)參數(shù)通常設(shè)置的大小等于CPU個(gè)數(shù)。


    posted @ 2008-08-07 22:16 dennis 閱讀(1697) | 評(píng)論 (0)編輯 收藏

        Ehcache的overflowToDisk屬性用來(lái)配置當(dāng)緩存存儲(chǔ)的數(shù)據(jù)達(dá)到maxInMemory限制時(shí)是否overflow到磁盤上。如果這個(gè)屬性為true,那么要求緩存的數(shù)據(jù)必須是可序列化的,如果不是可序列化的,ehcache將在日志中打印這個(gè)錯(cuò)誤(文檔中僅指出了這點(diǎn)),并且調(diào)用memoryStoreEvictionPolicy設(shè)置的策略(例如LRU)移除內(nèi)存中的一個(gè)緩存元素再放入新的Element,同時(shí)觸發(fā)CacheEventListener的notifyElementEvicted方法。

    posted @ 2008-08-06 23:17 dennis 閱讀(1770) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共56頁(yè): First 上一頁(yè) 23 24 25 26 27 28 29 30 31 下一頁(yè) Last 
    主站蜘蛛池模板: 国产一区二区三区免费观看在线| 免费无码一区二区三区| 一级毛片免费观看| 蜜臀91精品国产免费观看| 亚洲ⅴ国产v天堂a无码二区| 色综合久久精品亚洲国产| 日本免费高清视频| 免费国产高清视频| 亚洲精品美女在线观看| 国产99久久久国产精免费| 亚洲中文无码永久免费| 精品国产亚洲一区二区三区| 亚洲色欲色欲www在线播放| 精品一卡2卡三卡4卡免费视频| 国产成人涩涩涩视频在线观看免费 | 亚洲午夜福利精品无码| 亚洲国产人成在线观看| 中文字幕免费在线播放| 特级淫片国产免费高清视频| 亚洲嫩模在线观看| 五月婷婷免费视频| 成人五级毛片免费播放| 亚洲欧洲国产日韩精品| fc2免费人成在线视频| 免费特级黄毛片在线成人观看 | 日本红怡院亚洲红怡院最新| 亚洲精品无码你懂的| 中文字幕在线观看免费视频| 久久亚洲精品无码播放| 亚洲中文无码永久免费| 999任你躁在线精品免费不卡| 久久精品国产精品亚洲艾草网美妙 | 亚洲AV永久无码精品一福利 | 亚洲成人免费在线观看| 韩国免费A级毛片久久| 国产三级免费观看| 中日韩亚洲人成无码网站| 最好看最新的中文字幕免费 | 亚洲av无码日韩av无码网站冲| 18禁成人网站免费观看| 久久夜色精品国产亚洲|