星期六, 8月 27, 2011

書:學徒模式 Apprenticeship Patterns


很棒的一本書
教導軟體人員在不同階段的學習心態

最重要的是認清自己的無知
才能持續學習
且軟體的技術太多 單只會特定一項就自以為是
要跟外界多交流,而不是閉門造車
否則只會是個井底之蛙






列出作者提的模式清單
時時回顧,鞭策自己
  • 不同的道路
    你發現你想要前進的方向與軟體工藝之路不同
  • 成為菜鳥
    隨著你超越身邊其他人,你發現自己學習的速度減慢
  • 拋棄式玩具
    你在一個無法允許失敗的環境工作,然而你需要一個安全的地方學習
  • 具體技能
    你想要在一個偉大的開發團隊中工作,但你只擁有極少的實務經驗
  • 正視你的無知
    你發現自己的知識有巨大的差距,但你的工作要求你瞭解這些主題
  • 工藝先於藝術
    你需要交付解決方案給客戶,可以選擇一個簡潔、驗證過的解決方式或是藉機建立一個新穎、了不起的解決方案
  • 建立回饋迴路
    你無法分辨自己是否處於「無自覺的無知」
  • 量身繪製地圖
    僱主所提供的職涯路線都不適合
  • 擴展你的頻寬
    你對軟體開發的瞭解很狹窄,專注在每天工作上的低階細節
  • 顯露你的無知
  • 熟悉使用工具
  • 尋找個人導師
  • 志趣相同的夥伴
  • 自失敗中學習
  • 培養你的熱情
  • 練習練習再練習
  • 持續閱讀
  • 閱讀清單
  • 記錄個人所學
  • 邊工作邊反省
  • 退回舒適區
  • 密切交往
  • 分享個人所學
  • 堅守初衷
  • 研讀經典
  • 持續的動力
  • 打掃地板
  • 深水區
  • 漫漫長路
  • 繫上白帶
  • 釋放你的熱情
  • 使用原始碼
  • 使用你的頭銜
  • 你的第一個語言

星期五, 8月 26, 2011

Object & Data Structure

  • 資料隱藏
    如setter及getter對I/O的validate及filter
    而data structure會曝露資料
    如同從db來欄位出來用tb['name']
    將來欄位修改為name2時,不同引用的地方就都得改
    而物件就只需要在組成的地方修改即可
  • 抽像化
    public interface Vehicle {
        double getPercentFuelRemaining();
    }
    
    透過method操作資料
    不用知道實作的細節
    上例不會從程式裡知道data的細節
    user只知道要呼叫的method,不用考慮細節或有何資料
    連setter及getter都不用
    而data structure曝露資料且無意義的名稱

.gitignore

不加入版本控管可透過.gitgnore設定
在git的根目錄下建.gitgnore,其內容設定
#.gitignore內容
tmp.txt                  #不加入tmp.txt
*.log                    #不加入所有的log檔
tmp/*                    #不加入tmp下所有檔
log/**/*.log             #忽略log目錄下包含子目錄的所有.log檔案
log/**/*                 #略特定目錄下的所有檔案

由於git不會track空資料夾,所以當ignore *, 會造成tmp/log資料夾不會加入repository
這時只要在tmp/log下,加個.gitignore,內容如下
vi tmp/.gitignore # log/.gitignore
#--
*
!.gitignore #這個檔也可以不追蹤

其他過濾條件(其實就正規表達式)
  • ?:代表任意的一個字元
  • *:代表任意數目的字元
  • {!ab}:必需不合於此pattern
  • {ab,bb,cx}:代表合於ab,bb,cx之一種pattern即可
  • [abc]:代表合於a,b,c中任一字元即可
  • [^abc]:代表必需不合於a,b,c中任一字元

FAQ
  • 加入ignore無效?
    明明就已經加入了,但一樣會檢查
    因為一開始就把檔案加入tracking,就把檔案放進repository追蹤
    所以每次改變都會檢查,這時只要下
    git rm --cached <ignore file>
    然後再commit一次,這樣就ok啦
    p.s. 當然這次 gitignore就要先寫好 後記:但別人merge後,不知為何他的<ignore fil>會整個刪掉....
References git ignore

星期四, 8月 25, 2011

PHP時間函數


  • 取值
    • 取今天日期
      $today = date("F j, Y, g:i a");                 // March 10, 2001, 5:16 pm
      $today = date("m.d.y");                         // 03.10.01
      $today = date("j, n, Y");                       // 10, 3, 2001
      $today = date("Ymd");                           // 20010310
      $today = date('h-i-s, j-m-y, it is w Day');     // 05-16-18, 10-03-01, 1631 1618 6 Satpm01
      $today = date('\i\t \i\s \t\h\e jS \d\a\y.');   // it is the 10th day.
      $today = date("D M j G:i:s T Y");               // Sat Mar 10 17:16:18 MST 2001
      $today = date('H:m:s \m \i\s\ \m\o\n\t\h');     // 17:03:18 m is month
      $today = date("H:i:s");                         // 17:16:18
    • 取今、明、後天的秒數
      $tomorrow  = mktime(0, 0, 0, date("m")  , date("d")+1, date("Y"));
      $lastmonth = mktime(0, 0, 0, date("m")-1, date("d"),   date("Y"));
      $nextyear  = mktime(0, 0, 0, date("m"),   date("d"),   date("Y")+1);
    • 取特定日期到目前的秒數
      $Date_In = '2007-01-08';
      echo time() - strtotime($Date_In); // Output the number of seconds between now and $Date_In
  • Validation
    • 判斷是否日期是否正確
      if(strtotime($Date_In))
      ...





Reference

log4php

Quick Start
  • Install
    1. download Apache log4php
    2. copy
      將src/main/php/搬到目的地library/log4php
  • logging
    include('library/log4php/Logger.php');
    $logger = Logger::getLogger("main");
    $logger->info("foo");
    $logger->warn("bar");
    
    This produces the following output:
    Sun Jul 26 01:40:23 2009,021 [10093] INFO main - foo
    Sun Jul 26 01:40:23 2009,030 [10093] WARN main - bar
    
  • 設定配置
    //在getLogger前讀
    Logger::configure('config.xml');
    $logger = Logger::getLogger("main");
    
    config.xml
    
            
            
            
    
            
            
                            
            
                    
                     
            
    
    
進階設定
  • appender
    log的記錄可寫到不同的地方,如console, file, db,這就靠appender裡的設定來區分,而appender可以設定不同的class,以寫到不同的類型,以下列出常用的appender classes
  • logger
    logger即為記錄器,透過logger記錄資訊,logger設定提供過濾等級(debug, warn或error),及配對appender以便寫到不同的媒體(console, file或db)裡
    • Logger threshold
      設定info以上全記錄
      <configuration xmlns="http://logging.apache.org/log4php/">
          <appender class="LoggerAppenderConsole" name="default">
          
              
              
          
        </appender>
      </configuration>
      
    • Configuring loggers
      範例中每次要換appender,就得改xml設定
      可透過取得不同logger,即可得不同的appender
       
               
      
      
      $logger = Logger::getLogger("fileAppender"); //即可取得 myFileAppender
      
  • Filters
    提供比logger設定裡更精確的過濾條件
  • Renderers
    要記錄object時,log4php會透過default renderer預設將所有屬性印出,如果要客製化的話
    1. 先寫render
      例如$person
      /** All object renderers must implement the LoggerRendererObject interface. */
      class PersonRenderer implements LoggerRendererObject {
          public function render($person) {
              return "{$person->firstName} {$person->lastName} ({$person->age})";
          }
      }
    2. 設定檔
      Person對應PersonRenderer
      <configuration xmlns="http://logging.apache.org/log4php/">
          <renderer renderedClass="Person" renderingClass="PersonRenderer" />
          <appender name="defualt" class="LoggerAppenderEcho" />
          <root>
              <appender_ref ref="defualt" />
          </root>
      </configuration>

  • Configuration
    設定檔可用XML, properties(ini) or PHP files來設定,擇一即可
    • 利用properties(ini)設定default的appender
      log4php.appender.default = LoggerAppenderDailyFile
      log4php.appender.default.layout = LoggerLayoutPattern
      log4php.appender.default.layout.ConversionPattern = "%d{ISO8601} [%p] %c: %m (at %F line %L)%n"
      log4php.appender.default.datePattern = Ymd
      log4php.appender.default.file = logs/behavior/%s.log
    • 利用php設定default2的appender
      //config.php
      return array(
          'rootLogger' => array(
              'appenders' => array('default2'),
          ),
          'appenders' => array(
              'default2' => array(
              'class' => 'LoggerAppenderEcho',
              'layout' => array(
                'class' => 'LoggerLayoutSimple'
              )
           )
          )
      ));
      
      //include cofigure file
      Logger::configure('config.php');
      
  • Pattern Layout Parameters
    %d 時間
    %p log的level( info, error , ...)
    $c appender的名稱
    %m message
    %F filename
    %L 行數
    %n 斷行
references

時區設定

星期一, 8月 22, 2011

PHP轉影音檔

[轉]使用PHP進行影片轉檔及擷取縮圖

要在 Linux 主機上使用 PHP 進行影片轉檔,須安裝 LAME、ffmpeg、Ruby、FLVTool2。

  1. 安裝 LAME
    LAME 是用來將聲音壓成 MP3 格式,並加入 --enable-shared 以供 ffmpeg 使用
    網址:http://lame.sourceforge.net/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf lame-3.98.4.tar.gz
    [root@localhost ~]# cd lame-3.98.4
    [root@localhost ~]# ./configure --enable-shared -prefix=/usr
    [root@localhost ~]# make
    [root@localhost ~]# make install
  2. ffmpeg Install With Libx264
    1. Download libx264
      Get the libx264 package from here: http://www.videolan.org/developers/x264.html
    2. Install libx264
      cd /path/to/x264-dir
      ./configure --enable-shared
      make
      make install
      ldconfig
      如果遇到yasm not found,就用無敵的yum install yasm
      如果遇到yum找不到yasm,就先裝epel
      //32bit 
      sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
      
      //CentOS 5 64bit
      sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
      
      //CentOS 6
      rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
  3. 安裝 ffmpeg
    ffmpeg 影片轉檔系統,其 libavcodec 涵蓋大部分影片格式,不過仍有轉換 FLV 上的問題,須另外安裝 FLVTools 來修正。
    網址:http://www.ffmpeg.org/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf ffmpeg-0.5.1.tar.gz
    [root@localhost ~]# cd ffmpeg-0.5.1
    [root@localhost ~]# ./configure --enable-gpl --enable-libmp3lame --enable-shared --enable-libx264 --prefix=/usr

    [root@localhost ~]# make clean && make
    [root@localhost ~]# make install
  4. 安裝 Ruby
    FLVTool2 可以修正 ffmpeg 不正確儲存 FLV metadata 的問題,不過它是用 Ruby 寫的,須先安裝 Ruby。
    網址:http://www.ruby-lang.org/en/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf ruby-1.9.1-p376.tar.gz
    [root@localhost ~]# cd ruby-1.9.1-p376
    [root@localhost ~]# ./configure
    [root@localhost ~]# make
    [root@localhost ~]# make install
  5. 安裝 FLVTool2
    FLVTool2 是一個用來編輯FLV檔的套件,透過它來儲存FLV檔,確保 FLV 檔裡有正確的 metadata。
    網址:http://rubyforge.org/projects/flvtool2/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -xvf flvtool2-1.0.6.tar
    [root@localhost ~]# cd flvtool2-1.0.6
    [root@localhost ~]# ruby setup.rb config
    [root@localhost ~]# ruby setup.rb setup
    [root@localhost ~]# ruby setup.rb install
  6. 安裝 ffmpeg-php
    為了讓 PHP 取得影片的資料,要安裝 ffmpeg-php 插件。
    網址:http://ffmpeg-php.sourceforge.net/
    下載:http://sourceforge.net/projects/ffmpeg-php/files/ffmpeg-php/0.6.0/ffmpeg-php-0.6.0.tbz2/download

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -xvf ffmpeg-php-0.6.0.tbz2
    [root@localhost ~]# cd ffmpeg-php-0.6.0
    [root@localhost ~]# phpize
    [root@localhost ~]# ./configure && make
    [root@localhost ~]# make install

    在configure && make階段遇到CODEC_TYPE_VIDEO undeclared問題
    新增yum的Repository後
    重裝yum install ffmpeg ffmpeg-devel ffmpeg-libpostproc 解決一些問
    Install FFmpeg and ffmpeg-php on CentOS Easily
    之後又遇到‘PIX_FMT_RGBA32′undeclared 看下篇解決
    ffmpeg-php error PIX_FMT_RGBA32

    如果 Apache 是使用 XAMPP 請參考這篇:
    [Linux] 在 XAMPP 上安裝 PHP extension (以 ffmpeg-php 為例)

    make後 可以看到產生ffmpeg.so的資料
    再搬到/usr/lib64/php/modules/ffmpeg.so
    即可設定 PHP 載入這個plugin。
  7. 設定 php.ini
    1. #vi /etc/php.ini
      加入以下內容:
      [ffmpeg]
      extension=ffmpeg.so
    2. 重開apache
      #service httpd restart

    最後重啟 Apache
  8. 開始轉檔
    以下是一個簡單的範例:
    PHP程式碼
    //ffmpeg 的執行路徑
    $ffmpegPath = "/usr/bin/ffmpeg";
    //來源影片路徑
    $srcFile = '/var/www/html/ffmpeg/upload/test_in.wmv';
    //輸出影片路徑
    $outFile = '/var/www/html/ffmpeg/upload/test_out.flv';
    //輸出縮圖路徑
    $outImg = '/var/www/html/ffmpeg/upload/test.jpg';

    //取得影片資訊
    $ffmpegObj = new ffmpeg_movie($srcFile);
    //取得音頻比特率
    $srcAB = intval($ffmpegObj->getAudioBitRate()/1000);

    //將影片轉換為FLV檔
    exec("$ffmpegPath -i $srcFile -f flv -s 436x324 -acodec libmp3lame -ar 22050 -ac 2 -ab $srcAB -y $outFile");

    //從影片產生縮圖
    exec("$ffmpegPath -itsoffset -1 -i $srcFile -vcodec mjpeg -vframes 1 -an -f rawvideo -s 436x324 $outImg");
如果沒有錯誤,又沒有轉出的檔案 檢查一下資料夾權限是否限制寫入

Reference

星期五, 8月 19, 2011

書: Clean Code

  1. What is clean code
    • "elegant and efficient" Bjarne Stroustrup, C++之父
      寫的真好...
    • "simple and direct" Grady Booch, OO大師
      幾個字就說出精要,大師就是大師

    為什麼會有bad code
    程式不斷修改,保持clean,混亂的程式碼才不會越滾越大
    導致沒辦法維護,記住童子軍的規則
    The Boy Scout Rule
    Leave the campground cleaner than you found it.

    5S
    • Sort 命名易辯識
    • Systematize 歸類(知道到哪找)
    • Cleaning 潔簡
    • Standardization 一致的coding style
    • Self-discipline 遵守規定
    總而言之就是Keep it clean
    Each function, each class, each module
    exposes a single-minded attitude

  2. Meaningful Names
    • Use Intention-Revealing Names
      透過命名就能知其意圖,如果還需要註解來解釋它,就代表不夠清楚
    • Use Pronounceable Names
      使用可發音的Name幫助溝通
    • Use Searchable Names
      方便search及取代
    • Use Problem Domain Names
      沒有適合使用的term,就使用domain的term,讓接手維護的人至少還可以問domain專家,這代表什麼
  3. Functions
    • Do One Thing(Small)
      只做命名的事細節,包給其他function
    • Function Arguments The Ideal number of arguments is 0 有參數,增加理解困難

  4. Comments
    Don’t comment bad code
    rewrite it 註解沒太多幫助,不如重寫重新整理

程式持續修改演化
不可能一次把程式寫好
First, Make It Work
Then Make It Right


References

星期五, 8月 12, 2011

git push 二三事

  • push origin
    git push可夾很多參數
    還看不太懂,好好研究一下吧
    • git push
          即git push <remote>, 如果<remote>沒設定,便push到origin
    • git push origin
         即git push origin :.
         The default behavior of this command when no is given can be configured by setting the push option of the remote.
         For example, to default to pushing only the current branch to origin use git config remote.origin.push HEAD. Any valid (like the ones in the examples below) can be configured as the default for git push origin.
    • git push origin :
           自動推到相同名稱的分支     
    • git push origin master
          將目前的master推到origin的master
      (most likely, it would find refs/heads/master), and update the same ref (e.g. refs/heads/master) in origin repository with it.      
    • git push origin HEAD
      將目前所在的branch推回origin下,同名稱的branch(
      未建立,會自動建立)
    • git push origin master:satellite/master dev:satellite/dev
           Use the source ref that matches master (e.g. refs/heads/master) to update the ref that matches satellite/master (most probably
          refs/remotes/satellite/master) in the origin repository, then do the same for dev and satellite/dev.   
    • git push origin HEAD:master
          
      HEAD為目前所在branch,也可以直接下名稱;而後面master是push到origin下的branch
    • git push origin master:refs/heads/experimental
             Create the branch experimental in the origin repository by copying the current master branch. This form is only needed to create a new branch or
                    tag in the remote repository when the local name and the remote name are different; otherwise, the ref name on its own will work.      
    • git push origin :experimental
                    Find a ref that matches experimental in the origin repository (e.g. refs/heads/experimental), and delete it.        
    • git push origin +dev:master
                    Update the origin repository’s master branch with the dev branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling
                    in the origin repository. Consider the following situation, where a fast-forward is not possible:
  • push remote
    • 送給某個repo
      $ git push ssh://yourserver.com/~you/proj.git master

git運用流程

目前做法
一台共用的測試機 + n台開發機

雖然每個人可各自pull其他人的東西
不過共同開發還是用1台做merge,其他人pull比較簡單點

  • push時機
    每次commit完
    便push到測試機,而push是push到測試機上自己的branch,這樣方便分辯誰push的
    再到測試機做merge,其他人做pull
  • pull時機
    每次commit完,就做pull

星期三, 8月 10, 2011

MySQL Proxy & Amoeba

做MySQL的效能多會用load balance
目前MySQL的load balance多採用官方的MySQL Proxy及大陸的Amoeba
以下整理網路上收集到的資訊,挺多簡體翻的 要習慣一下
  • MySQL Proxy
    安裝:mysql proxy讀寫分流(一)-mysql proxy的安裝方式
    說明:MySQL Proxy位於 client及MySQL server(s)中間
    MySQL Proxy可以monitor, analyze or transform their communication. 可達到:
    • load balancing
    • failover
    • query analysis
    • query filtering and modification
    • ... and many more. 
  • Amoeba
    安裝:Amoeba For MySQL 實現資料庫負載平衡(讀寫分離)
    說明:Amoeba 也位於Client、Database Server(s)之間
     Amoeba 具有負載均衡、高可用性、 sql過濾
    可承受達到讀寫分離、Query Route(解析sql query語句,並且根據條件與預先設定的規則,請求到指定的目標數據庫。可並發請求多台數據庫合併結果)
    對客戶端透明。主要降低數據切分帶來的複雜多數據庫結構、數據切分規則給應用
    帶來的影響。
  • 比較 in action

    • Load Blance及讀寫分離
      Master:Server1(可讀寫)
      Slaves:Server2, Server3, Server4(3個平等的數據庫。只讀/負載均衡)

      • MySQL Proxy
        #設定db server變數
        Server1=10.1.1.1  #master
        Server2=10.2.1.1  #slave1
        Server3=10.3.1.1  #slave2
        Server4=10.4.1.1  #slave3
        ROOT_DIR=/usr/local

        #指定讀寫server
        LUA_PATH="$ROOT_DIR/mysql-proxy/share/mysql-proxy/?.lua" $ROOT_DIR/mysql-proxy/sbin/mysql-proxy \
        --daemon \
        --proxy-backend-addresses=$Server1:3306 \
        --proxy-read-only-backend-addresses=$Server2:3306 \
        --proxy-read-only-backend-addresses=$Server3:3306 \
        --proxy-read-only-backend-addresses=$Server4:3306 \
        --proxy-lua-script=$ROOT_DIR/mysql-proxy/share/mysql-proxy/rw-splitting.lua

        這個例子中10.1.1.1為可寫
        限制10.2.1.1,10.3.1.1,10.4.1.1只能讀
      • Amoeba
        amoeba提供讀寫分離pool相關配置。並且提供負載均衡配置。
        可配置server2、server3、server4形成一個虛擬的 virtualSlave,該配置提供負載均衡、failOver、故障恢復功能
        <dbServer name=“virtualSlave” virtual=“true”>
        <poolConfig>
        <className>com.meidusa.amoeba.server.MultipleServerPool</className>
        <!-- 負載均衡參數 1=ROUNDROBIN , 2=WEIGHTBASED -->
        <property name="loadbalance">1</property>

        <!-- 參與該pool負載均衡的poolName列表以逗號分割 -->
        <property name="poolNames"> Server2,Server3,Server4</property>
        </poolConfig>
        </dbServer>

        指派讀寫機
        <queryRouter>
        <className>com.meidusa.amoeba.mysql.parser.MysqlQueryRouter</className>
        <property name="LRUMapSize">1500</property>
        <property name="defaultPool">server1</property>

        <property name="writePool">server1</property>
        <property name="readPool">virtualSlave</property>

        <property name="needParse">true</property>
        </queryRouter>
        那麼遇到update/insert/delete將 query語句發送到 wirtePool,將 select發送到 readPool機器中執行。
    • 資料分割
      • MySQL Proxy
      • Amoeba
        SELECT * from user_event where user_id='test' and gmt_create between Sysdate() -1 and Sysdate()

        如果根據gmt_create 時間進行數據切分,比如 6個月進行切分一次
        amoeba提供利用類似sql表達式進行數據切分:
        • 規則1(對應服務器1):
          GMT_CREATE > to_date('2008-01-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-05-31','yyyy-mm-dd')
        • 規則2(對應服務器2)
          GMT_CREATE > to_date('2008-06-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-12-31','yyyy-mm-dd')
        上面的sql的條件 gmt_create 與規則裡面的的gmt_create 進行交集判斷,如果存在交集則表示符合規則。 則會將sql轉移到 規則1 的相應的服務器上面執行。
        利用amoeba寫出這種類似規則很容易,但是要想做到數據切分以後可線性擴容,那麼這樣的規則需要自己根據業務實際情況進行設置。
        amoeba可同時將sql 並發分發到多台服務器、然後將結果合併再反饋給客戶端,而且amoeba內部現成採用無阻塞模式,工作線程是不會等待的,並發請求多台 database server情況下,客戶端等待的時間基本上面是性能最差的那台 database server+amoeba內部解析協議的時間

    注意事項

    沒實作過,也不知要注意什麼 還是看別人寫的吧
    • MySQL Proxy
      • 同步延遲問題
        寫入後,其他slaves的同步問題,MySQL Proxy如何解決同步延遲問題
      • 資料是亂碼
        有看到2種解決方法,還沒試過
        • 設定mysql server
          set names "utf8"也沒有效果。
          [mysqld]
          skip-character-set-client-handshake
          init-connect='SET NAMES utf8'
          default-character-set=utf8
        • 修改/etc/my.cnf 設定檔
          加入底下設定,即可解決亂碼問題(當然您要依據您的環境做修改)
          default-character-set = utf8
          skip-character-set-client-handshake
          character-set-server = utf8
          collation-server = utf8_general_ci
          init-connect = SET NAMES utf8
    • Amoeba
        MySQL使用Amoeba作为Proxy时的注意事项 以下是截錄的
      • Amoeba不支持事务
        p.s. 還不知道"事務"是什麼 不過官網似乎提到有支援了
      • Amoeba不支持跨库join和排序
        跨庫的join和排序非常消耗資源,會導致性能嚴重下降,Amoeba沒有進行支持,只能做到分數據庫實例。
      • Amoeba不支持大數據量的查詢。
        不適合返回大量(超過10萬)數據的查詢,大數據量的查詢非常消耗內存,Amoeba在進行大數據量查詢時性能會非常差。當然,實際業務中需要進行大數據量查詢的情況會非常少或者根本沒必要實現這種情況。這裡所謂的大數據量查詢指的是一次查詢結果超過十萬行。
      • Amoeba需要更嚴格的SQL語句規範
        From 關鍵字後面如果不是子查詢,一律不能帶括號」()」;
        如果的表中字段名與關鍵字或者函數名一樣需要帶上字符` (比如:mytable.`order`)
      • 與直接操作mysql數據庫相比,amoeba性能的損失大概在怎麼一個範圍?
        amoeba是屬於代理層,起碼要消耗2次網絡IO,加上amoeba自身的計算時候的消耗,
        如果數據庫的性能非常高,或者sql的執行並不消耗數據庫的磁盤IO,那麼這時候完全不能體現amoeba的好處,反而會降低整體的性能。具體數據目前沒有算過。

    結論

    • 學習曲線
      由於MySQL Proxy需透過Lua Script
      看起來不難,不過要初學者在linux去碰這東西,還真是有難度

      而Amoeba設定就簡單的多
      只需要進行相關的XML配置就可以滿足需求
      SQLJEP語法寫規則
      雖然lua也不難,但比起設定檔的學習曲線還是有差
    • 效能方面
      比官方的mysql proxy性能大致低10%~20%左右
      在一次請求數據量比較大的情況下比如好幾千條數據,性能有所下降,這個原因是由於解析了mysql與客戶端之間交互的所有數據包,而mysql proxy在沒有使用lua特定腳本的時候是不會解析mysql數據包
      並發能力來說比mysql proxy會更強勁,還有穩定性方面都比mysql proxy強。從使用的連接數來看,在相同的客戶端並發連接情況下,與mysql數據庫的連接數將比mysql proxy少一半。
      在0.27版本以後,amoeba的性能逐漸超過了MySQL Proxy
    • 文件支援
      維護amoebad的人似乎不多
      在官網查相關文件都有些不清楚
      問題回覆也沒有歸類,有問題不好解決
    • 穩定性
      覺得Amoeba太新了
      官網上也有不少人回應bug的事
      穩定性也是需要考量的地方
    References

星期五, 8月 05, 2011

php比較相似字串

  1. 比對相似的字串 similar_text($str1, $str2)
    //測試性名陣列
    $names = array('Robert Smith','Bobby Smythe','Roberto Thithe', 'Robin Smith');

    //檢查相似程度
    foreach($names as $name){
    similar_text($name, 'Roberto Smythi', $percent);
    echo "{$name} = {$percent}%\n";
    }
    //result
    //Robert Smith = 88%
    //Bobby Smythe = 64%
    //Roberto Thithe = 74.074074074074%
    //Robin Smith' = 66.66666666667%
  2. levenshtei()


See Also

  • soundex() - Calculate the soundex key of a string

星期一, 8月 01, 2011

$_SERVER

url為www.example.com/controllerA/actionB/argC/C
利用$_SERVER的各參數,可得以下

  • Server相關
    參數說明value
    SERVER_NAMEServer位置www.example.com
    SERVER_ADDRserver IP位置192.168.11.1
    SERVER_PORTPort80
    DOCUMENT_ROOTweb的根目錄/var/www/html(看/etc/httpd/conf/httpd.conf的設定)
    SCRIPT_FILENAMEscript位置
    SCRIPT_NAMEscript名稱
  • Client相關
    參數說明value
    REMOTE_ADDRclient的ip192.168.11.1
  • request相關
    參數說明value
    REQUEST_URIrequest的uri/controllerA/actionB/argC/C