<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] # 分析 ## 協處理器-coprocessor 協處理器有兩種:observer和endpoint Observer允許集群在正常的客戶端操作過程中可以有不同的行為表現 Endpoint允許擴展集群的能力,對客戶端應用開放新的運算命令 ![](https://box.kancloud.cn/6590117d3aaf0a1a4e6f8c603f734e8f_420x342.png) ![](https://box.kancloud.cn/b0f1058b7d334185cf8a8393f2962f12_488x420.png) 1. 客戶端發出put請求 2. 該請求被分派給合適的RegionServer和region 3. coprocessorHost攔截該請求,然后在該表上登記的每個RegionObserver上調用prePut() 4. 如果沒有被prePut()攔截,該請求繼續送到region,然后進行處理 5. region產生的結果再次被CoprocessorHost攔截,調用postPut() 6. 假如沒有postPut()攔截該響應,最終結果被返回給客戶端 * Observer的類型 1. RegionObs——這種Observer鉤在數據訪問和操作階段,所有標準的數據操作命令都可以被pre-hooks和post-hooks攔截 2. WALObserver——WAL所支持的Observer;可用的鉤子是pre-WAL和post-WAL 3. MasterObserver——鉤住DDL事件,如表創建或模式修改 ## 二級索引 row key在HBase中是以B+ tree結構化有序存儲的,所以scan起來會比較效率。單表以row key存儲索引,column value存儲id值或其他數據 ,這就是Hbase索引表的結構。 由于HBase本身沒有二級索引(Secondary Index)機制,基于索引檢索數據只能單純地依靠RowKey,為了能支持多條件查詢,開發者需要將所有可能作為查詢條件的字段一一拼接到RowKey中,這是HBase開發中極為常見的做法 比如,現在有一張1億的用戶信息表,建有出生地和年齡兩個索引,我想得到一個條件是在杭州出生,年齡為20歲的按用戶id正序排列前10個的用戶列表。 有一種方案是,系統先掃描出生地為杭州的索引,得到一個用戶id結果集,這個集合的規模假設是10萬。然后掃描年齡,規模是5萬,最后merge這些用戶id,去重,排序得到結果。 這明顯有問題,如何改良? 保證出生地和年齡的結果是排過序的,可以減少merge的數據量?但Hbase是按row key排序,value是不能排序的。 變通一下——將用戶id冗余到row key里?OK,這是一種解決方案了,這個方案的圖示如下: ![](https://box.kancloud.cn/7be7fcb3cb8c91ecb166e85304413bfb_418x290.png) merge時提取交集就是所需要的列表,順序是靠索引增加了_id,以字典序保證的。 按索引查詢種類建立組合索引。 在方案1的場景中,想象一下,如果單索引數量多達10個會怎么樣?10個索引,就要merge 10次,性能可想而知。 ![](https://box.kancloud.cn/7ee51ae9414c930e844dad2828b3cb0d_464x318.png) 解決這個問題需要參考RDBMS的組合索引實現。 比如出生地和年齡需要同時查詢,此時如果建立一個出生地和年齡的組合索引,查詢時效率會高出merge很多。 當然,這個索引也需要冗余用戶id,目的是讓結果自然有序。結構圖示如下: ![](https://box.kancloud.cn/13c73d7c850e8227341b7a43046d01cf_283x371.png) 這個方案的優點是查詢速度非常快,根據查詢條件,只需要到一張表中檢索即可得到結果list。缺點是如果有多個索引,就要建立多個與查詢條件一一對應的組合索引 而索引表的維護如果交給應用客戶端,則無疑增加了應用端開發的負擔 通過協處理器可以將索引表維護的工作從應用端剝離 * 利用Observer自動維護索引表示例 在社交類應用中,經常需要快速檢索各用戶的關注列表t_guanzhu,同時,又需要反向檢索各種戶的粉絲列表t_fensi,為了實現這個需求,最佳實踐是建立兩張互為反向的表: * 一個表為正向索引關注表 “t_guanzhu”: Rowkey: A-B f1:From f1:To * 另一個表為反向索引粉絲表:“t_fensi”: Rowkey: B—A f1:From f1:To 插入一條關注信息時,為了減輕應用端維護反向索引表的負擔,可用Observer協處理器實現: ![](https://box.kancloud.cn/3c181a9f91fcac7868039dcf826e49b7_1052x395.png) # 代碼 1. 編寫代碼 ~~~ package com.study; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver; import org.apache.hadoop.hbase.coprocessor.ObserverContext; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import org.apache.hadoop.hbase.regionserver.wal.WALEdit; import java.io.IOException; public class FFCoprocessor extends BaseRegionObserver { @Override public void prePut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException { Configuration conf = HBaseConfiguration.create(); Connection conn = ConnectionFactory.createConnection(conf); //二級索引表 Table table = conn.getTable(TableName.valueOf("index_user")); //攔截到原始put對象中的rowkey和列的Value byte[] row = put.getRow(); String rowkey = new String(row); Cell addressCell = put.get("info".getBytes(), "name".getBytes()).get(0); byte[] valueArray = addressCell.getValueArray(); String address = new String(valueArray,addressCell.getValueOffset(),addressCell.getValueLength()); String[] user_fensi = rowkey.split("-"); Put putIndex = new Put((user_fensi[1]+"-"+user_fensi[0]).getBytes()); putIndex.addColumn("info".getBytes(), "name".getBytes(),address.getBytes()); table.put(putIndex); table.close(); } } ~~~ 2. 打成jar包“coprocess.jar”上傳hdfs ~~~ hadoop fs -put coprocess.jar / ~~~ 3. 創建表 ~~~ create 'user_guanzhu','info' create 'index_user','info' ~~~ 4. 修改schema,注冊協處理器 需要先disable一下 ~~~ disable 'user_guanzhu' ~~~ 注意下面的表名,jar包和類名修改為自己的 ~~~ alter 'user_guanzhu',METHOD => 'table_att','coprocessor'=>'hdfs://master:9000/coprocess.jar|com.study.FFCoprocessor|1001|' ~~~ 啟用這個表 ~~~ enable 'user_guanzhu' ~~~ 5. 檢查是否注冊成功 ~~~ describe 'user_guanzhu' ~~~ 6. 向正向索引表中插入數據進行驗證 ~~~ put 'user_guanzhu','zhangsan-liuyifei','f1:adress','beijing' ~~~ # 刪除協處理器 ~~~ 先disable表 disable 'user_guanzhu' 刪除,$1表示是第一個協處理器 alter 'user_guanzhu',METHOD=>'table_att_unset',NAME=>'coprocessor$1' 再enable表 enable 'user_guanzhu' ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看