设置系统相关属性,实现打开的窗体以重叠任务栏窗口不重叠形式显示

Android面试题拾掇(上)_Eclipse RCP施用系统开发方法与实战2- 定制应用程序窗口属性_HBase高级配置跟调整(1)__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
Android面试题拾掇(上)
Eclipse RCP施用系统开发方法与实战2- 定制应用程序窗口属性
HBase高级配置跟调整(1)
Android面试题拾掇(上)
Android面试题整理(上)
1.Android 常用5大布局?
FrameLayout(框架布局):一般也说是帧布局。特点就是放上去的界面是重叠的,就像抽纸巾一样,抽了一张就是下面一张。
LinearLayout (线性 布局):LinearLayout:线性布局,每一个LinearLayout里面又可分为垂直布局和水平布局。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
AbsoluteLayout(绝对布局): 绝对布局用X,Y坐标来指定元素的位置,这种布局方式也比较简单,但是在屏幕旋转时,往往会出问题,而且多个元素的时候,计算比较麻烦。
RelativeLayout (相对布局):相对布局可以理解为某一个元素为参照物, 来定位的布局方式。用的好这个是很犀利的布局。他的效率是最高的。
TableLayout (表格布局): 表格布局,每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素。每一个布局都有自己适合的方式,这五个布局元素可以相互嵌套应用,做出美观的界面。2.Android 中的两种动画类型?
Tween 动画 :移动,放大,缩小,旋转,透明度
Frame 动画 :传统动画3.Android 中常用的5种数据存储方式?
1. SharedPreference
SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的
一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键
值的方式存储,可以简单的读取与写入.
2. 文件存储 (FIleInputStream/FileOutputStream)
文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中
实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读
取设备上的文件。
此保存方式比较适合游戏的保存和使用,可以保存较大的数据,并且可以将自己
的数据存储到文件系统或者数据库当中,也可以将自己的数据存储到SQLite数据库中
4.ContentProvider (不推荐用于游戏保存)
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,
就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问
方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操
作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读
写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式
5.网络存储
网络存储方式,需要与Android 网络数据包打交道
以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。4.Android中Activity的生命周期
onCreate——onStart——onResume——onPause——onStop——onDestroy
onCreate: 在这里创建界面 ,做一些数据 的初始化工作
到这一步变成用户可见不可交互 的
onResume: 变成和用户可交互 的,(在activity 栈系统通过栈的方式管理这些Activity的最上面,运行完弹出栈,则回到上一个Activity)
到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU的事情,从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动.
变得不可见 ,被下一个activity覆盖了
onDestroy:
这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方 法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。
Activity正常启动,他们被调用的顺序是 onCreate -& onStart -& onResume
Activity被干掉,他们被调用的时顺序是onPause -& onStop -& onDestroy
Activity如果中止的时候新出的一个Activity是全屏的那么:onPause-&onStop
Activity恢复的时候onStart-&onResume
Activity如果打断
这个应用程序的是一个Theme为Translucent 或者Dialog 的Activity那么只是onPause ,恢复 的时候onResume 。5.Android四大组件,以及作用?Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的食物,定义好需要接受的Intent提供同步和异步的接口Content Provider:是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的借口模型,大大简化上层应用,对数据的整合提供了更方便的途径BroadCast Receiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型
6.如何启用Service,如何停用Service。Context.startService()
Context.bindService().Context.stopService()
Service.stopSelf() or Service.stopSelfResult()
Eclipse RCP施用系统开发方法与实战2- 定制应用程序窗口属性
Eclipse RCP应用系统开发方法与实战2-- 定制应用程序窗口属性 写道
定制应用程序窗口属性
向导生成的应用程序主界面并不能满足要求,存在很多问题,例如,主界面运行时没有自动居中,主界面大小没有固定,主窗口标题栏文字应该是“高校经费测算系统”。再看看图5-3、图5-4的标题栏有区别没有?当然有,图5-3所示界面的标题栏是很漂亮的弧线形,而图5-4所示界面的标题栏则不是。如此等等,需要重新设置。
1.闪屏画面
应用程序主界面显示之前往往需要做一些初始化处理工作,就是启动时间可能稍微长一些,如果没有任何提示,用户可能会感到困惑,闪屏画面能够较好地解决这个问题。准备一幅24bit色BMP格式的图片,注意图片大小不要超过500mm×300mm。将该图片复制到项目文件夹中替换掉原来的splash.bmp文件即可。
2.不保存窗口状态
将ApplicationWorkbenchAdvisor.java的initialize()方法中的语句:configurer.setSaveAndRestore(true);
修改为:configurer.setSaveAndRestore(false);
前文说过,设置为true,应用程序每次退出时将保存窗口状态,此处并不需要且对性能有轻微影响,所以设置为false。
3.定制窗口式样
再来定制主窗口。前面已经介绍过,在ApplicationWorkbenchWindowAdvisor.java的preWindowOpen()方法中定制窗口式样,现在修改如下。
cn.edu.jfcs.app/ ApplicationWorkbenchWindowAdvisor.java
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
//窗口设定为800x600
configurer.setInitialSize(new Point(800, 600));
//暂时不显示工具栏
configurer.setShowCoolBar(false);
//显示状态栏
configurer.setShowStatusLine(true);
//窗口只显示最小化、关闭按钮
configurer.setShellStyle(SWT.MIN | SWT.CLOSE);
//设置窗口标题
configurer.setTitle("高校经费测算系统");
执行上步操作后,我们会发现configurer.setShellStyle(SWT.MIN | SWT.CLOSE)这句代码的旁边出现一个带红色叉叉的小灯泡,这意味着该行代码有问题,这是因为使用了SWT.MIN常量而又没有导入相应类。解决方法很简单,只需鼠标单击小灯泡,根据弹出的提示导入包import org.eclipse.swt.SWT即可,这也是Eclipse很贴心的小功能。现在运行看看,程序主界面已经有了较大变化。
程序中最后一句代码中的“高校经费测算系统”是一个自定义常量。一个系统中有很多类似的自定义常量,例如图片的名称、视图的名称等等,而这些常量可能不止一个地方需要使用到。一个很好的方法是创建一个接口文件,将全部常量的定义放置到该接口文件中,这样可以统一管理,而且维护方便。如果要修改某个常量的值,只需要到接口文件中修改就可以了。下面来实现该处理,新建一个包cn.edu.jfcs.sys,在该包下新建接口类 IAppConstants.java,代码类似于以下形式。
package cn.edu.jfcs.
public interface IAppConstants {
public static final String
APPLICATION_TITLE="高校经费测算系统";
现在只需要将 ApplicationWorkbenchWindowAdvisor.java中preWindowOpen()方法的 configurer.setTitle("高校经费测算系统")修改为 configurer.setTitle(IAppConstants.APPLICATION_ TITLE)即可。记得导入cn.edu.jfcs.sys.IAppConstants类。
以后还会不断往该接口文件中添加常量定义。为了避免不必要的麻烦,建议读者在实际操作时先将本书附带源代码的IAppConstants.java类直接复制到自己的项目中。
4.窗口自动居中
窗口居中需要手工编程实现,编写之前先得想想代码放在哪儿?还是放在preWindowOpen()方法中吗?当然不行,preWindowOpen()是配置窗口的构成元素,即形成窗口本身的构成部件,而居中则是定义窗口的位置,显然不属于窗口构成元素。 postWindowOpen()可以胜任此项工作,因为postWindowOpen()主要用来处理那些需要一个现成窗口才能进行的事件处理。
在代码编辑视图中单击鼠标右键,在弹出的快捷菜单中选择【Source】→【Override/ Implement Methods…】命令,弹出“Override/Implement Methods”对话框,勾选postWindowOpen()方法,默认将在光标所在处插入postWindowOpen()方法。这又是 Eclipse的一个很贴心的功能,希望读者熟练使用。改写该方法的代码如下:
cn.edu.jfcs.app/ ApplicationWorkbenchWindowAdvisor.java
public void postWindowOpen() {
//设置窗口自动居中
Shell shell = getWindowConfigurer().getWindow().getShell();
Rectangle screenSize = Display.getDefault().getClientArea();
Rectangle frameSize = shell.getBounds();
shell.setLocation((screenSize.width - frameSize.width) / 2,(
screenSize.height - frameSize.height) / 2);
该方法通过默认Display对象来设置屏幕宽度和高度,通过Shell对象获得当前窗口的宽度和高度,两者分别相减后再除以2,计算得到窗口左上角的(x,y)坐标。不要忘了导入相关的类,再看看运行后窗口是否自动居中。
5.设置视图标题栏的弧线形外观
大家肯定都喜欢图5-3所示界面中弧线形的标题栏,这种风格的标题栏涉及到工作台UI属性(org.eclipse.ui Preference):SHOW_TRADITIONAL_STYLE_TABS。可以通过三种方法进行设置。
(1)硬编码实现
硬编码实现是指通过直接编写代码实现。打开ApplicationWorkbenchAdvisor.java文件,修改initialize()方法代码如下:
cn.edu.jfcs.app/ ApplicationWorkbenchAdvisor.java
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);
configurer.setSaveAndRestore(false);
PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.
SHOW_TRADITIONAL_STYLE_TABS, false);
相关的属性很多,具体可以查看IWorkbenchPreferenceConstants接口文件。方法是,按住【Ctrl】键,将鼠标移动到IWorkbenchPreferenceConstants上面,IWorkbenchPreferenceConstants下面会出现下划线,单击鼠标左键即可。对于Eclipse的其他方法也是如此操作。这里先简单介绍几个常用属性。
IWorkbenchPreferenceConstants常见属性
名 属 性 说 明
EDITOR_MINIMUM_CHARACTERS 但很多编辑器重叠时,设置编辑器标题文字的最短长度。默认为8个字符
SHOW_PROGRESS_ON_STARTUP 设置启动时是否显示进度条。默认值false
DOCK_PERSPECTIVE_BAR 设置透视图标题栏停泊位置。默认值为TOP_RIGHT,还可以设置为TOP_LEFT、LEFT
SHOW_TEXT_ON_PERSPECTIVE_BAR 设置透视图是否显示标题文本。默认值为true
SHOW_INTRO 启动时是否显示欢迎画面。默认值为true
可能有些人喜欢每次启动时显示欢迎画面,则可以在initialize()方法中加入:
PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.SHOW_INTRO, true);
(2)修改产品默认配置文件
可以创建一个初始化配置文件,使用默认的配置文件名plugin_customization.ini。在项目名称上单击鼠标右键,选择【New】→【File】,在File name后输入plugin_customization.ini,单击【Finish】按钮,输入以下内容。
#设置视图标题栏的弧线形外观
org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
#编辑器标题栏提示文字最短长度
org.eclipse.ui/ EDITOR_MINIMUM_CHARACTERS =12
(3)自定义配置文件
如果你不喜欢默认的配置文件,完全可以更改配置文件名(本书采用这种方法),具体步骤如下。
① 双击pludin.xml文件,再单击“Extensions”页。
② 展开org.eclipse.core.runtime.products,在jfcs(Product)上单击鼠标右键,选择【New】→【property】。
③ 在Extension Element Details下的name后的文本框中输入属性名preferenceCustomization
(属性名不能更改),value后的文本框中输入AppPref.ini(可任意命名),具体如图5-10所示。若要查看 org.eclipse.core.runtime.products有哪些可供配置的属性,则只需要单击 org.eclipse.core.runtime.products名,然后再单击右边的Open extension point description,Eclipse将打开关于Products扩展点的属性描述,如图5-11所示。注意到该属性默认的文件正是前面所说的 plugin_customization.ini。
添加属性设置视图
org.eclipse.core.runtime.products扩展点描述
④ 在项目名称上单击鼠标右键,选择【New】→【File】,在File name后输入AppPref.ini,单击【Finish】按钮,输入配置内容即可。
这里提醒一下,如果做了很多设置,而运行时似乎没有生效,这是由于Eclipse缓存了旧配置信息。解决方法:选择系统菜单的【Run】→【Run…】,弹出“Run”对话框,先单击“Eclipse Application”,再单击“jfcs”,勾选“Clean workspace data before launching”,不要勾选“Ask for confirmation before cleaning”。这样可以保证每次运行都是最新结果,设置画面如图5-12所示。
运行设置对话框
SHOW_INTRO 比较特别。如果使用ini配置文件的方式,无论使用默认配置文件还是自定义配置文件,产品打包发布后(不在Eclipse环境中运行)只是首次启动时出现欢迎画面,这是因为Eclipse在运行结束时会修改工作空间目录中org.eclipse.ui.prefs文件的showIntro=false,所以下次启动时将不会出现欢迎画面。如果希望程序每次启动时都出现欢迎画面,需要采取硬编码的方式!
HBase高级配置跟调整(1)
HBase高级配置和调整(1)
在对HBase集群进行调整之前,你需要先知道它的性能如何。因此,我们将使用Yahoo! Cloud Serving Benchmark(YCSB,雅虎云服务基准)来测量HBase集群的性能(基准性能测试)。
HBase集群基本上可按负载类型分为两类:写密集的集群和读密集的集群。每种类型的调优选项不同。许多调优方案都需要在写性能和读性能之间作出权衡。我们将介绍几种调整HBase集群以获得更好写入性能的方法,同时我们也将介绍几种调整读密集HBase集群的方法。这些方法包括服务器端配置、客户端配置和表模式选择。
没有一种调整能够适用于所有的情形。你需要仔细考虑你的系统的性能要求,然后调整集群以获得写入性能和读取性能之间的最佳平衡。
一、使用YCSB对HBase集群进行基准测试
测量HBase集群的性能(或对集群进行基准性能测试)与集群调优本身一样重要。HBase集群需要测量的性能特性至少包括以下这些内容:
集群的总体吞吐量(每秒的操作数)
集群的平均延迟时间(每个操作的平均时间)
操作延迟的分布情况
YCSB是一个很棒的工具,可对HBase集群进行基准性能测试。YCSB支持以并行方式运行可变的负载测试,可以评估系统的插入、更新、删除和读取性能。因此,对于写密集和读密集HBase集群都可以使用YCSB来进行基准性能测试。每个测试都可以配置其要加载的记录数、要执行的操作次数、读写比以及许多其他属性,这样就可以很容易地使用YCSB来测试集群的不同负载情形。
YCSB也可以用于对许多别的键-值存储进行性能评估。YCSB的常见用途就是对多个系统进行基准测试,然后对它们的性能进行比较。
HBase带有一个自己的性能评价(PE)的工具,它也可以用来对HBase进行基准测试。
二、增加RegionServer的处理线程数
RegionServer要保持一定数量的线程处于运行状态,以此来响应传入的对于用户表的请求。为了防止RegionServer在运行时耗尽内存,该线程数默认都设得非常低。在很多情况下,尤其是在有大量并发客户端的时候,为了能处理更多请求,你需要将该值调高。
vi $HBASE_HOME/conf/hbase-site.xml
&property&
&name&hbase.regionserver.handler.count&/name&
&value&40&/value&
&/property&
hbase.regionserver.handler.count属性可控制RPC侦听程序的线程数。该属性的默认值为10。这是一个相当低的值,这样设置的目的是防止RegionServer在某些情况下出现耗尽内存的情况。
如果RegionServer上的可用内存较少,就应该将该属性设为一个较低的值。较低的值也适用于需要大量内存才能对请求进行处理的情形(比如将大值写入HBase或在大型缓存中扫描数据)。将hbase.regionserver.handler.count属性设为较高值意味着可以有更多的并发客户端,这可能会消耗掉很多RegionServer的内存,甚至有可能会用光所有的内存。
如果每个请求只需要一点点内存,但每秒的交易次数(TPS)却很高,那么就应该将该属性设为一个较大的值,以使RegionServer可以处理更多的并发请求。
在调整该属性的同时,建议启用RPC级的日志记录功能,然后监控每个RPC请求的内存使用情况和GC状态。
三、使用自定义算法预创建区域
当我们在HBase中创建一张表时,该表一开始只有一个区域。插入该表的所有数据会保存在这个区域中。随着数据的不断增加,当该区域的大小达到一定阀值时,就会发生区域分割(Region Splitting)。这个区域会分成两半,以便使该表可以处理更多的数据。
在写密集的HBase集群中,区域分割会带来以下几个需要解决的问题。
分割/合并风暴问题。
如果数据均匀地增长,大部分区域就会在同一时间发生分割,从而导致大量的磁盘I/O和网络流量。
只有在分割出了足够多个区域之后,负载才会均衡。
尤其是在表刚创建时,所有请求都会发给首个区域所在的那台RegionServer。
对于第一个问题,可以参考“HBase基本性能调整”的“管理区域分割”一节,可通过手动分割的方法来解决。
对于第二个问题,可以参考“在数据移入HBase前预创建区域”一节,可通过在创建表时预先创建好一些区域的方法来避免这一问题。使用HBase的RegionSplitter工具来预创建区域的方法。
在默认情况下,RegionSplitter实用工具会使用MD5算法来生成MD5校验和,以此来作为区域的开始键。键值的范围是“”到“7FFFFFFF”。这种算法(HexStringSplit)适用于很多情况,但在有些情况下,你可能更需要使用一种自己的算法来生成键值,以使负载能在集群中分散开来。
HBase的行键完全由向HBase写入数据的应用程序所控制,在很多情况下,(由于这样或那样的原因)行键的范围和分布情况是可以预测的。因此,可以先计算出各区域的分割键,然后再使用这些分割键来创建预分割区域。
我们将使用一组记录在文本文件中的区域开始键来创建表的预定义区域。
1.创建一个split-keys文件。在该文件中输入一组区域分割键,每个键一行。假设该文件包含有如下一些开始键:
$ cat split-keys
2.创建Java类FileSplit,用它来实现org.apache.hadoop.hbase.util.RegionSplitter.SplitAlgorithm接口。
import org.apache.hadoop.hbase.util.B
import org.apache.hadoop.hbase.util.RegionSplitter.SplitA
public class FileSplit implements SplitAlgorithm {
// public static final String SPLIT_KEY_FILE = "split-keys";
private String splitKeyF
public FileSplit (String splitKeyFile) {
this.splitKeyFile = splitKeyF
public byte[] split(byte[] start, byte[] end) {
public byte[][] split(int numberOfSplits) {
BufferedReader reader=
List&byte[]& regions = new ArrayList&byte[]&();
//一行一行读
reader = new BufferedReader(new FileReader(splitKeyFile));
while ((line = reader.readLine()) != null) {
System.out.println(line);
if (line.trim().length() & 0) {
regions.add(Bytes.toBytes(line));
return regions.toArray(new byte[0][]);
} catch (IOException e) {
throw new RuntimeException("Error reading splitting keys from " + splitKeyFile, e);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) reader.close();
} catch (IOException e) {
e.printStackTrace();
public byte[] firstRow() {
public byte[] lastRow() {
public byte[] strToRow(String input) {
public String rowToStr(byte[] row) {
public String separator() {
3.编译该Java文件。
$ javac -classpath $HBASE_HOME/hbase-0.92.0.jar FileSplit.java
4.将包含有分割键信息的split-keys文件复制到编译生成FileSplit类的目录下。
5.运行如下脚本来在创建表的时候预创建一些区域。
$ export HBASE_CLASSPATH=$HBASE_CLASSPATH:./
$ $HBASE_HOME/bin/hbase org.apache.hadoop.hbase.util.RegionSplitter -D split.algorithm=FileSplit -c 2 -f f1 test_table
6.通过HBase的Web用户界面确认表和预定义区域是否已正确创建。
HBase带有一个名为RegionSplitter的实用工具,该类可以用于:
创建带预分割区域的HBase表
对现有的表中的所有区域进行滚动分割
使用自定义算法来分割区域
为了能在创建表时分割区域,只需要像第2步那样实现一下split()方法。RegionSplitter类会调用该方法来对整张表进行分割。在我们的实现中,该方法会从我们准备好的文件中读取分割键(每个键一行),然后将它们转换并保存在一个存储该表所有初始区域的分割键的byte[]数组中。
为了能使用该类来分割区域,我们将FileSplit类加入到了HBASE_CLASSPATH中,然后以带如下参数的方式调用了RegionSplitter实用程序。
-D split.algorithm=FileSplit:指定分割算法。
-c 2:表分割的区域数。在本实现中没有用到。
-f f1:创建一个名为“f1”的列族。
test_table:待创建的表的名称。
正如你在第6步中看到那样,我们用4个分割键将test_table分成了5个区域。这4个分割键正是我们写在split-keys文件中的内容。
该表的其他属性都使用了默认值,你可以在HBase Shell中使用alter命令来修改其中的一些属性。
请注意,即便是在对区域进行过分割之后,也仍然需要在应用层对行键进行设计,以避免将过多连续的行键写入同一个区域。你需要仔细地选择,找到一种适合你的数据访问模式的分割算法。
该方法的另一个适用场景是用来提高将HBase表导出备份的数据导入回HBase的速度。
你可以使用一个简单的脚本来备份各区域的开始键。有了FileSplit类,我们可以使用原来的这些键来恢复HBase表的区域边界,然后再以使用导出数据文件进行导入的方式来恢复数据。
与将数据导入到同一个区域相比,这种方法能够显著提高数据恢复的速度,因为它会提前在多台RegionServer上恢复好多个区域,并且让这些区域均衡分布在多台RegionServer上。
四、避免写密集集群中的更新阻塞
在写密集的HBase集群中,你可能会发现有写入速度不稳定的现象。大多数写操作都非常快,但有些写操作却非常慢。对于一个在线系统来说,无论平均速度如何,这种写入速度的不稳定都是不可接受的。
导致这种情况的原因可能有两个:
分割/合并使得集群的负荷非常高
更新操作被RegionServer给阻塞住了
正如我们在“HBase基本性能调整”中描述的那样,你可以通过“禁用自动分割/合并,然后在低负载时手动进行分割/合并”的方式来避免分割/合并问题。
要在RegionServer日志中进行一下查找,如果发现很多带“Blocking updates for ...”字样的消息,说明很可能就有很多更新都被阻塞住了,这样的更新操作的响应时间可能就是非常差。
若要解决这类问题,必须同时对服务器端和客户端的配置作出调整,才能获得稳定的写入速度。
vi $HBASE_HOME/conf/hbase-site.xml
&property&
&name&hbase.hregion.memstore.block.multiplier&/name&
&value&8&/value&
&/property&
&property&
&name&hbase.hstore.blockingStoreFiles&/name&
&value&20&/value&
&/property&
HBase写入操作的工作流程。
数据的修改首先会被写入到了RegionServer的HLog(WAL预写日志)中,以此方式来持久化在HDFS中。然后,该修改被传给了宿主HRegion,然后传入到其所属列族的HStore的内存空间里(即MemStore)。当MemStore的大小达到一定阀值时,数据修改会被写入到HDFS上的StoreFile中。StoreFiles在内部使用HFile文件格式来存储数据。
HBase是一种多版本并发控制(MVCC,Multiversion Concurrency Control)的架构。在更新/删除任何旧数据时,HBase都不会进行覆盖,而是给数据增加一个新版本。这使得HBase的写速度非常快,因为所有写操作都是顺序化的操作。
如果HDFS上的小StoreFile太多,HBase就会启动合并操作来将它们重写为几个大一些的StoreFile,同时减少StoreFile文件的数量。当一个区域的大小达到一定阀值时,它又会被分成两个部分。
为了防止合并/分割的时间过长并导致内存耗尽的错误,在某一区域的MemStore的大小达到一定阀值时,HBase会对更新进行阻塞。该阀值的定义为:
hbase.hregion.memstore.flush.size 乘以 hbase.hregion.memstore.block.multiplier
hbase.hregion.memstore.flush.size属性指定了MemStore在大小达到何值时会被写入到磁盘中。其默认值是128MB(0.90版本是64MB)。
hbase.hregion.memstore.block.multiplier属性的默认值是2,这意味着,如果MemStore的大小达到了256MB(128 * 2),该区域上的更新将被阻塞。对于写密集集群的更新高峰期来说,这个值太小了,所以我们要调高该阻塞阀值。
我们通常会让hbase.hregion.memstore.flush.size属性保持为默认值,然后将hbase.hregion.memstore.block.multiplier属性调整为一个较大的值(比如8),以此来提高MemStore阻塞阀值,减少更新阻塞发生的次数。
请注意,调高hbase.hregion.memstore.block.multiplier会增大写盘时出现合并/分割问题的可能性,所以调整时一定要小心。
第2步适用于另一种阻塞情况。如果任何一个Store的StoreFiles数(每个写盘MemStore一个StoreFile)超过了hbase.hstore.blockingStoreFiles(默认为7),那么该区域的更新就会被阻塞,直到合并完成或超过hbase.hstore.blockingWaitTime(默认90秒)所指定的时间为止。我们将它加大到了20,这对于写密集集群来说是一个相当大的值了。这样做的副作用是:会有更多的文件需要合并。
这种调整通常会减少更新阻塞的发生机会。然而,正如我们刚才提到的那样,它也有副作用。建议在调整这些设置时务必小心,调整期间务必时刻观察写操作的吞吐量和延迟时间,这样才能找到最佳的配置值。
五、调整MemStore内存大小
HBase的写操作会首先在所属区域的MemStore中生效,然后要等到MemStore的大小达到一定阀值之后才会被写入HDFS,从而省出一部分内存空间。MemStore的写盘操作以后台线程的方式运行,使用的是MemStore的快照。因此,即便是在MemStore写盘时,HBase仍可以一直处理写操作。这使得HBase的写入速度非常快。如果写操作的高峰值高到MemStore写盘都跟不上趟的程度,那么写操作填满MemStore的速度就会不断提高,而MemStore的总内存使用量也将继续升高。如果某一RegionServer中所有MemStore的总大小达到了某一可配置的阀值,更新又会被阻塞,并且强制进行写盘。
调整MemStore总体内存的大小以避免发生更新阻塞。
vi $HBASE_HOME/conf/hbase-site.xml
&property&
&name&hbase.regionserver.global.memstore.upperLimit&/name&
&value&0.45&/value&
&/property&
&property&
&name&hbase.regionserver.global.memstore.lowerLimit&/name&
&value&0.4&/value&
&/property&
hbase.regionserver.global.memstore.upperLimit属性控制了一台RegionServer中所有MemStore的总大小的最大值,超过该值后,新的更新就会被阻塞,并且强制进行写盘。这是一项可防止HBase在写入高峰时耗尽内存的配置信息。该属性默认为0.4,这意味着RegionServer堆大小的40%。
该默认值在很多情况下都可以很好地发挥作用。但是,如果RegionServer日志中出现了许多含有Flush of region xxxx due to global heap pressure的日志,那么可能就需要调整该属性来处理这种高写入速度了。
在第2步中,我们调整了hbase.regionserver.global.memstore.lowerLimit属性,它指定了何时对MemStores进行强制写盘,系统会一直进行写盘直到MemStore所占用的总内存大小低于该属性的值为止。其默认值是RegionServer堆大小的35%。
在写密集集群中,调高这两个值有助于减少更新因MemStore大小限制而被阻塞的机会。另一方面,调整时必须十分小心,避免引发全垃圾回收或出现内存耗尽的错误。
通常情况下,写密集集群上的读性能不像写性能那么重要。因此,我们可以为了优化写操作而调整集群。优化方法之一就是:减少分配给HBase块缓存的内存空间,将空间留给MemStore。关于如何调整块缓存的大小,请参见“调高读密集集群的块缓存大小”一节。
六、低延迟系统的客户端调节
前面两节介绍的是避免服务器端阻塞的方法。可以帮助集群稳定、高性能地运行。服务器端的调整可以显著改善集群的吞吐量和平均延迟时间。
然而,在低延迟系统和实时系统中,只进行服务器端的调优还不够。在低延迟系统中,长时间的停顿即使只是偶尔发生一两次也不可以接受。
为了避免长时间的停顿,还要对客户端进行一些调节。
在写密集集群中进行客户端调整的步骤如下。
vi $HBASE_HOME/conf/hbase-site.xml
&property&
&name&hbase.client.pause&/name&
&value&20&/value&
&/property&
&property&
&name&hbase.client.retries.number&/name&
&value&11&/value&
&/property&
&property&
&name&hbase.ipc.client.tcpnodelay&/name&
&value&true&/value&
&/property&
&property&
&name&ipc.ping.interval&/name&
&value&4000&/value&
&/property&
在第1步和第2步中调整hbase.client.pause和hbase.client.retries.number属性的目的是:让客户端在连接集群失败时能在很短的时间内迅速重试。
hbase.client.pause属性控制的是让客户端在两次重试之间休眠多久。其默认值是1000毫秒(1秒)。hbase.client.retries.number属性用来指定最大重试次数。其默认值是10。
每两次重试之间的休眠时间可按下面这个公式计算得出。
pause_time = hbase.client.pause * RETRY_BACKOFF[retries]
其中,RETRY_BACKOFF是一个重试系数表,其定义如下。
public static int RETRY_BACKOFF[] = { 1, 1, 1, 2, 2, 4, 4, 8, 16, 32};
在重试10次以后,HBase就会一直使用最后一个系数(32)来计算休眠时间。
如果将暂停时间设为20毫秒,最大重试次数设为11,每两次连接集群重试之间的暂停时间将依次为:
{ 20, 20, 20, 40, 40, 80, 80, 160, 320, 640, 640}
这就意味着客户端将在2060毫秒内重试11次,然后放弃连接到集群。
在第3步中,我们将hbase.ipc.client.tcpnodelay设为了true。此设置将禁止使用Nagle算法来进行客户端和服务器之间的套接字传输。
Nagle算法是一种提高网络效率的手段,它会将若干较小的传出消息存在缓冲区中,然后再将它们一次全都发送出去。Nagle算法默认是启用的。低延迟系统应该将hbase.ipc.client.tcpnodelay设置为true,从而禁用Nagle算法。
在第4步中,我们将ipc.ping.interval设为了4000毫秒(4秒),这样客户端和服务器之间的套接字传输就不会超时。ipc.ping.interval的默认值是1分钟,对于低延迟系统来说,这有点太长了。
你也可以在客户端代码中使用org.apache.hadoop.hbase.HBaseConfiguration类来覆盖之前在hbase-site.xml中设置的各属性的值。下面代码可以实现与前面的第1步和第2步设定同样的效果。
Configuration conf = HBaseConfiguration.create();
conf.setInt("hbase.client.pause", 20);
conf.setInt("hbase.client.retries.number", 11);
HTable table = new HTable(conf, "tableName");
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:}

我要回帖

更多关于 excel表格窗口重叠 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信