大量並發的應急處理方案與實踐2——使用緩衝

來源:互聯網
上載者:User

大量並發的應急處理方案與實踐2——使用緩衝
    《大量並發的應急處理方案與實踐》提供的方法,只能做應急時的一種參考,不推薦在設計之初時使用,設計之初我們應該採用更合理的架構,以避免文中所提及的問題發生,關於架構請參考我的另一篇文章《開餐館與做軟體——如何提高大型網站效能》。
      資源可以分成兩種,一種為禁止並發訪問的資源,另一種為允許並發訪問的資源。禁止並發訪問的資源如高速公路收費站,每一個收費口一次只處理一個通過請求,當有多個車輛請求通過時,解決的辦法有兩種,一種是增設收費口,另一種就是讓車輛排隊等候,即不馬上處理請求,讓請求等待空閑資源,我把這種解決辦法稱作後向非同步處理,即將需要處理的請求,延後一段時間處理,這種方法適用於使用者不需要看到即使效果的情況。關於“後向非同步處理” 的例子請參考《大量並發的應急處理方案與實踐1——非同步處理》。允許並發訪問的資源如商場,任何顧客都可以隨時購買需要的商品,早先的大部分商場商品前都有一個櫃檯,顧客通過售貨員購買需要的商品,當顧客增多後,售貨員就會應接不暇,讓顧客排隊是一個辦法,但是沒有哪個商場會強制顧客排隊購買商品,這種“後向非同步處理”不適合解決這樣的問題,於是一種更好的解決方案產生了——“超市”,取出部分商品直接擺放在售貨台上,讓顧客自己去取,然後只需要安排一個服務人員隨時觀察,發現商品不全再到庫房中取來相應商品進行補充。
      即將如下流程:
 顧客 -> 售貨員1 -> 商品1 -> 付費
 顧客 -> 售貨員2 -> 商品2 -> 付費
 顧客 -> 售貨員3 -> 商品3 -> 付費
      改造為
 庫房 -> 服務員 —> 售貨台(緩衝)(前向非同步處理)
 顧客 -> 商品(1、2、3)->  排隊付費(後向非同步處理)
      這是一個典型例子,顧客對於付費的請求不需要即時響應,我們可以採用後向非同步處理的方法。但是對於查看商品的請求越早滿足越好,因此我們採用另一種前向非同步處理的辦法,將商品(資料)提前放到售貨台(緩衝)裡,這樣當顧客(請求)需要的時候可以直接取走。下面我們來看一個你可能會遇到的例子:
      有一天你的老闆突然接到電話,客戶抱怨說當登入人數增加的時候,頁面開啟的非常慢,這時老闆找到你,你竭盡全力向老闆解釋,老闆用無奈的眼神望著你,對你說:"使用者很急,全靠你了。"
      你垂頭喪氣的走回到座位上,開始一點點排查原因,這時你發現原來這些頁面在開啟時,伴隨大量的資料庫操作,
這就是頁面開啟速度慢的原因。遇到這樣的問題,比較簡單快速的改造方法就是使用緩衝。
      即是將如下結構,
 使用者-> 頁面與邏輯 -> 資料庫
      改造為:
 資料庫 -> 監控程式 -> 緩衝 (前向非同步處理)
 使用者-> 頁面與邏輯 -> 緩衝
 

      舉例來說你發現需要加速的頁面 test.jsp, 其通過TestDB.java 類擷取資料。

    public class TestDB{
                 ...
                // 讀取資料庫 1
                String sql1 = "..."; //查詢語句
                List tmplist1 = queryBySQL(sql1); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
                ...
                // 讀取資料庫 2
                String sql2 = "..."; //查詢語句
                List tmplist2 = queryBySQL(sql2); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
                ...
                // 讀取資料庫 3
                String sql3 = "..."; //查詢語句
                List tmplist3 = queryBySQL(sql3); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
                ...
    }

 

       首先,我們建立一個與頁面相對應的緩衝模組(例如Buffer)。為需要快取資料的頁面建立一個與之對應的類TestBuffer.java 用來存放資料。必須保證TestBuffer.java 中的資料與資料庫中相應資料的一一對應關係,因此我們將TestBuffer.java 設計為一個單例。

    #Buffer
           -- TestBuffer.java

 

     public class TestBuffer{
               private volatile static TestBuffer singleton=null;
               private TestBuffer(){}

               public static TestBuffer getInstance()
              {

                     if(singleton==null){
                           synchronized(TestBuffer.class)
                          {
                                  singleton=new TestBuffer();
                           }
                     }
   
                     return singleton;
              }

     }

 

    我們分析需要加速頁面的資料庫操作模組,找出所有資料庫操作點。例如我們分析TestDB.java ,發現如下資料庫
操作點:讀取資料庫 1、讀取資料庫 2、讀取資料庫 3。這三個操作點分別返回三個List 對象,這三個List 對象就是我們要緩衝的資料。我們將這三個對象加入到testBuffer.java 中。

     public class TestBuffer{
               private volatile static TestBuffer singleton=null;
               private TestBuffer(){}

               private static List tmplist1 = null
               private static List tmplist2 = null
               private static List tmplist3 = null

 

               public static TestBuffer getInstance()
               {

                       if(singleton==null){
                              synchronized(TestBuffer.class)
                              {
                                     singleton=new TestBuffer();
                              }
                       }
   
                       return singleton;
                }

                public List getTmplist1(){
                      return tmplist1;
                }
 
                public List setTmplist1(List tmplist1){
                      this.tmplist1 = tmplist1;
                }

                public List getTmplist2(){
                      return tmplist2;
                }
 
                public List setTmplist2(List tmplist2){
                      this.tmplist2 = tmplist2;
                }

                public List getTmplist3(){
                      return tmplist3;
                }
 
                public List setTmplist3(List tmplist3){
                     this.tmplist3 = tmplist3;
                }

      }

 

   重新改造原先的資料庫訪問模組TestDB.java ,更改如下:
  
    public class TestDB{
             ...
           //String sql1 = "..."; //查詢語句
           //String sql2 = "..."; //查詢語句
           //String sql3 = "..."; //查詢語句
           //List tmplist1 = queryBySQL(sql1); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
           //List tmplist2 = queryBySQL(sql2); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
           //List tmplist3 = queryBySQL(sql3); //queryBySQL 方法,執行sql 語句,執行結果放到一個List 中返回
 
           List tmplist1 = TestBuffer.getTmplist1();
           List tmplist2 = TestBuffer.getTmplist2();
           List tmplist3 = TestBuffer.getTmplist3();

            ...

    }

 

    然後我們添加從資料庫到緩衝的前向非同步處理模組,即我們實現一個提前啟動並執行監控程式,將資料庫中的資料放到緩衝中,並保持緩衝與資料庫中的資料同步,我們可以使用線程實現。

 public class testThread implements Runnable{

           private static long interval = 3000; //迴圈間隔

           @Override
           public void run(){
                 while(true){
                        ...

                       String sql1 = "..."; //查詢語句
                       String sql2 = "..."; //查詢語句
                       String sql3 = "..."; //查詢語句
                       List tmplist1 = queryBySQL(sql1);
                       TestBuffer.setTmplist1(tmplist1);

 

                       List tmplist2 = queryBySQL(sql2);
                       TestBuffer.setTmplist2(tmplist2);

 

                       List tmplist3 = queryBySQL(sql3);
                       TestBuffer.setTmplist3(tmplist3);
                        ...

                       try { 
                              Thread.sleep(interval);
                       } catch (InterruptedException e) {
                              // TODO Auto-generated catch block
                             e.printStackTrace();
                       }

                }

         }

 }

 

    以上提供的方法只做您遇到類似問題時的一種參考,是術,方法千變萬化而道理不離其宗,合理使用緩衝和非同步處理是解決這一類問題的核心。
    

      

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.