首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

MySQL Group Replication 学习笔记

作者简介 刘伟 云和开创高级顾问 题记:group replication作为mysql官方,在5.7版本阶段开发的,innodb的分布式数据库架构,从发布开始就有很多关注,下文是我对目前为止的材料以及实验的一些总结。 主要资料来源是官方blog:http://mysqlhighavailability.com/ group replication架构 group replication(后文简称GR)实现的分布式数据库架构,底层的分布式基础是Paxos(出于行文限制,此处不单独交代Paxos)。通过Paxos来保证分布式数据库系统中,事务的提交顺序。 每次一个事务在一个节点提交的时候,就会发送所修改的数据到所有节点,检查期间是否有修改冲突(比如修改了别的节点已经修改并提交成功的事务的数据),如果发现冲突,本事务回滚。如果没有冲突,则可以直接提交成功。 对于非执行事务的远程节点,如果事务判断为执行成功,远程发送过来的数据,会被保存在本地的一个relay log里面(注意,与常规主从同步使用的relay log不是同一组),之后由从库的applier线程采用正常主从同步(目前已经支持LOGICAL_CLOCK并行执行)的方式执行掉对应的relay log。 这里有一个临界点,如果一个事务刚刚被写入relay log,还没有来得及执行掉,这时候有一个事务的执行涉及了相关的数据,那么后来的这个事务在执行阶段可以执行成功,但是必定会在提交阶段失败的。 使用建议 根据目前的状况看,GR使用的时候,应该做到以下几点以对性能优化以及减少分布式冲突。 节点分区 虽然是分布式,但并非采用纯粹的随机或者轮询来对节点访问,而是采用一些分区算法,保证指定的主键必定发生指定的实例上。 这点主要目的是避免出现事务在分布式系统中的冲突,导致不可控的事务回滚。 建议的分区算法是一致性哈希,方便节点的添加删除,以及负载均衡。 控制单次事务操作数据量 即控制事务所涉及修改(增,删,改)的数据,主要原因有两点: 一是,多节点之间的冲突检验需要传输相关的数据,如果单次事务量过大,会导致单次事务的检查时间增长,由于分布式事务的全局序列性,单个慢事务会导致全局的低速。 二是,由于最终多节点的同步,还是通过每个节点自己的relay线程来执行的,如果有大事务,会导致relay线程执行不到后面的事务,导致事务延迟,并导致可能会产生的分布式事务回滚。 周边功能介绍 主要组件简介 capture 追踪当前正在执行的事务的上下文 applier 执行远程事务传输到本地的日志到本地数据库 recovery 负责分布式环境下的节点恢复,以及相关的数据回追,失败处理等 失败节点检测 只有认为无法连接的节点才会从集群中自动踢走。 机制如下: 不可用本身的发觉,是依赖消息通讯的超时决定的。即如果节点对另外的节点的消息发送超时,则认为远程节点不可用。 对于正常节点,如果认为一个其他节点不可用了,首先会标记为不可用,之后与其他节点沟通,如果确认这个节点确实其他节点都认为不可用,则实际设置为不可用节点。 如果一个节点发现自生连接不到其他所有的实例(认为其他节点全部死亡),则这个节点本身之后的事务执行,就不会采用分布式算法而是退回传统的单节点事务模式。 另外,如果同时失败节点数过多(超过一半),为了避免脑裂,分布式算法会拒绝运行,需要人工介入恢复,这也是需要注意的一点。 节点状态 ONLINE 节点状态正常,可以正常执行事务 RECOVERING 正在接收种子节点的日志 OFFLINE 节点之前注册了,但并不属于当前集群(可能节点已经失败) ERROR 恢复阶段,阶段1或者阶段2失败 UNREACHABLE 节点不可达,一般出现在通讯超时的情况 失败恢复 这里说的,主要把一个节点,加入到已有集群的过程,而非单实例的崩溃恢复。 -->阶段1 第一阶段,新实例选择集群中的一个实例作为种子实例,这个种子实例会发送所有新实例到加入集群为止缺失的日志数据到新实例,这个的执行,是通过简单的主从同步日志的方式做的。 执行阶段1的期间,新实例还会一直持续接收当前正在活跃(实例加入集群后)的事务的日志,补全从种子实例没有传输的增量日志。 当种子实例传输日志完成之后,第一阶段就完毕了。 这一阶段,如果种子实例出现问题崩溃或者失败了,新实例会自动选取实例里面别的实例替代。 -->阶段2 这一阶段,新实例合并之前的活跃事务到当前数据库,当残余的事务量接近0(新事务一直在别的实例发生,只能非常接近0而很难完全追上)的时候,实例在集群中的状态,就会被修改为ONLINE了。 流量控制 mysql的GR,全局所有的实例都拥有所有的数据,也实际上需要运行所有的写入流量,如果有某一个实例相对较慢,如果时间持续下去,这个节点可能出现延迟,极端情况下,可能越追越远。 流量控制试图做到的事情是,保障整个集群节点之间,最快的节点和最慢的节点之间的事务差距不要太大。 实际需要控制的,有两个队列,一个是事务提交时候的冲突检查队列,一个是事务实际执行的relay日志队列 DDL执行 DDL先天上并不支持事务化,也就是多节点执行的时候,如果有几个节点失败,并不会导致已经执行成功的节点回滚DDL,对于DDL的执行结果需要单独验证,以避免多节点表不一致。 IP白名单 这个主要是安全方面的考虑,之允许指定来源的ip作为复制节点与集群通讯。 一些限制 使用group replication有以下一些限制。 所有涉及的数据都必须发生在InnoDB存储引擎的表内。 所有的表必须有明确的主键定义。 网络地址只支持IPv4。 需要低延迟,高带宽的网络。 目前集群限制最多允许9个节点。 必须启用binlog。 binlog 格式必须是row格式。 必须打开gtid模式。 复制相关信息必须使用表存储。 事务写集合(Transaction write set extraction)必须打开。(这个目前与savepoint冲突,这也是导致mysqldump无法备份GR实例的原因) log slave updates必须打开。 binlog的checksum目前不支持。 由于事务写集合的干扰,无法使用savepoint。 SERIALIZABLE 隔离级别目前不支持。 对同一个对象,在集群中不同的实例上,并行地执行DDL(哪怕是相互冲突的DDL)是可行的,但会导致数据一致性等方面的错误,目前阶段不支持在多节点同时执行同一对象的DDL。 外键的级联约束操作目前的实现并不完全支持,不推荐使用。 几个名词 Donor:用于节点恢复时候,传输历史binlog的节点。Group Configuration:集群里已经配置的实例列表。Group Membership Service:维护一致性view变更的服务,作用于节点的新增,退出,以及当前视图的维护工作。Joiner:将要加入到集群但状态尚未恢复到ONLINE的新节点。Seed:负责触发新节点加入集群动作的实例。View:当前集群活跃实例的列表。 本文出自数据和云公众号,原文链接

优秀的个人博客,低调大师

Android Drawable绘图学习笔记

如何获取 res 中的资源 数据包package:android.content.res 主要类:Resources Android SDK中的简介:Class for accessing an application’s resources.Class for accessing an application’s resources. This sits on top of the asset manager of the application (accessible through getAssets()) and provides a higher-level API for getting typed data from the assets. 其主要接口按照功能,划分为以下三部分: getXXXX() 例如: int getColor(int id) Drawable getDrawable(int id) String getString(int id) 直接获取res中存放的资源 InputStream openRawResource(int id) 获取资源的数据流,读取资源数据 void parseBundleExtras(XmlResourceParser parser, Bundle outBundle) 从XML文件中获取数据 Resource为每种资源提供了相应的接口来获取这种资源,除了可以直接获取资源外,还额外提供了以数据流的方式获取资源,这在以后的应用程序开发中会经常使用,那么如何获取Resources了,如下:Resources r = this.getContext().getResources(); 如何获取资源中的画图对象 数据包package:android.graphics.drawable 主要类:Drawable Android SDK中的简介:A Drawable is a general abstraction for “something that can be drawn.” Most often you will deal with Drawable as the type of resource retrieved for drawing things to the screen; the Drawable class provides a generic API for dealing with an underlying visual resource that may take a variety of forms. 看了以上简介,发现Drawable是个virtual class,具体如何画图,需要具体分析Drawable的子类,例如:BitmapDrawable Android SDK中的简介:A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a BitmapDrawable from a file path, an input stream, through XML inflation, or from a Bitmap object. It can be defined in an XML file with the<bitmap>element. 其主要接口如下: BitmapDrawable() BitmapDrawable(Bitmap bitmap) BitmapDrawable(String filepath) BitmapDrawable(InputStream is) void draw(Canvas canvas) Draw in its bounds (set via setBounds) respecting optional effects such as alpha (set via setAlpha) and color filter (set via setColorFilter). final Bitmap getBitmap() final Paint getPaint() Drawable是个抽象类,在BitmapDrawable中我们就看到位图的具体操作,在仔细看下BitmapDrawable的构造函数,我们就会发现与Resource中的openRawResource()接口是相对应的,就可以通过以下方法来获取位图: Resources r = this.getContext().getResources(); Inputstream is = r.openRawResource(R.drawable.my_background_image); BitmapDrawable bmpDraw = new BitmapDrawable(is); Bitmap bmp = bmpDraw.getBitmap(); Paint 数据包package:android.graphics Android SDK中的简介:The Paint class holds the style and color information about how to draw geometries, text and bitmaps. 主要就是定义:画刷的样式,画笔的大小/颜色等。 Typeface 数据包 package:android.graphics Android SDK中的简介:The Typeface class specifies the typeface and intrinsic style of a font. 主要就是定义:字体。 核心类显示资源 数据包package:android.graphics 主要类:Canvas Android SDK中的简介:The Canvas class holds the “draw” calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing). 按照结构的功能,将主要接口分为以下3部分: boolean clipXXXX() Region区域操作:DIFFERENCE INTERSECT REPLACE REVERSE_DIFFERENCE UNION XOR void drawXXXX()画图函数 void rotate() void scale() void skew() void translate() 画布操作函数 Region在这里需要特殊说明下:Region就是一个区域,也就是画布(Canvas)中的有效区域,在无效区域上draw,对画布没有任何改变。 Drawable类 Drawable是一个通用的抽象类,它的目的是告诉你什么东西是可以画的。你会发现基于Drawable类扩展出各种绘图的类,见下面的表格,当然你可以继承它来创建你自己的绘图类. Interfaces Animatable Interface that drawables suporting animations should implement. Drawable.Callback Implement this interface if you want to create an animated drawable that extendsDrawable. Classes AnimationDrawable An object used to create frame-by-frame animations, defined by a series of Drawable objects, which can be used as a View object's background. BitmapDrawable A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. ClipDrawable A Drawable that clips another Drawable based on this Drawable's current level value. ColorDrawable A specialized Drawable that fills the Canvas with a specified color, with respect to the clip region. Drawable A Drawable is a general abstraction for "something that can be drawn." Most often you will deal with Drawable as the type of resource retrieved for drawing things to the screen; the Drawable class provides a generic API for dealing with an underlying visual resource that may take a variety of forms. Drawable.ConstantState DrawableContainer DrawableContainer.DrawableContainerState GradientDrawable A Drawable with a color gradient for buttons, backgrounds, etc. InsetDrawable A Drawable that insets another Drawable by a specified distance. LayerDrawable A Drawable that manages an array of other Drawables. LevelListDrawable A resource that manages a number of alternate Drawables, each assigned a maximum numerical value. NinePatchDrawable A resizeable bitmap, with stretchable areas that you define. PaintDrawable Drawable that draws its bounds in the given paint, with optional rounded corners. PictureDrawable Drawable subclass that wraps a Picture, allowing the picture to be used whereever a Drawable is supported. RotateDrawable A Drawable that can rotate another Drawable based on the current level value. ScaleDrawable A Drawable that changes the size of another Drawable based on its current level value. ShapeDrawable A Drawable object that draws primitive shapes. ShapeDrawable.ShaderFactory Base class defines a factory object that is called each time the drawable is resized (has a new width or height). StateListDrawable Lets you assign a number of graphic images to a single Drawable and swap out the visible item by a string ID value. TransitionDrawable An extension of LayerDrawables that is intended to cross-fade between the first and second layer. 有三种方法可以定义和实例化一个Drawable:保存一个图片到你工程资源中,使用XML文件来描述Drawable属性或者用一个正常的类去构造。下面我们将讨论两种技术(对一个有开发经验的开发者来说构造并不是最新的技术)。 从资源图像文件中创建 一个比较简单的方法是添加一个图片到你的程序中,然后通过资源文件引用这个文件,支持的文件类型有PNG(首选的) JPG(可接受的)GIF(不建议),显然这种对于显示应用程序的图标跟来说是首选的方法,也可以用来显示LOGO,其余的图片可以用在例如游戏中。 把一个图片资源,添加你的文件到你工程中res/drawable/目录中去,从这里,你就可以引用它到你的代码或你的XML布局中,也就是说,引用它也可以用资源编号,比如你选择一个文件只要去掉后缀就可以了(例如:my_image.png 引用它是就是my_image)。 注意:SDK指出,为了缩小图片的存储空间,在Build的时候又可能对图片进行压缩,如果不想被压缩,可以将图片放在res/raw/目录中。 SDK给出的例子: LinearLayout mLinearLayout; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a LinearLayout in which to add the ImageView mLinearLayout = new LinearLayout(this); // Instantiate an ImageView and define its properties ImageView i = new ImageView(this); i.setImageResource(R.drawable.my_image); i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); // Add the ImageView to the layout and set the layout as the content view mLinearLayout.addView(i); setContentView(mLinearLayout); } 获取Drawable对象: Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable.my_image); 注意:保持每个资源类型的一至,可以保证你项目状态的一致性,就不用担心有许多不同类型的对象来实例化它。例如:如果使用相同的图像资源来实例化两个Drawable对象。然后修改一个Drawables的属性(例如alpha),然后不幸得是这个效果也会出现在另一个对象上去。所以当处理同一个资源的多个实例对象时,不是直接转换为Drawable,而是应该执行tween animation 如何添加资源到ImageView: <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#55ff0000" android:src="@drawable/my_image"/> 从XML文件中创建 到如今,你应该比较熟悉按Android的原则去开发一个用户接口,因此,你也应该理解了定义一个XML文件对于对象的作用与灵活的重要性。这个理念无数次用于Drawables. 如果你想创建一个Drawable对象,而这个对象并不依赖于变量或用户的交换,把它定义到XML中去应该是一个不错的方法。即使你期望在你的应用程序中改变其属性来增加用户体验。你应该考虑把对象放入XML中,因为你可以随时修改其属性。 当你在你的XML中定义了一个Drawable,保存这个XML文件到你工程目录下res/drawable目录中,然后通过调用Resource.getDrawable()来检索并实例化,传递给它XML文件中的资源ID号。任何Drawable的子类都支持inflate这个方法,这个方法会通过XML来实例化你的程序。任何Drawable都支持XML的扩展来利用特殊的XML属性来帮助定义对象的属性,可以查看任何Drawable子类文档来看如何定义XML文件。 如下定义了一个TransitionDrawable:An extension of LayerDrawables that is intended to cross-fade between the first and second layer. It can be defined in an XML file with the<transition>element. Each Drawable in the transition is defined in a nested<item>. 有关TransitionDrawable的详细信息查看http://androidappdocs.appspot.com/reference/android/graphics/drawable/TransitionDrawable.html。 将其定义在res/drawable/expand_collapse.xml: <?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/pic1"/> <item android:drawable="@drawable/pic2"/> </transition> 下面实例化并处理: public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res=getResources(); TransitionDrawable trans=(TransitionDrawable )res.getDrawable(R.drawable.expand_collapse); ImageView image = (ImageView)findViewById(R.id.ImageView01); image.setImageDrawable(trans); trans.startTransition(3000); } } ShapeDrawable 当你想去画一些动态的二维图片,一个ShapeDrawable对象可能会对你有很大的帮助。通过ShapeDrawable,你可以通过编程画出任何你想到的图像与样式。 ShapeDrawable继承了Drawable, 所以你可以调用Drawable里有的函数,比如视图的背景,通过setBackgroundDrawable()设置。当然,你可以在自定义的视图布局中画你的图形,因为ShapeDrawable有自己的draw()方法。你可以在View.OnDraw()方法期间创建一个视图的子类去画ShapeDrawable。 ShapeDrawable类(像很多其他Drawable类型在android.graphics.drawable包)允许你定义drawable公共方法的各种属性。有些属性你可以需要调整,包括透明度,颜色过滤,不透明度,颜色。 例子: public class CustomDrawableView extends View { private ShapeDrawable mDrawable; public CustomDrawableView(Context context) { super(context); int x = 10; int y = 10; int width = 300; int height = 50; mDrawable = new ShapeDrawable(new OvalShape()); mDrawable.getPaint().setColor(0xff74AC23); mDrawable.setBounds(x, y, x + width, y + height); } protected void onDraw(Canvas canvas) { mDrawable.draw(canvas); } 显示: CustomDrawableView mCustomDrawableView;protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCustomDrawableView = new CustomDrawableView(this); setContentView(mCustomDrawableView);} 在XML中定义方法:如果你想用XML文件配置来取代原有布局来画自定义的drawable,于是你自定义的Drawable类必须重载view (Context, AttributeSet) 构造函数。 <com.example.shapedrawable.CustomDrawableView android:layout_width="fill_parent" android:layout_height="wrap_content" /> NinePatchDrawable NinePatchDrawable 绘画的是一个可以伸缩的位图图像,Android会自动调整大小来容纳显示的内容。一个例子就是NinePatch为背景,使用标准的Android按钮,按钮必须伸缩来容纳长度变化的字符 NinePatchDrawable是一个标准的PNG图像,它包括额外的1个像素的边界,你必须保存它后缀为.9.png,并且保持到工程的res/drawable目录中。 这个边界是用来确定图像的可伸缩和静态区域。你可以在左边和上边的线上画一个或多个黑色的1个像素指出可伸缩的部分(你可以需要很多可伸缩部分),它的相对位置在可伸缩部分相同,所以大的部分总是很大的。 你还有可以在图像的右边和下边画一条可选的drawable区域(有效的,内边距线)。如果你的视图对象设置NinePath为背景然后指定特殊的视图字体,它将自行伸缩使所有的文本来适应根据右线与底部线设计好的区域(如果有的话),当然内边距线不包括其中,Android可以使用左边的线与上面的线来定义一个drawable区域。 我们来澄清一下这两条不同的线,左边跟顶部的线来定义哪些图像的像素允许在伸缩时被复制。底部与右边的线用来定义一个相对位置内的图像,视图的内容就放入其中。 使用方法: <Button id="@+id/tiny" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerInParent="true" android:text="Tiny" android:textSize="8sp" android:background="@drawable/my_button_background"/><Button id="@+id/big" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:text="Biiiiiiig text!" android:textSize="30sp" android:background="@drawable/my_button_background"/> 本文转自feisky博客园博客,原文链接:http://www.cnblogs.com/feisky/archive/2010/01/08/1642567.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android学习进阶和IoC

1.成为Android高手一般分为六个阶段: 第一阶段:熟练掌握Java SE,尤其是对其内部类、线程、并发、网络编程等需要深入研究;熟练掌握基于HTTP协议的编程,清楚POST和GET等请求方式流程和细节;能够进行基本的Java Web编程,如果能够使用Java EE则更好; 第二阶段:精通Android的核心API的使用,例如四大组件所涉及的API、Context等,精通核心界面的编程,例如ListView的编程;到达这个阶段已经能够做大部分基本的应用开发了; 第三阶段:精通应用框架的原理,尤其是对IoC的理解及其在Android应用框架中的应用,精通基本的23种设计模式在Android中的应用; 第四阶段:精通JNI,熟练Android类库中C/C++组件开发;并能够使用JNI机制把现有的C/C++组件移植成为应用框架的核心组件;具备修改和编写自己的应用框架的能力; 第五阶段:做出自己的Android系统,无论是底层还是上层都能够了如指掌;能够根据实际需要设计和实现比较大Android系统,例如带领比较大的团队做出自己的Android手机产品等; 第六阶段:势。一切的思考均进入“势”的思考,一切都是思路问题,判断和预测Android的形势,引领市场,通往自由的天堂。 2. Android之IoC (Inversion of Control) 1)概念 一种设计思想。使调用者和被调用者解耦和分离,便于更改和代码重用,便于移植。 许多应用都是由多个类通过彼此合作来实现业务逻辑,每个对象之间都相互依赖,这将导致代码高度耦合并且难以测试、难以修改难以重用。 IoC很好的解决了该问题,它将实现组件间关系从程序内部提到外部容器来管理。也就是说由容器在运行期将组件间的某种依赖关系动态的注入组件中。控制程序间关系的实现交给了外部容器来完成。 2)案例 为了实现调用者和被调用者解耦,分离,一般是通过工厂模式实现的,下面将通过比较工厂模式和Ioc模式不同,加深理解Ioc模式。 假设有两个类B 和 C:B作为调用者,C是被调用者。一般的做法是: public class B{private C comp=new C(); ...... } 工厂模式实现如下: public class B{private C comp; private final static MyFactory myFactory = MyFactory.getInstance();public B(){this.comp = myFactory.createInstanceOfC(); }public void someMethod(){this.comp.sayHello(); } } 使用Ioc依赖性注射实现Picocontainer如下: public class B{private C comp; public B(C comp){this.comp = comp; }public void someMethod(){this.comp.sayHello(); } } //外部容器实现,控制程序间的关系。CImp类为C接口/类的一个具体实现。public class client{public static void main( String[] args ) { DefaultPicoContainer container = new DefaultPicoContainer(); container.registerComponentImplementation(CImp.class); //向B类实现注射C类具体实现 container.registerComponentImplementation(B.class); B b = (B) container.getComponentInstance(B.class); b.someMethod(); } } 3)工厂模式和Ioc不同的特点和区别: 如上,主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。 使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。 所以,Ioc并没有消除B和C之间这样的联系,只是转移了这种联系。 总之,使用Ioc模式,可以不管将来具体实现,完全在一个抽象层次进行描述和技术架构。 分类: Android 本文转自快乐就好博客园博客,原文链接:http://www.cnblogs.com/happyday56/p/3611800.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

IoT Kaa平台学习(二)

版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/73115338 在这片文章中,主要讨论在Kaa架构和逻辑设计下的功能性概念。 Kaa IoT平台由Kaa server,Kaa扩展和端点SDKs组成。 kaa服务器是平台的后端部分。他被用于去管理租户,应用,用户和设备。Kaa服务器暴露了集成接口并且提供了管理能力。 kaa扩展是独立的软件模块,他提升了平台的功能性。 端点SDK是为多种多样的Kaa平台特征提供客户端的API并且处理通信,数据编集,持久性等的一个库。Kaa SDK被设计区促进客户端应用的创造性来运行在各种各样连接的设备上。然而,不使用Kaa端点SDK的客户端应用也是有可能的。以不同的编程语言有多种不同的端点SDK。 Kaa集群 Kaa服务器节点使用Apache的ZooKeeper来与服务合作。互相连接的节点和特别的Kaa实例组成了一个Kaa集群。Kaa集群需要Nosql和SQL数据库实例来保存端点数据和原语。 位于集群中的Kaa节点运行了Control,Operation和Bootstrap服务的组合。 Control服务 Kaa控制服务管理所有的系统数据,处理来自Web UI和外部集成系统的API请求,并且向Operaion服务发送通知。控制服务通过持续的接收来自ZooKeeper的信息来维持一个最新的可操作服务列表。除此之外,控制服务运行嵌入的使用控制服务API的管理web UI组件,来想用户提供方便的基于web的接口来管理租户,用户账户,应用数据等。 为了支持高可用性,一个Kaa集群至少有两个节点是使能控制服务的。在高可用性模式中,其中的一个控制服务是活动的,另外一个是待机模式。一旦活动的控制服务失效了,ZooKeeper会唤醒其中一个待机控制服务并且将它升级成为活动控制服务。 操作服务 操作服务最基础的角色就是与当前多个端点进行通信。操作服务处理端点请求并且把数据发送给他们。 为了横向扩展,你可以设置一个Kaa集群的每一个几点都是操作服务使能的。在这个情况下,所有的操作服务的实例当前都是在运行的。如果一个操作服务意外终止了,之前连接端点自动转换到其他可用的操作服务中去。Kaa服务器在运行时可以重新负载均衡,所以在集群中路由端点到低负载的节点中的效率是非常高的。 引导程序服务 Kaa Bootstrap服务发送关于操作服务连接参数的信息到端点中。取决于配置的协议栈,连接参数可能包括IP地址,TCP端口,安全证书等。Kaa SDK包含一个在集群中预生成的Bootstrao可用列表,他被用于生成SDK库。在这个列表中的端点查询Bootstrap服务为当前可用操作服务取回连接。Bootstrap服务通过和ZooKeeper服务合作来维持他们的可用操作服务的列表。 第三方组件 Zookeeper Apache ZooKeeper使能在Kaa集群节点之间高可靠性分布式合作。每一个Kaa节点持续的推送关于连接参数,使能的服务和回应的服务负载的信息,其他Kaa节点使用这个信息去获取他们兄弟的列表并且与他们进行通信。活动的控制服务在SDK生成期间使用关于可用Bootstrap服务和他们连接参数的信息。 SQL database SQL数据库实例被用于存储租户,应用,端点组合其他原语,他们不随着端点的增加而增长。 一个Kaa集群的高可用性通过在HA模式下部署SQL数据库被实现了。Kaa现在官方支持MariaDB和PostgreSQL最为嵌入的SQL数据库。 NoSQL database NoSql数据库实例被用于存储端点关系数据,这些数据随着端点的增加成线性增长。 NoSQL数据库节点可以和Kaa节点一样放在相同的为或虚拟机上,并且为了这个系统的高可用性,他应该在HA模式下被部署。Kaa官方支持Apache Cassandra和MongoDB作为嵌入的NoSQL数据库。 Internode communications Kaa服务使用Apache Thirft来进行进程和节点之间的通信。每一个服务使用ZooKeeper包含关于他的兄弟的元数据。这个元数据包含关于Thrift主机和端口的信息。 高可用性和伸缩性 Kaa集群可以横向和线性扩展;在Kaa集群架构中没有单一故障点。Kaa操作和Bootstrap服务是独一无二的并且工作在主动-主动的HA模式下。其中一个集群节点包含一个活动的控制服务。一旦节点发生故障,位于另外一个节点的待机控制服务被提升变成活动的。Kaa集群的高可用性也依赖于SQL和NoSQL数据库的HA。 主动负载均衡 Kaa SDK在初始化期间伪随机选择Bootstrap和操作服务实例。依赖于对Kaa集群的请求发起者两个负载均衡的方法被使用:Kaa端点SDK或者是REST API。 端点SDK请求 Kaa SDK在初始化过程中伪随机选择Bootstrap和操作服务。然而,如果集群负载太重,端点的随机分发可能是效率不高的。当一个新的节点加入集群的时候,他在更新拓扑的时候,为了更好的性能,被要求重新均衡负载。 Kaa服务使用主动负载均衡方法来构建一些端点来重新连接一个不同的操作服务,因此平衡了节点之间的负载。使用算法来使服务器加载数据(连接的端点的数量,加载平均值等),该算法被kaa节点公布作为输入,并且定期的重新计算每一个节点的权重值。然后,超负荷的节点被要求重定向到一个不同的节点,一些端点被要求连接。 一个相似的方法可以被采用,通过预定服务的方式来加载进一个节点中,或者是在物理或虚拟机上逐渐的移植集群。为了实现,你需要通过实现重新均衡负载借口来设置一个自定义的负载均衡策略。 REST API请求 对于REST API负载均衡,你可以使用现成的HTTP负载均衡解决方案,例如Nginx,AWS Elastic负载均衡,Google Cloud LB。 Kaa实例 Kaa实例是Kaa平台一个特殊的安装,特也可以是单节点的,也可以是集群部署。 在Kaa中的一个应用定义了一系列数据模型,端点和Kaa服务之间的通信的类型和运行规则。Kaa应用对特定的平台,操作系统或客户端软件实现是不具体的。例如,针对一个压力传感器的两个固件实现在Arduino和STM32平台上是不一样的,但是在kaa中可以被看做是相同的应用,只要他们报告相同结构的遥测数据。 Kaa平台是多租户的。一个单一的Kaa实例可以支持多个独立的商务实体。应用属于租户,但是端点注册在应用中。(看下图) 一个端点(EP)是一个抽象,他代表着在一个Kaa部署中一个分离的管理实体。通俗的将,一个端点是在一个Kaa实例中的特别注册的Kaa客户端。基于用户实例,不同层的物理实例被认为是端点。在一个个人设置中,一个位于船队追踪应用中的单一的空气质量传感器,一个火车(尽管写到这多个报告数据的传感器)可能只是一个实体被认为是一个端点。 为了通过不同的属性区分端点,而不是使用一个ID,Kaa使用端点配置文件。 端点配置文件是一个自定义的结构化的数据集合,他描述了位于一个应用中的一个特定端点的特征。每一个端点配置文件包括客户端,服务端和系统部分。客户端部分的初始化值是被客户端开发者使用数据模式指定的。接着,客户端端点配置文件在一个新的端点被注册的时候生成。端点配置文件的服务器和系统部分数据是由Kaa服务管理的。 配置文件数据被用于将端点放到端点组中 - 由配置文件适配器定义的独立的管理实体。配置文件符合配置文件适配器的端点被自动变成这个组的成员。一个端点可以同时位于无限个组中。 端点也与拥有者相关。基于应用,应有着可以是人,组或者是组织。

优秀的个人博客,低调大师

Kaa IoT平台学习(一)

版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/72964894 kaa IoT开发平台概览 Kaa是一个用于物联网的多功能的中间件平台,他允许构建完全端到端IoT解决方案,连接的应用和智能产品。Kaa平台为IoT产品开发提供了一个开放的,功能丰富的工具组件,因此有效的降低了相关的费用,风险和面向市场的时间。为了快速开始,kaa提供了一套开箱即用的企业级物联网功能,其能够被简单的插入并实现大量的IoT用户实例。 kaa上有很多架构特征使得IoT开发更加快速和简单。首先,kaa是与硬件无关的,因此 kaa与虚拟化的任何类型的连接的设备,传感器和网关是相兼容的。他也提供了一个清澈的IoT特征和延伸的架构用于不同种类的应用。在开发上,他们可以使用最小额外的代码,被用于即插即用的模块。和用于连接协议和整体分析的无限选项结合在一块,这些能力使得Kaa成为了用于创新性IoT开发的恰当的比喻。 Kaa可以管理你的设备的能力有: 管理无限数量的连接设备 设置跨设备的协同工作的能力 运行A/B服务测试 运行远程设备供应和配置 运行实时设备监控 发布OTA固件更新 为智能产品创建云服务 收集和分析传感器数据 分析用户行为,发送目标提醒 Kaa如何工作 Kaa为连接的对象使能数据管理,并且通过提供服务器和末端SDK组件来使能你的后端基础建设。SDKs被嵌入到你连接的设备上并且实现与服务器的实时双流向的数据交换。Kaa SDKs能被集成在虚拟的任何连接的设备或芯片上。 Kaa服务器提供了所有的后端功能,这些功能需要操作甚至是大规模和关键任务的IoT解决方案。他处理所有通过连接对象的交流,包括数据一致性和安全性,设备协同工作能力和失败证明连接性。 Kaa服务器特征非常好的被构建了接口用于数据管理和分析系统和你的产品专属服务的集成。他为你的后端系统扮演一个功能,便是你可以非常简便的扩展和定制来满足你的产品的特殊的需求。

优秀的个人博客,低调大师

android studio 学习之一

一、简介 Android Studio 是一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试。 官网:http://www.android-studio.org/ 二、安装问题 1.Unable to access Android SDK add-on list 如果是第一安装完之后出现这个界面,在这个目录下 C:\Program Files\Android\Android Studio\bin\idea.properties 最后面添加上这句话 disable.android.first.run=true 2.汉化教程 提示:resources_en.jar拷贝出来改名为resources_cn.jar,使用解压软件打开,然后把中文版的文件拷进去,保存后再考回lib下 http://www.imgeek.org/article/825308169

优秀的个人博客,低调大师

Material Design学习之 Camera

转载请注明出处:王亟亟的大牛之路 年后第一篇,自从来了某司产量骤减,这里批评下自己,这一篇的素材来源于老牌Material Design控件写手afollestad的 https://github.com/afollestad/material-camera 开篇前,继续安利,你懂的:https://github.com/ddwhan0123/Useful-Open-Source-Android (最近把 6.0授权部分单独罗列出来了) 介绍代码之前先贴下效果图 如何使用 先是添加依赖让maven去下代码 maven部分 repositories { jcenter() maven { url "https://dl.bintray.com/drummer-aidan/maven" } } 然后在build.gradle里添加 compile 'com.afollestad:material-camera:0.4.4' 当然你要下源码也行,就是一个java代码和布局文件,截图如下 依赖加好,代码下好,还需要做一件事,注册Activity 需要在项目的main文件里加 <activity android:name="com.afollestad.materialcamera.CaptureActivity" android:theme="@style/MaterialCamera.CaptureActivity" /> <activity android:name="com.afollestad.materialcamera.CaptureActivity2" android:theme="@style/MaterialCamera.CaptureActivity" /> 用于注册library的activity OK,配置大致就是如下 自定义设置 在使用拍摄功能前肯定,一定会有多多少少的设置,最通常的诸如,图片储存地址,图片大小,画质压缩等等,原作者也提供了强大的api,这里做下翻译。 .allowRetry(true) //是否显示重拍按钮 .autoSubmit(false) //是否允许用户在录制后播放视频 .saveDir(saveFolder) //拍摄的内容的储存地址 .primaryColorAttr(R.attr.colorPrimary) //相机配色,建议遵从app style .showPortraitWarning(true) //如果用户按纵向方向的记录,是否显示警告 .defaultToFrontFacing(false) //是否默认为前置摄像头 .allowChangeCamera(true) //允许用户更改相机 .retryExits(false) //如果为true,播放屏幕中的“重试”按钮将退出相机,而不是返回录音机 .restartTimerOnRetry(false) //如果为true,则当用户在播放中轻按“重试”时,倒计时器将重置为0 .continueTimerInPlayback(false) //如果为true,倒计时器将在播放过程中继续向下,而不是暂停。 .videoEncodingBitRate(1024000) //设置视频大小 .audioEncodingBitRate(50000) // 设置音频大小 .videoFrameRate(24) //设置视频fps值 .qualityProfile(MaterialCamera.QUALITY_HIGH) //设置质量配置文件,手动设置比特率或帧速率与其他设置将覆盖单个质量配置文件设置 .videoPreferredHeight(720) //设置录制视频的首选高度 .videoPreferredAspect(4f / 3f) //为录制的视频输出设置首选宽高比 .maxAllowedFileSize(1024 * 1024 * 5) //将最大文件大小设置为5MB,如果文件达到此限制,录制将停止。请记住,FAT文件系统的文件大小限制为4GB。 .iconRecord(R.drawable.mcam_action_capture) //设置用于开始录制的按钮的自定义图标 .iconStop(R.drawable.mcam_action_stop) //为用于停止录制的按钮设置自定义图标 .iconFrontCamera(R.drawable.mcam_camera_front) //设置用于切换到前置摄像头的按钮的自定义图标 .iconRearCamera(R.drawable.mcam_camera_rear) //设置用于切换到后置摄像头的按钮的自定义图标 .iconPlay(R.drawable.evp_action_play) //设置用于开始播放的自定义图标 .iconPause(R.drawable.evp_action_pause) // 设置用于暂停播放的自定义图标 .iconRestart(R.drawable.evp_action_restart) //设置用于重新开始播放的自定义图标 .labelRetry(R.string.mcam_retry) //为用于重试记录的按钮设置自定义按钮标签(如果可用) .labelConfirm(R.string.mcam_use_video) //为用于确认/提交录音的按钮设置自定义按钮标签 .autoRecordWithDelaySec(5) //摄像机将在5秒倒计时后自动开始录制。这将最初禁用前后摄像头之间的切换。 .autoRecordWithDelayMs(5000) //与上面相同,用毫秒而不是秒表示。 .audioDisabled(false) //设置为true可记录没有任何音频的视频 .start(CAMERA_RQ); //启动相机活动,结果将被发回当前活动 这都是api提供的设置的方法,通俗易懂,建议写成一个工厂方法然后调用,省得每次构造一个新的MaterialCamera对象 控件调用 作者在适配方面还是做的很用心的,高低版本的Fragment和通常的Activity都有做。兼容方面我分别在 华为,nexus,小米部分机型做过测试没有明显的差异和bug出现,我们来看下具体是如何调用的。 MaterialCamera materialCamera = new MaterialCamera(this) .saveDir(saveDir) .showPortraitWarning(true) .allowRetry(true) .defaultToFrontFacing(true) .allowRetry(true) .autoSubmit(false) .labelConfirm(R.string.mcam_use_video); materialCamera.stillShot() .labelConfirm(R.string.mcam_use_stillshot); materialCamera.start(CAMERA_RQ); 按钮啊或者其他地方调用下就好了,然后和使用普通相机一样在onActivityResult里找结果就行 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Received recording or error from MaterialCamera if (requestCode == CAMERA_RQ) { if (resultCode == RESULT_OK) { final File file = new File(data.getData().getPath()); Toast.makeText(this, String.format("Saved to: %s, size: %s", file.getAbsolutePath(), fileSize(file)), Toast.LENGTH_LONG).show(); } else if (data != null) { Exception e = (Exception) data.getSerializableExtra(MaterialCamera.ERROR_EXTRA); if (e != null) { e.printStackTrace(); Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } } } 首先判断是否是自己之前预设的requestCode值是的话去读取data里面的值只要能读到data值那就走正常的业务逻辑就好。整体使用体验和厂商自带的相机相机功能没有什么区别。 区别在于存储部分帮你做了,常用功能帮你封了,长得很MD,还有很强的拓展性 一些补充 1.暂时只支持android.support.v4.app.Fragmentandroid.app.FragmentActivity调用相机,特殊场景的话自己得转Context 2.manifest里面加的2个Activity节点不能漏,lib裤自己没有存货的进程,都依附于调用者(我没试过不加会怎么样,八成是找不到那个类)那为什么需要有2个呢? 兼容看看2个类的注解就知道了 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class Camera2Fragment extends BaseCameraFragment implements View.OnClickListener 以及 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public class CameraFragment extends BaseCameraFragment implements View.OnClickListener 这个库暂时就介绍到这里,这篇没去拆源码,我对这个库的理解感觉这是一个实用性大于教学性的开源库,类似功能的库实现都是大同小异都是对自带的照相机外面套了层ui,套了层功能强化,当然感兴趣可以自己去读读,不是很难。 如果觉得部分功能自己需要拓展,继承BaseCameraFragment 这部分开始自己实现我觉得也很方便。 项目地址:https://github.com/afollestad/material-camera

优秀的个人博客,低调大师

虚拟化技术学习笔记

ECS 用的KVM。 任何计算机的问题都可以通过另一层的重定向解决。 虚拟技术:Xen, KVM, Hyper-V, Vmware ESX Server, VMware workstation, VirtualBox Binary Translation: 因为一开始X86不支持虚拟化, 实现复杂,性能损失 硬件辅助虚拟化:2004年 Intel和AMD 发布新的CPU规范,支持虚拟化。 问题: 1,ECS主要就是用的虚拟化技术吧,ECS产品本身和盘古有什么关系呢?这张图感觉有点需要推敲。 2,一个特定的ECS在阿里云里面,如果相应的物理机发生故障,如何切换?

优秀的个人博客,低调大师

Learning ELK stack 学习笔记

不错的入门书Learning ELK stack 第三章: Logstash插件类型分为四类: Input Filter Output Codec Logstash input类的file插件维护了一个sincedb文件追踪监控操作文件的当前位置。默认写入$HOME/.sincedb*,游标及读取频率可以通过配置修改。 file的两个配置属性:sincedb_path,sincedb_write_interval(默认15秒读取一次文件) 这里还涉及另一个配置 start_position => "beginning" 或"end"(默认),使用beginning,如果移除了.sincedb,将重新读取历史数据,造成数据重复。 lumberjack和logstash forwarder(轻量化的logstash)使用lumberjack协议打包日志 redis经常做为logstash forwarder 与logstash的中间人角色,在高负载系统上提供获取日志的服务。 Logstash outpu类型插件: 重点是elasticsearch,email,kafka,lumberjack,redis, Logstash filter类型插件: date,drop,grok解析非结构化的日志转换成结构化,mutate重命名,移除,替换,修改字段,转换字段类型,合并字段等 Logstash codec类型插件:编码解码日志 json,mutliline 第五章节: elasticsearch > indices > documents(json) > fields(_type,mapping) pattern=>"logstash-%{+YYYY.MM.dd}"(默认index) shard:index的物理存储位置,支持Primary shard and replica shard, 默认每个document使用5个shard replica shard分布在各个节点上,可以failover与平均负载 cluster > nodes :三种角色 =>data node =>master node =>routing node & load banlancer node elasticsearch api $curl -X '://://?'d '' VERB:GET, POST, PUT,DELETE, HEAD PROTOCAL:http,https PATH:/index/type/id OPERATION_NAME:_search, _count, and so on QUERY_STRING:?pretty for pretty print of JSON documents BODY:This makes a request for body text. 查看指定index的document thinkt@linux-pw37:~> curl -XGET 'http://192.168.56.101:9200/logstash-2016.09.09/_search?pretty' { "took" : 107, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 1.0, "hits" : [ { "_index" : "logstash-2016.09.09", "_type" : "logs", "_id" : "AVf3tVjYndkMLGPlmtnx", "_score" : 1.0, "_source" : { "message" : "2016-09-09,770.099976,773.244995,759.659973,759.659973,1812200,759.659973", "@version" : "1", "@timestamp" : "2016-09-09T00:00:00.000Z", "path" : "/home/vagrant/table.csv", "host" : "localhost.localdomain", "Date" : "2016-09-09", "Open" : 770.099976, "High" : 773.244995, "Low" : 759.659973, "Close" : 759.659973, "Volume" : 1812200, "Adj_close" : 759.659973 } } ] } } 查看所有index thinkt@linux-pw37:~> curl -XGET 'http://192.168.56.101:9200/_cat/indices?v' health status index pri rep docs.count docs.deleted store.size pri.store.size yellow open logstash-2016.03.18 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.03.17 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.03.16 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.03.15 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.06.07 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.06.08 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.06.09 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.08.31 5 1 1 0 8kb 8kb yellow open logstash-2016.09.01 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.08.30 5 1 1 0 8kb 8kb yellow open logstash-2016.03.21 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.06.14 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.09.08 5 1 1 0 8kb 8kb yellow open logstash-2016.06.15 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.09.09 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.06.16 5 1 1 0 7.9kb 7.9kb yellow open logstash-2016.09.06 5 1 1 0 7.9kb 7.9kb 查看集群中所有nodes thinkt@linux-pw37:~> curl -XGET 'http://192.168.56.101:9200/_cat/nodes?v' host ip heap.percent ram.percent load node.role master name 10.0.2.15 10.0.2.15 13 56 0.00 d * node-1 logstash 的elasticsearch 插件会自动创建index kibana4特性: 搜索关键字高亮 聚合类型:桶,度量 可脚本化的字段 动态展示 kibana的主项: discover,visualize,dashboard,settings discover的search box搜索记录默认最多显示500条index documents time filter支持quick,absolute,relative三种时间过滤方式,并支持定义自动刷新间隔,也可以使用histogram直方图拖动选择时间。 查询语法使用lucene语法 Lucene n. Lucene是一个非常优秀的开源的全文搜索引擎; 我们可以在它的上面开发出各种全文搜索的应用来。Lucene在国外有很高的知名度; 现在已经是Apache的顶级项目; 在国内; 搜索方式:search box 文本查询,field查询 visualize,dashboard 阻止数据丢失 logs > borker(redis,rabbit mq,amqp,zeroMQ) > logstash > elasticsearch > kibana > nginx 加固数据访问 elasticsearch,kibana使用SSL认证访问elasticsearch browser-(ssl_key_file,ssl_cert_file)->kibana->elasticsearch Elasticsearch shield(收费) Search guard(free) 系统伸缩性 horizontally scalable fast,quick,realtime inexpensive便宜的 flexable弹性灵活的 用户量及支持力度 开源的 数据保留策略 elasticsearch curator管理indeices

优秀的个人博客,低调大师

Hbase 学习(十) HBase Snapshots

HBase Snapshots允许你对一个表进行快照(即可用副本),它不会对Region Servers产生很大的影响,它进行复制和 恢复操作的时候不包括数据拷贝。导出快照到另外的集群也不会对Region Servers产生影响。 下面告诉你如何使用Snapshots功能。 1. 开启快照支持功能,在0.95+之后的版本都是默认开启的,在0.94.6+是默认关闭。 <property> <name>hbase.snapshot.enabled</name> <value>true</value> </property>2. 给表建立快照,不管表是启用或者禁用状态,这个操作不会进行数据拷贝。 $ ./bin/hbase shell hbase> snapshot 'myTable', 'myTableSnapshot-122112'3. 列出已经存在的快照 $ ./bin/hbase shell hbase> list_snapshots4. 删除快照 $ ./bin/hbase shell hbase> delete_snapshot 'myTableSnapshot-122112' 5. 从快照复制生成一个新表 $ ./bin/hbase shell hbase> clone_snapshot 'myTableSnapshot-122112', 'myNewTestTable' 6. 用快照恢复数据,它需要先禁用表,再进行恢复 $ ./bin/hbase shell hbase> disable 'myTable' hbase> restore_snapshot 'myTableSnapshot-122112' 提示:因为备份(replication)是系统日志级别的,而快照是文件系统级别的,当使用快照恢复之后,副本会和master出于不同的状态,如果你需要使用恢复的话,你要停止备份,并且重置bootstrap。 如果是因为不正确的客户端行为导致数据丢失,全表恢复又需要表被禁用,可以采用快照生成一个新表,然后从新表中把需要的数据用map-reduce拷贝到主表当中。 7. 复制到别的集群当中 该操作要用hbase的账户执行,并且在hdfs当中要有hbase的账户建立的临时目(hbase.tmp.dir参数控制),采用16个mappers来把一个名为MySnapshot的快照复制到一个名为srv2的集群当中。 $ bin/hbase class org.apache.hadoop.hbase.snapshot.tool.ExportSnapshot -snapshot MySnapshot -copy-to hdfs://srv2:8020/hbase -mappers 16

优秀的个人博客,低调大师

Hbase 学习(二)各种filter

各种filter 今天的主题是 Filter,hbase客户端查询的时候,自定义查询filter。 直接上例子吧,不多说别的了,第一个例子是RowFilter的。 Scan scan = new Scan(); scan.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-0")); Filter filter1 = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("row-22"))); scan.setFilter(filter1); ResultScanner scanner1 = table.getScanner(scan); for (Result res : scanner1) { System.out.println(res); } scanner1.close(); Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*-.5")); scan.setFilter(filter2); ResultScanner scanner2 = table.getScanner(scan); for (Result res : scanner2) { System.out.println(res); } scanner2.close(); Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("-5")); scan.setFilter(filter3); ResultScanner scanner3 = table.getScanner(scan); for (Result res : scanner3) { System.out.println(res); } scanner3.close();第二个例子是 QualifierFilter的 Filter filter = new QualifierFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("col-2"))); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println(result); } scanner.close(); Get get = new Get(Bytes.toBytes("row-5")); get.setFilter(filter); Result result = table.get(get);第三个例子是 ValueFilter Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(".4")); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } } scanner.close(); Get get = new Get(Bytes.toBytes("row-5")); get.setFilter(filter); Result result = table.get(get); for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); }第四个例子是 PageFilter,分页的filter Filter filter = new PageFilter(15); int totalRows = 0; byte[] lastRow = null; while (true) { Scan scan = new Scan(); scan.setFilter(filter); if (lastRow != null) { byte[] startRow = Bytes.add(lastRow, POSTFIX); System.out.println("start row: " +Bytes.toStringBinary(startRow)); scan.setStartRow(startRow); } ResultScanner scanner = table.getScanner(scan); int localRows = 0; Result result; while ((result = scanner.next()) != null) { System.out.println(localRows++ + ": " + result); totalRows++; lastRow = result.getRow(); } scanner.close(); if (localRows == 0) break; } System.out.println("total rows: " + totalRows);第五个例子是 InclusiveStopFilter,它是什么意思呢,就是扫描到某个rowkey就停止,下面的例子是从row-3开始扫描,一直扫描到row-5结束。 Filter filter = new InclusiveStopFilter(Bytes.toBytes("row-5")); Scan scan = new Scan(); scan.setStartRow(Bytes.toBytes("row-3")); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println(result); } scanner.close();第六个 SingleColumnValueFilter,这个是我们最常用的filter,我觉得很好用。 SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"), CompareFilter.CompareOp.NOT_EQUAL, new SubstringComparator("val-5")); filter.setFilterIfMissing(true); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } } scanner.close(); Get get = new Get(Bytes.toBytes("row-6")); get.setFilter(filter); Result result = table.get(get); System.out.println("Result of get: "); for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); }第七个 FilterList,它有两个选项,需要全部通过,还是一个通过就行,MUST_PASS_ALL,MUST_PASS_ONE。 public class CustomFilter extends FilterBase { private byte[] value = null; private boolean filterRow = true; public CustomFilter() { super(); } public CustomFilter(byte[] value) { this.value = value; } @Override public void reset() { this.filterRow = true; } @Override public ReturnCode filterKeyValue(KeyValue kv) { if (Bytes.compareTo(value, kv.getValue()) == 0) { filterRow = false; } return ReturnCode.INCLUDE; } @Override public boolean filterRow() { return filterRow; } @Override public void write(DataOutput dataOutput) throws IOException { Bytes.writeByteArray(dataOutput, this.value); } @Override public void readFields(DataInput dataInput) throws IOException { this.value = Bytes.readByteArray(dataInput); } }这里要讲的是 自定义filter,从FilterBase继承。 public class CustomFilter extends FilterBase { private byte[] value = null; private boolean filterRow = true; public CustomFilter() { super(); } public CustomFilter(byte[] value) { this.value = value; } @Override public void reset() { this.filterRow = true; } @Override public ReturnCode filterKeyValue(KeyValue kv) { if (Bytes.compareTo(value, kv.getValue()) == 0) { filterRow = false; } return ReturnCode.INCLUDE; } @Override public boolean filterRow() { return filterRow; } @Override public void write(DataOutput dataOutput) throws IOException { Bytes.writeByteArray(dataOutput, this.value); } @Override public void readFields(DataInput dataInput) throws IOException { this.value = Bytes.readByteArray(dataInput); } } 然后打成jar包,要在hbase-env.sh中指明路径。 export HBASE_CLASSPATH="/hbase/target/hbase-customfilter.jar",然后就可以在客户端中使用它了。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册