云平台调整建议

一,建立最少的列簇
1,用户表
将用户基本信息放入一个列簇中(如nickname,gender等),将好友,标签等有大量列的单独存放,这样用户表成为5个列簇
2,信息表、用户关系等基本表都改为一个列簇
调整依据:更少的列簇,更少的io
分析:一个HRegion中所有HStore中MemStore的大小总和到达阀值时就会进行flush操作(解释:可大概理解为同一个表中的所有列簇会同时flush),若是多个列簇,就会同时对多个hstore下的文件进行写入,同时牵扯到该hregion下的所有hstore文件是否需要进行合并及拆分的验证加查,及进行相应的合并及拆分操作等一连串反映。
代码如下:

long flushSize = regionInfo.getTableDesc().getMemStoreFlushSize();


if (flushSize == HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE) {


flushSize = conf.getLong(“hbase.hregion.memstore.flush.size”,


HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE);


this.memstoreFlushSize = flushSize;



二,建立比较合理的hregion个数,及修改hbase0.90错误



代码分析:


  hbase在每次put以前,需要检查当前regionserver上的memstore是否超过总memstore阀值,如果超过,需要block住当前的写入,防止OOM,代码片段见下: 

Java代码  



  • /**
  •    * Check if the regionserver's memstore memory usage is greater than the
  •    * limit. If so, flush regions with the biggest memstores until we're down
  •    * to the lower limit. This method blocks callers until we're down to a safe
  •    * amount of memstore consumption.
  •    */  
  •   public synchronized void reclaimMemStoreMemory() {  
  •     if (isAboveHighWaterMark()) {  
  •       lock.lock();  
  •       try {  
  •         while (isAboveHighWaterMark() && !server.isStopped()) {  
  •           wakeupFlushThread();  
  •           try {  
  •             // we should be able to wait forever, but we've seen a bug where  
  •             // we miss a notify, so put a 5 second bound on it at least.  
  •             flushOccurred.await(5, TimeUnit.SECONDS);  
  •           } catch (InterruptedException ie) {  
  •             Thread.currentThread().interrupt();  
  •           }  
  •         }  
  •       } finally {  
  •         lock.unlock();  
  •       }  
  •     } else if (isAboveLowWaterMark()) {  
  •       wakeupFlushThread();  
  •     }  
  •   }  


    这是一个同步操作,其中isAboveHighWaterMark()的代码如下: 

Java代码  



  • private boolean isAboveHighWaterMark() {  
  •   return server.getGlobalMemStoreSize() >= globalMemStoreLimit;  
  • }  


    getGlobalMemStoreSize()里面的操作是遍历所有region,拿到每个region的memstore大小: 

Java代码  



  • public long getGlobalMemStoreSize() {  
  •   long total = 0;  
  •   for (HRegion region : onlineRegions.values()) {  
  •     total += region.memstoreSize.get();  
  •   }  
  •   return total;  
  • }  


    如果region数量很多就比较杯具了,在单台服务器3500个region的环境下通过btrace跟踪到这一步需要耗时0.4ms,也就是每一个put会block所有线程0.4ms,这样无法发挥出server端并行处理能力,同时可以计算出无论如何配置,写tps无法超过1000/0.4=2500! 
    产生这个问题的根本原因是在0.90.x版本中,region无法拿到regionserver的信息,因此只能通过实时计算来得到rs上总的memstore大小。在0.92.0或trunk版本中修改了HRegion的数据结构,让HRegion在初始化时得到regionserver的信息,因此可以实时记录memstore的总大小,并让每个region对象能拿到该值,于是这个isAboveHighWaterMark()就不再block住所有线程了,在region较多的场景下写性能得到较大提升。 
建议 :治标手动操作将hregion大小合并到一个合理的范围
根本解决:翻看0.92的patch包,将jar包中的class文件做好备份进行替换测试。
参考于: http://koven2049.iteye.com/blog/1144526 
减少hregion性能会有成倍提升,可以先进行手动合并hregion的测试

你可能感兴趣的:(java,数据结构,测试,hbase,平台,代码分析)