借助hbase的讀寫思路做數倉
hbase讀寫速度快(與HDFS對比)是基於兩方面:
1)用戶寫(入cache)和(cache)寫入硬盤是異步的
2)有-root-和-meta-表,能夠快速定位表的位置 => 成為物理化的標准索引
詳見:https://www.cnblogs.com/sabertobih/p/14001268.html
設計案例
需求描述:在mysql中存在2億數據,全是真葯。葯品id如果在庫中不存在,則為假葯。
要求給一個葯品id,能立刻判斷出是真葯假葯?
設計思路:
1)給mysql的id建立索引 => 會快一些,但僅僅是一些
2)在高速緩存中建立索引表,所有id插入key:value(set集合)時用加鹽哈希分桶,存儲set集合(防止mysql中真要id有重復)
=> 這樣我給一個id=12345,根據索引定位進某個桶,遍歷1000size的數據
=> 沒找到即為真葯 => 添加進mysql+redis
找到即為假葯
優點:原本遍歷mysql2億數據量,現在只需要遍歷1000數據量
插入索引表
public static String tucketNo(int i){ // 此方法如果String值特別大會出現負數 // hadoop默認的hashpartitioner中為了解決這個問題,使用與運算:(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks; return (i+"").hashCode()%100000+""; // 這里可以用abs取絕對值,否則生成200000個桶 } Jedis jedis = new Jedis("192.168.56.111",6379); Pipline pip = jedis.pipelined(); // 開啟Jedis的多線程操作 for (int i = 0; i <200000000 ; i++) { pip.sadd(tucketNo(i),i+""); // 看進度條的 if(i%100000==0){ Thread.sleep(50); System.out.println(i); } } pip.syns(); jedis.close();
性能測試
Jedis jedis = new Jedis("192.168.56.111",6379); int no = 123344; long time = System.currentTimeMillis(); // 這個桶(value是set的key)是不是存在no這個數? System.out.println(jedis.sismember(tucketNo(no),no+"")); // 判斷是否redis某個桶中存在某個數只花費了___milliseconds System.out.println(System.currentTimeMillis()-time);
實現葯品需求偽代碼:找不到id則另開線程,異步寫入緩存+mysql
if 找不到這個id => new Thread(new Runnable(){ @overrideid public void run(){ sout("id插入數據庫mysql") jedis.sadd(tucketNo(no),no+""); // id插入索引 sout() } }).start()