per

阅读 / 问答 / 标签

用什么代词替换some paper plates

what

cpu是r7 1700,电源mwe550,主板b450m迫击炮,显卡能换成2070super吗

能的,原全没问题,上吧!

whisperofhope是怎样创作的

Whisper of Hope是由德国音乐家Johannes Bornlof创作的的一首钢琴曲。根据Johannes bornlof在他的官网上的自述,这首曲子是在他的一个创作挑战项目中产生的。

person和prison发音上有什么区别

person[ˈpə:sən]prison[英][ˈprizən] [美][ˈprɪzən]

kaiser permanente是什么意思

kaiser permanente凯泽永久 医疗网 【例句】1. Arthur klatsky is a heart doctor at the kaiser permanente medical center in oakland , california亚瑟?克拉斯盖是加利福尼亚州奥克兰永皇研究中心的心脏病医生。 2. " obesity in middle age increases the risk of future dementia , " said dr rachel whitmer , of kaiser permanente , a health care organisation in oakland , california中年肥胖,会增加未来罹患痴呆症的风险,加州奥克兰卫生护理机构kaiserpermanente的芮秋?惠特莫博士说。 3. “ obesity in middle age increases the risk of future dementia , ” said dr rachel whitmer , of kaiser permanente , a health care organization in oakland , california中年肥胖,会增加未来罹患痴呆症的风险,加州奥克兰卫生护理机构kaiserpermanente的瑞秋.惠特莫博士说。 4. Klatsky is a senior consultant in cardiology and an adjunct investigator at the division of research at the kaiser permanentemedical center in oakland , calif克拉斯基毕业于哈佛医学院,他曾担任哈佛医学院心脏科的主任( 1978 ~ 1994 ) ,并领导冠状动脉医疗小组( 1968 ~ 1990 ) 。 5. Kaiser permanente , a health care organization in the us , has publicly reported greenhouse gas emissions for 2006 and is being certified as a climate action leader in the state of california美国健保机构凯撒医疗中心公开其2006年的温室气体排放量,在加州获验证为气候环保精英。 6. " the message is really obesity in the abdomen matters even more than obesity overall , " dr . carlos iribarren of kaiser permanente of northern california in oakland , the study " s lead author , said该研究主笔、奥克兰的北加州凯瑟医疗中心的伊瑞贝伦医生说:这项讯息是,腹部肥胖真的不能小看,甚至比整身肥胖还严重。 7. " it " s too early to say whether this will relate to anything to do with human health , " says dr . arthur klatsky , senior consultant in cardiology at kaiser permanente medical center in oakland , calif . , and a pioneer in studying the effects of alcoholic beverages on cardiac health in humans英语新闻学习http : news . jewelove . net “现在就说喝红酒是否与身体健康有任何关系还太早, ”阿瑟克拉斯基博士说,他是加利福尼亚州奥克兰凯撒永恒医学中心的心脏病学资深顾问,也是研究酒精饮料对人类健康影响的先驱。 相关词汇permanente schleuse是什么意思 circuito permanente de jerez是什么意思 fondation de formation permanente是什么意思 comision permanente del pacific sur是什么意思 kaiser是什么意思 georg kaiser是什么意思 kaiser bazan是什么意思 kaiser ver是什么意思 kaiser kuo是什么意思 相邻词汇热门词汇kaiser kabel是什么意思 kaiser kabel gmbh是什么意思 kaiser knuckle是什么意思 kaiser kuo是什么意思 kaiser melange是什么意思 kaiser pk是什么意思 kaiser resources ltd是什么意思 kaiser roll是什么意思 kaiser steel是什么意思

电脑出现reboot and selsct proper boot device or lnsert boot media in selec

开机进不了系统出现 eboot and select proper boot device r Insert boot Media in selected boot device and press a key ♂一、用系统光盘修复系统 1、设置光驱启动 Award BIOS 6.0设置 重启,按Del进入BIOS 6.0设置界面,找到Advanced Bios Features(高级BIOS参数设置)按回车进Advanced Bios Features界面,用键盘方向键盘选定First Boot Device ,用PgUp或PgDn翻页将它右边的HDD-O改为CDROM(光驱启动),按ESC,按F10,再打Y,回车,保存退出。 AMI BIOS 8.0设置 启动电脑,按Del进入AMI BIOS设置程序主界面,在上方菜单中找到“Boot”选中,回车,在打开的界面中用方向键↑↓选中“ Boot Device Priority”,回车,进到“1st Boot Device”界面,回车,进options界面,用方向键↑↓选中“CD/DVD:3S-PH……”(光驱启动),回车,按Esc,按F10,再按Y,回车,保存退出。 2、将XP安装光盘插入光驱,重启,在看到屏幕底部出现CD……字样的时候,及时按任意键,否则计算机跳过光启又从硬盘启动了。 3、首先会出现WINXP安装界面,选择“在现在安装WINXP……”,回车。 4、有的光盘出现“Windows XP 安装协议,Windows XP Professional最终用户安装协议”界面中,按下“F8”键,同意接受许可协议。 5、当出现“假如下列WINXP安装中有一个己损坏,安装程何以尝试将其修复”界面时,选“所要修复的WINXP安装”即可。 6、以下操作,按中文提示进行就可以了。 二、重装系统。 ♂安全模式能进吗?进就系统还原 不行重装把 ♂系统破坏 只能重装系统吧 ♂你可能将字母打错了,应该是:Reboot and Select proper boot device or insert boot media in seiected boot device and press a key 英文意思是:重新启动并且选择适当的启动装置或者插入启动光盘.在选中启动装置后.按一个键. (1)可能是你的安装盘中缺少引导文件.而无法进入系统.需要启动盘来启动电脑. (2)系统安装失败.硬盘中根本就没有系统.(你的安装盘存在问题,建议换一张盘试试) (3)光驱坏了 (4)还有几率很小的可能,就是硬盘的数据线插口出松了.内存条和显卡重新插拔一下.以及硬盘有坏道. (5)将系统重新装一次.不要用----刚才用过的系统盘. ♂显然是装好系统后没有在BIOS里设置启动设备,启动电脑按DEL键,进入BIOS设置界面,假如是AWARD BIOS,则选择BIOS FEATURES SETUP,将BOOT SEQUENCE处改为C开头的,保存并重启;假如是AMI Bios 则选择BOOT选项卡,选Boot Device Priority,将1st Device Priority设置成为你的硬盘,保存并重启。

sqlmap的tamper过waf关键字过滤 将select变为selecSELECTt的函数是哪一个

但很多时候还是得静下来分析过滤系统到底过滤了哪些参数,该如何绕过。sqlmap中的tamper给我们带来了很多防过滤的脚本,非常实用,可能有的朋友还不知道怎样才能最有效的利用tamper脚本。当然使用脚本之前需要确定的就是系统过滤了哪些关键字,比如单引号、空格、select、union、admin等等。所以有的时候我们会发现,注入成功了但是dump不出数据,很可能是select被过滤了等等原因。如何判断使用哪个脚本最简单的办法就是在url参数中手工带入关键词,判断是否被过滤。如图:直接加个单引号被过滤,说明注入时单引号是没法用的。空格、等于号都没有过滤,成功报错。select被过滤。以此类推,当sqlmap注入出现问题时,比如不出数据,就要检查对应的关键词是否被过滤。比如空格被过滤可以使用space2comment.py,过滤系统对大小写敏感可以使用randomcase.py等等。

kaiser permanente是什么意思

kaiser permanent健康维护组织凯泽永久(美国)例句"The National Institute of Mental Health and Kaiser Permanence, Norther Permanente Northern California , also took part in the latest study.美国国家心理卫生研究院和北卡罗来纳的研究机构“凯泽永久”也加入了最新的研究当中。

remain continue persist maintain区别?

保持 继续 坚持 意思虽然相近但是还是可以区分的,根据语镜区分

insist on 与persist in 有什么区别

insist=in+sist,“坚持做一件事”,搭配insistonpersist=per(through)+sist,“坚持反复做同一件事”,搭配persistin英语里的insist和persist两个词。在英汉词典里查都是"坚持"的意思,用汉语翻译根本看不出这两个词的区别。而这种区别如果你查询或者使用英英词典的话,一开始就会明白。请看在longmanwebdictionary中对insist的解释是:tosayfirmlyandrepeatedlythatsomethingistrue,especiallywhenotherpeoplethinkitmaynotbetrue(尽管别人说某件事情不对,也执意要说而且是重复不断地说那件事情是对的);而对persist的解释是:tocontinuetodosomething,althoughthisisdifficult,orotherpeoplewarnyounottodoit.(继续不断地做某件事情,尽管这件事可能很难,或他人劝你不要做)。两者的差别通过查英英词典就一目了然了。

persist与innocent有两种名词形式,有什么区别吗?

没有。

Spark中cache和persist的区别

通过观察RDD.scala源代码即可知道cache和persist的区别:def persist(newLevel: StorageLevel): this.type = {if (storageLevel != StorageLevel.NONE && newLevel != storageLevel) {throw new UnsupportedOperationException( "Cannot change storage level of an RDD after it was already assigned a level")}sc.persistRDD(this)sc.cleaner.foreach(_.registerRDDForCleanup(this))storageLevel = newLevelthis}/** Persist this RDD with the default storage level (`MEMORY_ONLY`). */def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)/** Persist this RDD with the default storage level (`MEMORY_ONLY`). */def cache(): this.type = persist()可知:1)RDD的cache()方法其实调用的就是persist方法,缓存策略均为MEMORY_ONLY;2)可以通过persist方法手工设定StorageLevel来满足工程需要的存储级别;3)cache或者persist并不是action;附:cache和persist都可以用unpersist来取消

persist in是什么意思 persist in的中文翻译、读音、例句?

persist in在英语中代表”固执于、坚持不懈”的意思,在英美地区还有”执着”的意思,在线读音是[美],persist in常被用作动词,在《英汉新词词典》中,共找到52个与persist in相关的用法和句子persist in的翻译1.固执于例句:And if you say no, then i will persist翻译:/And if you say no, then l will persist自考/成考有疑问、不知道自考/成考考点内容、不清楚当地自考/成考政策,点击底部咨询官网老师,免费领取复习资料:https://www.87dh.com/xl/

insist on 与persist in 有什么区别

persist in表示坚持行动,有时表示固执已见或坚持不改,如: She persists in her spare time studies. 一直坚持业余学习,不改变. insist on表示坚持主张、意见. 如: He insisted on leaving that day.

adb怎么刷入persist分区

看adb使用说明刷。解锁手机,解锁BL还是之前的操作,使用常规的解锁命令fastbootoemunlock。刷入ROOT权限或者刷入TWRP_recovery中文版,其实两者都是一样的,具体选择哪一个看自己喜好。使用ADB命令刷入persist分区,首先我们把下载的persist分区文件放到手机内部存储,再输入以下命令回车修复文件下载。

关于persist的单选

One can use both words (in), and (with) in that regard, but it depends on the person to say, because let them know is your dynamic.

persist挂载失败

1、首先persis挂载失败去官网重新下载线刷包。2、其次进入(trwp)recovery把解压后image文件夹复制到手机中。3、最后点击“安装”“刷入image”刷入对应的镜像即可。

androidpersist保存文件

persist分区。androidpersist保存文件通常在恢复出厂设置以后都是在persist分区。安卓(Android)是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。

persist后面接什么介词?

你好!很高兴为你解答。persist in 坚持 固执于希望能帮到你。

persist的各种形式

名词:persister 动词过去式:persisted 过去分词:persisted 现在分词:persisting 第三人称单数:persists

如何在android的源代码中添加persist属性

  SystemProperties与Settings.System    1 使用 SystemProperties.get  如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。  如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。    在c++中就是对应JAVA的两个函数就是property_set, property_get,其实JAVA是通过JNI调用这两个函数的。  JAVA代码如下:  import android.os.SystemProperties;  SystemProperties.set("persist.sys.language", zone.getID());  String lang= SystemProperties.get("persist.sys.language");  获取方法:  boolean fastfoodenable = SystemProperties.getBoolean("persist.sys.fastfoodenable", false);  设置方法:  SystemProperties.set("persist.sys.fastfoodenable", "true");    C  #include <cutils/properties.h>  property_set("persist.sys.language", "zh");  property_get("persist.sys.language", propLang, "en");  在adb shell可以通过以下的命名读取和修改  #getprop persist.sys.language  #setprop persist.sys.language zh    创建与修改android属性用Systemproperties.set(name, value),获取android属性用Systemproperties.get(name),需要注意的是android属性的名称是有一定的格式要求的,如下: 前缀必须用systemcoreinitproperty_service.c中定义的前缀 ,进行系统属性设置的程序也必须有system或root权限  如果我们要添加一个property:例如:silvan_liu  路径:system/core/rootdir/int.rc  在on post-fs-data 目录下  setprop persist.sys.silvan_liu 1//persist.sys 前缀名; 1为初始值  PS:不同前缀名权限不同,这里就不一一说明;还有为什么要加载on post-fs-data目录下,这和int.rc的语法有关        2 使用 Settings.System.putInt  这种方式会保存变量到Settings 数据库中,飞行模式等的开关就是用这种方式实现的。  首先需要定义一个系统属性值  路径:frameworks/base/core/java/android/provider/Settings.java  public static final String VIVIEN_FASTFOOD= "hungry";  1)获取方法如下:  @Override  public void onResume()  {  super.onResume();  if(Settings.System.getInt(getContentResolver(), Settings.System.VIVIEN_FASTFOOD,0)==1)  {  mYesORNo.setChecked(true);  }  else  mYesORNo.setChecked(false);  }  2)设置  if (mYesORNo.isChecked()) {  Settings.System.putInt(getContentResolver(),  Settings.System.VIVIEN_FASTFOOD, 1);  } else {  Settings.System.putInt(getContentResolver(),  Settings.System.VIVIEN_FASTFOOD, 0);  }    需要import android.provider.Settings;  android源码开发中,常常要用到一些全局标志或者说变量,这时候我们可以给android系统添加自己想要的属性。  1.Settings.system  这种系统属性我们经常用到,例如飞行模式的开启和关闭,我们就是去改变Settings.system.AIRPLANE_MODE_ON 的值。  下面就介绍下我们怎样去定义一个系统属性。例如要添加一个属性名为“SILVAN_LIU”  路径:frameworks/base/core/java/android/provider/Settings.java    public static final String SILVAN_LIU = "silvan_liu";  public static final String[] SETTINGS_TO_BACKUP ={  ~  +SILVAN_LIU  ~  }  这样添加后,你就是可以通过Settings.System.getInt(getContentResolver(), Settings.System.SILVAN_LIU,0) 和Settings.System.getInt(getContentResolver(), Settings.System.SILVAN_LIU,0)去得到和设定SILVAN_LIU的属性值。    2.SystemProperties  创建与修改android属性用Systemproperties.set(name, value),获取android属性用Systemproperties.get(name),需要注意的是android属性的名称是有一定的格式要求的,如下: 前缀必须用systemcoreinitproperty_service.c中定义的前缀 ,进行系统属性设置的程序也必须有system或root权限  如果我们要添加一个property:例如:silvan_liu  路径:system/core/rootdir/int.rc  在on post-fs-data 目录下  setprop persist.sys.silvan_liu 1//persist.sys 前缀名; 1为初始值  PS:不同前缀名权限不同,这里就不一一说明;还有为什么要加载on post-fs-data目录下,这和int.rc的语法有关。    以上是我实际项目中运用到的地方,可能认识的不够深刻,还需继续摸索。转载

persist后面能不能加that从句

that 用法pron.1. 那;那个,那人,那事,那东西That"s my English teacher over there.那边是我的英文老师。2. (已被提到的)那个,那人,那事,那东西Who told her that?那是谁告诉她那件事的?3. 前者4. (用作关系代词的先行词)那,那个What is that which you have just stuffed into the plastic cup?你刚才塞在塑料杯里的是什么东西?5. (代替句中名词,避免重复)The output of steel this year has increased by 20% compared with that in 1992.今年钢产量比一九九二年增长了百分之二十。6. (用作关系代词,引导关系从句)a.1. 那,那个That book isn"t mine.那本书不是我的。ad.1. 【口】那样,那么Is the problem that easy?问题有那么简单吗?

手机的persist分区是干嘛的

如果这个出了问题,会提示“查找手机存储损坏”。

insist on和persist in区别

insist on:后常须加介词on,然后接名词、代词或动名词。该动名词前可加物主代词或名词、人称代词的宾格形式作其逻辑主语。 persist in:表示“坚持该怎么做”时,从句的谓语动词要用虚拟语气,即(should)+动词原形; 作不及物动词时,可表示尽管有不利条件,非常艰难,但还顽强地继续存在。 扩展资料   They insist on sticking to the letter of the law.   他们坚持严守法律的`字面意义。   I insist on paying for the damage.   我坚持要赔偿损失。   Mr Straw issued a stern warning to those who persist in violence.   斯特劳先生向那些坚持进行暴力活动的人发出了严正警告。

小米手机persist怎么进入

1、首先确保小米手机已经处于Root状态,没有Root的话需要先进行Root。2、其次打开手机上的“文件管理器”,并授权Root权限,如果没有授权的话需要先进行授权。3、最后在文件管理器中,进入“/data/property/”目录,找到一个名为“persist.sys”的文件。选择使用“文本编辑器”打开。即可进入小米手机persist文件。

uphold 和persist和insist on 三者的区别?

insist: 后接on 通常用于对意见、主张等的坚持。 persist:后接in 用于褒义指坚持继续做某事,有时用于贬义,指不听劝告,顽固坚持。 uphold既可指积极努力对陷入困境者的支持,也可指给某人在行动、道义或信仰上的支持。

persist后可直接加动词吗

后面可以直接加动词

persist 和 persevere都是坚持的意思,但有什么区别么? 是否可以互换?

persist:后接in 用于褒义指坚持继续做某事,有时用于贬义,指不听劝告,顽固坚持。 persevere:后接in或on 含褒义,强调坚持不懈的努力。 eg:Even though everybody told him he was wrong, he persisted in his opinion.If you persevere with your search for a job, you are sure to find it soon.

insist on 与persist in 有什么区别

insist=in+sist,“坚持做一件事”,搭配insistonpersist=per(through)+sist,“坚持反复做同一件事”,搭配persistin英语里的insist和persist两个词。在英汉词典里查都是"坚持"的意思,用汉语翻译根本看不出这两个词的区别。而这种区别如果你查询或者使用英英词典的话,一开始就会明白。请看在longmanwebdictionary中对insist的解释是:tosayfirmlyandrepeatedlythatsomethingistrue,especiallywhenotherpeoplethinkitmaynotbetrue(尽管别人说某件事情不对,也执意要说而且是重复不断地说那件事情是对的);而对persist的解释是:tocontinuetodosomething,althoughthisisdifficult,orotherpeoplewarnyounottodoit.(继续不断地做某件事情,尽管这件事可能很难,或他人劝你不要做)。两者的差别通过查英英词典就一目了然了。

hibernate中save,persist和saveorupdate这三个方法的不同之处

所有这三个方法,也就是save()、saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别。例如,save()只能INSERT记录,但是saveOrUpdate()可以进行记录的INSERT和UPDATE。还有,save()的返回值是一个Serializable对象,而persist()方法返回值为void。save与saveOrUpdate的区别 save通过INSERT语句将对象保存到数据库,产生一个新的ID,将数据插入到数据库,并返回一个Serializable对象。 saveOrUpdate能根据对象是否已存在,而执行插入或更新。显然saveOrUpdate更加灵活,但它需要额外判断对象是否已存在。save与persist的区别返回类型不同:save返回Serializable对象,而persist返回voidID赋值时机不同:二者同样用于将transient实例持久化,但persist不保证ID值立即赋给持久化实例,可能会在flush的时候给ID赋值。transaction外的行为不同:如果在transaction之外调用,persist保证会立即执行INSERT语句;而save则不保证(save返回一个identifier,如果必须执行INSERT来获取该identifier,则就会立即执行INSERT,而不论是在transaction之内或之外)使用场景:由于上述第三点区别,persist方法适用于被扩展的Session上下文的长期运行的会话中(useful in long-running conversations with an extended Session context);而save则不适用。

persevere与persist在英语中有什么区别?

正确答案应该是persist,在这里表示“继续存在,持续下去”的意思,其它几个词没有这个意思。比如:contactyourdoctorifthecoughpersists.如果持续咳嗽,就与医生联系。

persist和insist的区别?

persist vi. 坚持;固执 持久;持续 是不及物动词,不能单独用,常用的短语有: persist in sth. 坚持做某事 persist in doing sth. 坚持做某事 persist with 继续努力,坚持不懈 insist可以做及物动词也可以做不及物的,做不及物的后面要加ON或UPON有以下意思: 坚持; 坚决主张; 坚决认为(on,upon) 坚决要求,定要 insist on sb."s innocence 坚持认为某人无罪 insist on a point 强调一点 insist on being present 坚持要求出席 I insisted on his coming with us. 我坚持要求他和我们一起来. 做及物动词时后面加从句,有以下意思: 坚持; 坚决主张; 坚决认为 坚决要求; 定要 I insist that you (should) be present. 请您务必到场. They insisted that she (should) be invited. 他们坚持要邀请她. 综上,persist 和insist的用法不同,但可以表示相同或相近的意思,注意后接词及是否及物即可.

persist和insist的区别?

persist 一般坚持insist关键是用法insist oninsist that+虚拟语气should (可以省略)

persist的名词

persist本身的名词形式没有。 persist的派生名词有:persister坚持者。 persist:v. 顽强地坚持;执著地做;维持;保持;持续存在 。 扩展资料   例句:   These problems persisted for much of the decade.   这些问题在那10年的大部分时间里一直存在。   If the symptoms persist, it is important to go to your doctor.   如果这些症状持续存在,一定要去看医生。   He urged the United States to persist with its efforts to bring about peace   他敦促美国继续进行和平斡旋。

persist炸了?

persist音标[pu04d9"sist] 读音 汉语翻译vi. 坚持, 固执, 持续, 坚称【经】 持续

persist是什么意思

persist [英]pu0259u02c8su026ast [美]pu0259ru02c8su026ast v. 坚持;固执;存留;继续存在 [例句]Specifically , the wave of popular dissatisfaction sweeping across europe would persist.具体而言,席卷欧洲的普遍不满情绪将会持续。

persist是什么意思

  persist英 [pu0259u02c8su026ast] 美 [pu0259ru02c8su026ast]  v.坚持; 存留; 固执; 继续存在;  [网络]持续; 坚持,固执; 持久;  [其他]第三人称单数:persists 现在分词:persisting 过去式:persisted 过去分词:persisted 形近词: assist resist desist

求An Experiment in Misery,这篇短文的中文翻译。

在你邮箱里。注意查收。

Perry Como的《Sonata》 歌词

歌曲名:Sonata歌手:Perry Como专辑:Today & YesterdaySonaMick O"Brienrhy:下面可能会有错(不懂德文)Ag breacadh an lae do chumar ag siúl(The light of the sun took us strolling)aoibhneas an tsaoil amach romhainn(with the treasures of the world lying ahead,)clocha draíochta chomh geal lenár súile(Magic stones as bright as our eyes)casán ag glioscarnach dúinn (lighting a path before us)Suaimhneas na coillte is ceol inár gcroithe(The peace of the woods was music to our hearts)macalla fuaim an tsrutháin(echoing the sound of the streams,)duilleoga fómhar mar ghuth ar an ngaoth(Autumn leaves - the voice on the wind)sé nádúr is cúis lenár ngrá (as nature is the source of our love)A`Taisteal sa choill seo ar fán is ar fuaidreamh(Now the stones are dancing in the sky)réalta geala eolais ag lonradh don rí(while the world is quietly sleeping,)A`Taisteal sa choill seo ar fán is ar fuaidreamh(Lovely visions in the secret garden,)clocha bána ag lasadh ár slí (of dreams floating all around us)Anois tá réalta a`rince sa spéir(Traveling in this forest like a lost soul)is an saol ina gholadh go sámh(Bright stars of knowledge shining for the king)aislingi áille i ngairdín mo rún(Traveling in this forest like a lost soul)brionglóidí thart orainn ar snámh (Bright stones lighting our way)Súile síor lasta le solas(Eyes ever shining with light)súile faoi gheasa na rún(Eyes under a secret spell)taibhreamh ar sheoda an ghairdín(Dreaming of the jewels in the garden)iontais nach sceithfear go buan (of wonders that will never be revealed )A`Taisteal sa choill seo ar fán is ar fuaidreamh(Now the stones are dancing in the sky)réalta geala eolais ag louradh don rí(while the world is quietly sleeping,)A`Taisteal sa choill seo ar fán is ar fuaidreamh(Lovely visions in the secret garden,)clocha bána ag lasadh ár slí (of dreams floating all around us)http://music.baidu.com/song/8768890

有人知道RMA Percentage 是什么意思吗?

RMAabbr. (英国)皇家陆军军官学校(Royal Military Academy)percentage[pE5sentidV]n.百分数, 百分率, 百分比

geforceexperience怎么添加天刀

geforceexperience怎么添加天刀,先点击一下天刀,再点击一下需要添加的人物就行了。

为什么dubbo使用ZkClient作为zookeeper的客户端

1 ) ZooKeeper的Watcher是一次性的,用过了需要再注册;2 ) session的超时后没有自动重连,生产环境中如果网络出现不稳定情况,那么这种情况出现的更加明显;3) 没有领导选举机制,集群情况下可能需要实现stand by,一个服务挂了,另一个需要接替的效果;4) 客户端只提供了存储byte数组的接口,而项目中一般都会使用对象。5 )客户端接口需要处理的异常太多,并且通常,我们也不知道如何处理这些异常。

求一首英文歌 男生唱的 里面有很多superhero

http://www.170mv.com/song/93679.html是这个啦,《Superhero》-Simon Curtis 每次听到这首歌就如同和蜘蛛侠一样翱翔在城市中的高楼大厦之中,不亚于《he"s a 船长》

工程网络计划cpm,pERT,cpA,MPM代表什么

我认为最靠近的释意:Multi-Project Management 项目管理 工程网络计划的编制方法... 国际上,工程网络计划有许多名称,如CPM、PERT、CPA、MPM等。 MPM方法是使...

CPM, PERT, CPA, MPM国际上工程网络计划全称

CPM:关键路径法PERT:计划评审法CPA:关键路径分析法MPM:工艺信息管理法(运用较少)

Ruby,Perl,Python,Lua等语言相互之间都有哪些异同点

本文从RoR对Ruby的影响、Ruby的优势等多个角度分析了Ruby比Python成功的原因。伴随着RoR的风行,Ruby语言受到越来越多的开发者的关注,同为脚本语言,Python的地位却略显尴尬,什么样的原因,造成了这样的局面?笔者认为有以下几个方面:一、RoR的推波助澜笔者认为,Ruby的成功,很大一部分是由于RoR的带动。几年前,如果你没听过RoR倒是情有可原,但如果今天,RoR对你来说,还是一个陌生词汇的话,那你就有点危险了。:)什么是RoR呢?全称,RubyonRails,简称,RoR或者Rails。它是个全栈的(full-stack)web应用框架,它为开发者提供了构建一个web应用所需的完整基础结构,并且严格按照MVC(模型-视图-控制器)架构进行开发。RoR致力于提高开发者的开发效率,希望通过尽量少的代码,完成尽可能多的功能。基于这样的考虑,RoR有两大设计原则,一是,不要重复自己(Don""tRepeatYourself);二是,惯例优于配置(ConventionOverConfiguration)。使用RoR,你甚至可以通过简单的几条命令行、几行代码,就完成一个功能强大的web应用程序,这极大地提高了开发者的开发效率。2004年7月,RoR一经发布,在短期内,便受到很多开发者的追捧。时至今日,RoR已经被全世界的开发者们所关注,它带给开发者的效率提升,是前所未有的;它带给业界关于软件开发的思考,也是意义深远的。在RoR如此风行的大背景下,RubyonRails,这个需要使用Ruby进行开发的web框架,也自然地带动了Ruby语言的发展。在下面的“Ruby语言受关注程度趋势图”上,可以清晰地看出,Ruby语言在RoR发布也就是2004年7月后,进入了高速发展期。Ruby因为有了RoR这样的“杀手级”应用,变得春风得意,那么Python呢?在《浅谈Python语言》一文中,我们提到了Python具有丰富的API库,在web开发方面,也有Django、Turbogears这样的一些框架,就运行速度而言,Python比Ruby快;就社区而言,Python也比Ruby成熟,可是为什么Python没有产生一个像RoR这样的“杀手级”应用呢?Python语言的创始人Guido在接受InfoQ采访时,是这样解释的:“我不喜欢KillerApplication,因为那会让多数人或者社区将精力集中于一个地方。Python是一个应用广泛的语言,基于Python已经产生了很多好用的Web框架,比如Django等。但是Python不KillerApplication,至少目前是这样,而且我相信随着Python社区的发展,会有很多KillerApplications自然出现。我喜欢多样化的应用。”通过这个观点,我们可以看出Python在其发展道路上,追求的是一种均衡,一种“大而全”。“会有很多KillerApplications自然出现”,这点,我想我们需要拭目以待。单就“均衡”而言,笔者认为这很危险,作为一门脚本语言,试图做Java之类传统语言做的事情,不太可取。以Java为例,在web应用上,有太多的框架可供选择,不错,“在不同的场景用不同的框架”,这想法很好。可是,在实际应用中,有多少开发者可以根据项目特点,正确、合理地选择框架?与其到最后,用户还不知道该如何选择,还不如一开始就替用户做出一个选择。作为Python的使用者,我更愿看到有个Python的“杀手级”应用出现,进而带动Python更快速地发展。你可以说RoR成就了Ruby,可是Rails为什么偏偏选择了Ruby?!Ruby优势何在?二、Ruby的优势1.比Perl更强大,比Python更面向对象“比Perl更强大,比Python更面向对象”,这是Ruby创始人Matz设计Ruby的初衷。Python既支持面向过程的编程也支持面向对象的编程,而Ruby则是完全面向对象。在Ruby中,任何东西都是对象,包括Python中的基本数据类型;每个过程或函数都是方法。例如,取-3的绝对值,在Python中,是这样的:abs(-3)。而在Ruby中,则是这样的:-3.abs。这种OO的方式,显得更加直观。2.强大的语法功能单就语法的简单性而言,Ruby不及Python。但解决一些较复杂的问题,Ruby强大的语法功能,有助于降低问题的复杂度。例如:Ruby以“块”的方式来实现列表内的条件、循环语句,比Python的更灵活、更具通用性。Ruby具有类似Lisp的彻底的函数方式的条件、循环语句等。Ruby的迭代器功能可以将流程控制结构抽象化。3.强大的字符串处理、正则表达式功能Matz认为:Ruby>(Smalltalk+Perl)/2。Ruby类库是对Perl语言功能的面向对象方式的重组,因为借鉴了很多Perl的东西,使得字符串处理、正则表达式这块,Ruby同样强大。4.不会僵住的“胶水语言”同样是“胶水语言”,Ruby比Python更灵活。使用过一段时间的Python,你会发现,Python比较依赖第三方的东西。相比较,Ruby则更依赖自身。例如,Ruby可以使用(UNIX的)绝大部分的系统调用,单独使用Ruby也可以进行系统编程等。有优势,Ruby就一定可以成功了?Python同样也有很多优势!对,还得看当时所处的环境。三、时势造英雄这点还得回到RoR的崛起。Ruby,1995年12月正式发布,2000年进入美国;2004年7月,RoR正式发布。RoR的出现时间,值得玩味。在下面的“Java语言受关注程度趋势图”上,可以看到,2004年7月前后,Java处于一个相对“衰退期”。提到Java,大家应该都会想到J2EE。J2EE应用程序的广泛实现是从1999、2000年开始的,它的出现带来了诸如事务管理之类的核心中间层概念的标准化,但是因其开发效率、学习难度和实际性能的问题,在实践中没有获得完全的成功。作为J2EE核心技术的EJB(2.x),更是因其高昂的学习代价、极低的开发效率和极高的资源消耗,备受指责。在这样一个大背景下,2003年,Spring框架诞生了。Spring的设计思想在于“使J2EE开发更加简单”。这个设计思想,在包括Java领域在内的众多软件开发领域引起了广泛关注。软件开发者们开始思考,如何让开发向着一个更简单的方向发展。RoR在这一时期出现,无疑是顺应了这样一个潮流。可以这么说,是历史选择了RoR,当然也选择了Ruby。遇到合适的机遇,还不够,俗话说得好:“众人拾柴火焰高”。四、众星捧月Ruby的出现,受到了两大主流平台Java和.NET的极力追捧。2006年9月,SUN雇佣了JRuby的主要开发者CharlesNutter和ThomasEnebo;一年不到,2007年6月14号,JRuby1.0正式发布。SUN在其JavaIDENetBeans6.0M10中,更是集成了对Ruby/JRuby的支持。反观Python的Java实现——Jython,则没有这么幸运,发展至今,它并没有得到SUN的支持。而Microsoft,也在2007年7月,推出了Ruby的.NET实现——IronRuby的预览版。相信SUN和Microsoft对Ruby的竞相推崇,必然推动Ruby的进一步发展。基于以上几点,笔者认为Ruby的成功不是偶然,并且相信这样的成功还会持续下去。对于Python的未来,我们也将拭目以待。

tissure和paper towels的区别

tissue指餐巾纸,bath tissue 指厕纸,paper towels指大张擦手纸,厨房用纸

zookeeper的snapshot可以删除吗

2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑

paper towel是什么意思

paper towel英 [u02c8peipu0259 u02c8tauu0259l] 美 [u02c8peu026apu0259r u02c8tau028au0259l] 厨房纸巾; 纸巾双语例句1She tore off two sections of paper towel and folded them lengthwise. 她撕下两格纸巾,然后纵向对折。2He turns off the faucet with a paper towel. 他用纸巾把水龙头关闭了。

JAVA 为什么不同注册中心(zookeeper,Eurake) 注册的服务不能互相调用

底层实现服务注册与发现的原理都不一样。。。你要改狠多东西才可以互相调用的。。

Totheworldyoumaybeoneperson,buttoonepersonyoumaybetheworld.中文是什么

对于整个世界来说你可能只是一个人,但对于一个(爱你的)人来说,你可能是整个世界。

为什么不使用ZooKeeper

ZooKeeper作为发现服务的问题ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且,作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨了!而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的“法定人数”时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当Service发现服务得不偿失。做出正确的选择:Eureka的成功我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广的网络分割故障,并实现“0”宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些“濒死”的服务器;如果在Eureka中注册的服务, 它的“心跳”变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时,这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很”健康“的,只是因为网络分割故障把Eureka集群分割成了独立的子网而不能互访而已。幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入”自我保护模式“,同时保留那些“心跳死亡“的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对于”死亡“的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出”自我保护模式“。所以Eureka的哲学是,同时保留”好数据“与”坏数据“总比丢掉任何”好数据“要更好,所以这种模式在实践中非常有效。最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制,这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供了Restful-API接口,方便第三方程序集成Eureka的功能。

为什么不使用ZooKeeper

为什么不使用?我们公司项目就使用zookeeper,包括阿里的现在很多项目也使用zookeeper做分布式应用程序数据的一致性处理方案。

zookeeper 用到哪些设计模式

  ZooKeeper作为发现服务的问题  ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它 很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。  在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。  作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能 因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨 了!  而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的逗法定人数地时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。  如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况 下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是逗健康地的,可以正常提供服务的;所以导致到达这些节点的服务请求 被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)  更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了 一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!  如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台 很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务 群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当 Service发现服务得不偿失。  做出正确的选择:Eureka的成功  我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开 始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!  首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务注册信息而已。所以,再也不用担心有逗掉队地的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广的网络分割故障,并实现逗0地宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新 的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。  但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些逗濒死地的服务器;如果在Eureka中注册的服务, 它的逗心跳地变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时,这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很地健康逗的,只是因为网络分割故障把Eureka集群分割 成了独立的子网而不能互访而已。  幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入地自我保护模式逗,同时保留那些逗心跳死亡逗的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对于地死亡逗的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出地自我保护模式逗。所以Eureka的哲学是,同时保 留地好数据逗与地坏数据逗总比丢掉任何地好数据逗要更好,所以这种模式在实践中非常有效。  最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。  Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制,这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心 跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源 的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。  维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供 了Restful-API接口,方便第三方程序集成Eureka的功能。

为什么要使用ZooKeeper

记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。 但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑

zookeeper什么意思

zookeeper是动物管理员的意思。ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_homesrc ecipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。它的原理:ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos做了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。ZooKeeper的基本运转流程:1、选举Leader。2、同步数据。3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。4、Leader要具有最高的执行ID,类似root权限。5、集群中大多数的机器得到响应并接受选出的Leader。

etcd是什么东西?它和ZooKeeper有什么区别

etcdetcd作为最近很火的一个高可用性?键值对服务发现系统被Kubernetes等系统广泛使用他相比与zookeeper来说更加简单,在面对较小集群时可能会效率更高些?,而且他的编写语言Go本身就是一种多线程编程语言,确实有很大吸引人的地方(虽然我不懂Go语言,但是在学习docker时也是一睹其风采了)在Raft中,任何时候一个服务器可以扮演下面角色之一:Leader: 处理所有客户端交互,日志复制等,一般一次只有一个Leader.Follower: 类似选民,完全被动Candidate候选人: 类似Proposer律师,可以被选为一个新的领导人。leader选举阶段消息同步阶段Leader要求Followe遵从他的指令,都将这个新的日志内容追加到他们各自日志中:大多数follower服务器将日志写入磁盘文件后,确认追加成功,发出Commited Ok:在下一个心跳heartbeat中,Leader会通知所有Follwer更新commited 项目。对于每个新的日志记录,重复上述过程。zookeeper:zookeeper是基于paxos的简化版zab,我觉得确实很难理解?,以前看了好多遍《从paxos到zookeper》才感觉似懂非懂了,然而过了几个月发现又一脸蒙蔽了,在这里在整理一下(仅表示我自己的理解)ZAB协议中存在着三种状态,每个节点都属于以下三种中的一种:Looking :系统刚启动时或者Leader崩溃后正处于选举状态Following :Follower节点所处的状态,Follower与Leader处于数据同步阶段;Leading :Leader所处状态,当前集群中有一个Leader为主进程;在开始时,所有的节点都是looking状态并且每个节点都希望自己能成为leader节点,所有每个节点都会向集群中发送一个提案内容是选取自己作为leader节点,提案编号是ZXID(ZAB协议中使用ZXID作为事务编号,ZXID为64位数字,低32位为一个递增的计数器,每一个客户端的一个事务请求时Leader产生新的事务后该计数器都会加1,高32位为Leader周期epoch编号,当新选举出一个Leader节点时Leader会取出本地日志中最大事务Proposal的ZXID解析出对应的epoch把该值加1作为新的epoch,将低32位从0开始生成新的ZXID;ZAB使用epoch来区分不同的Leader周期),如果得到的提案的zxid比自己的大则说明发出这个题案的节点数据更新,则进行同意的投票,否则继续投自己,先得到多数的同意的节点当选为leader现在leader就可以进行管理了,zookeeper也是两段提交的实现,客户端提交事务请求时Leader节点为每一个请求生成一个事务Proposal,将其发送给集群中所有的Follower节点,收到过半Follower的反馈后开始对事务进行提交,ZAB协议使用了原子广播协议

阿里P8推荐:《Netty、Redis、Zookeeper高并发实战》看完真不错

移动时代、5G时代、物联网时代的大幕已经开启,它们对于 高性能、高并发 的开发知识和技术的要求,抬升了 Java工程师的学习台阶和面试门槛。 大公司的面试题从某个侧面映射出生产场景中对专项技术的要求。高并发的面试题以前基本是BAT等大公司的专利,现在几乎蔓延至与Java项目相关的整个行业。例如,与 Java NIO、Reactor模式、高性能通信、分布式锁、分布式ID、分布式缓存、高并发架构等 技术相关的面试题,从以前的加分题变成了现在的基础题,这也映射出开发Java项目所必需的技术栈: 分布式Java框架、Redis缓存、分布式搜索ElasticSearch、分布式协调ZooKeeper、消息队列Kafka、高性能通信框架Netty。 《Netty、Redis、Zookeeper高并发实战》为了让大家扎稳高性能基础,浅显易懂地剖析高并发IO的底层原理,细致细腻地解析Reactor高性能模式,图文并茂地介绍Java异步回调模式。掌握这些基础原理,能够帮助大家解决Java后台开发的一些实际问题。 本书共12章,主要介绍高性能通信框架Netty,并详尽介绍Netty的EventLoop、Handler、Pipeline、ByteBuf、Decoder、Encoder等重要组件,然后介绍单体IM的实战设计和模块实现。本书对ZooKeeper、 Curator API、Redis、Jedis API的使用也进行详尽的介绍,让大家具备高并发、可扩展系统的设计和开发能力。 由于内容较多,本次将展示部分截图,如果看得不过瘾想更加深入地了解本笔记彻底掌握,只需转发后私信回复【666】即可来获取免费领取方式了!

ZooKeeper在HBase中的应用

ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。 既然ZooKeeper的作用这么大,那我们就来详细说说ZooKeeper在HBase中的应用叭! 一个分布式HBase系统安装依赖于一个运行着的ZooKeeper集群,所有参与的节点和客户端必须能够正常访问运行着的ZooKeeper集群。HBase默认为你提供一个节点的ZooKeeper集群,它会伴随着HBase start/stop进程的启动/停止而启动/停止。那么HBase主要用ZooKeeper来干什么呢?HBase主要用ZooKeeper来实现HMaster选举与主备切换、系统容错、RootRegion管理、Region状态管理和分布式SplitWAL任务管理等。 一,HMaster选举与主备切换 HMaster选举与主备切换的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。 二,系统容错 当HBase启动时,每个RegionServer都会到ZooKeeper的/hbase/rs节点下创建一个信息节点(下文中,我们称该节点为”rs状态节点”),例如/hbase/rs/[Hostname],同时,HMaster会对这个节点注册监听。当某个 RegionServer 挂掉的时候,ZooKeeper会因为在一段时间内无法接受其心跳(即 Session 失效),而删除掉该 RegionServer 服务器对应的 rs 状态节点。与此同时,HMaster 则会接收到 ZooKeeper 的 NodeDelete 通知,从而感知到某个节点断开,并立即开始容错工作。 按照上面所说,那为什么HBase不直接让HMaster来负责RegionServer的监控呢?如果HMaster直接通过心跳机制等来管理RegionServer的状态,随着集群越来越大,HMaster的管理负担会越来越重,另外它自身也有挂掉的可能,因此数据还需要持久化。在这种情况下,ZooKeeper就成了理想的选择。 三,Region管理 对于大的HBase集群来说,Region的数量可能会多达十万级别,甚至更多,这样规模的Region状态管理交给ZooKeeper来做也是一个非常nice的选择。 四,分布式SplitWAL任务管理 当某台RegionServer服务器挂掉时,由于总有一部分新写入的数据还没有持久化到HFile中,因此在迁移该RegionServer的服务时,一个重要的工作就是从WAL中恢复这部分还在内存中的数据,而这部分工作最关键的一步就是SplitWAL,即HMaster需要遍历该RegionServer服务器的WAL,并按Region切分成小块移动到新的地址下,并进行日志的回放(replay)。 由于单个RegionServer的日志量相对庞大(可能有上千个Region,上GB的日志),而用户又往往希望系统能够快速完成日志的恢复工作。因此一个可行的方案是将这个处理WAL的任务分给多台RegionServer服务器来共同处理,而这就又需要一个持久化组件来辅助HMaster完成任务的分配。当前的做法是,HMaster会在ZooKeeper上创建一个SplitWAL节点(默认情况下,是/hbase/SplitWAL节点),将“哪个RegionServer处理哪个Region”这样的信息以列表的形式存放到该节点上,然后由各个RegionServer服务器自行到该节点上去领取任务并在任务执行成功或失败后再更新该节点的信息,以通知HMaster继续进行后面的步骤。ZooKeeper在这里担负起了分布式集群中相互通知和信息持久化的角色。 u200b 综上,就是ZooKeeper在HBase中的应用,在这里只列举出了一部分,相对说比较突出的作用,其实ZooKeeper在HBase中的应用远不止这些,比如HMaster还依赖ZooKeeper来完成Table的enable/disable状态记录,以及HBase中几乎所有的元数据存储都是放在ZooKeeper上的等等。

Zookeeper客户端Curator使用详解

[TOC] 维护多个博客比较麻烦,和博客园放弃维护,后续在个人博客持续更新: Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt(Zookeeper)以一句“Guava is to Java that Curator to Zookeeper”给Curator予高度评价。 引子和趣闻: Zookeeper名字的由来是比较有趣的,下面的片段摘抄自《从PAXOS到ZOOKEEPER分布式一致性原理与实践》一书: Zookeeper最早起源于雅虎的研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型的系统需要依赖一个类似的系统进行分布式协调,但是这些系统往往存在分布式单点问题。所以雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架。在立项初期,考虑到很多项目都是用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家Raghu Ramakrishnan开玩笑说:再这样下去,我们这儿就变成动物园了。此话一出,大家纷纷表示就叫动物园管理员吧——因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好用来进行分布式环境的协调——于是,Zookeeper的名字由此诞生了。 Curator无疑是Zookeeper客户端中的瑞士军刀,它译作"馆长"或者""管理者"",不知道是不是开发小组有意而为之,笔者猜测有可能这样命名的原因是说明Curator就是Zookeeper的馆长(脑洞有点大:Curator就是动物园的园长)。 Curator包含了几个包: curator-framework: 对zookeeper的底层api的一些封装 curator-client: 提供一些客户端的操作,例如重试策略等 curator-recipes: 封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等 Maven依赖(使用curator的版本:2.12.0,对应Zookeeper的版本为:3.4.x, 如果跨版本会有兼容性问题,很有可能导致节点操作失败 ): 一个例子如下: newClient静态工厂方法包含四个主要参数: 核心参数变为流式设置,一个列子如下: 为了实现不同的Zookeeper业务之间的隔离,需要为每个业务分配一个独立的命名空间( NameSpace ),即指定一个Zookeeper的根路径(官方术语: 为Zookeeper添加“Chroot”特性 )。例如(下面的例子)当客户端指定了独立命名空间为“/base”,那么该客户端对Zookeeper上的数据节点的操作都是基于该目录进行的。通过设置Chroot可以将客户端应用与Zookeeper服务端的一课子树相对应,在多个应用共用一个Zookeeper集群的场景下,这对于实现不同应用之间的相互隔离十分有意义。 当创建会话成功,得到client的实例然后可以直接调用其start( )方法: Zookeeper的节点创建模式: **创建一个节点,初始内容为空 ** 注意:如果没有设置节点属性,节点创建模式默认为持久化节点,内容默认为空 创建一个节点,附带初始化内容 创建一个节点,指定创建模式(临时节点),内容为空 创建一个节点,指定创建模式(临时节点),附带初始化内容 创建一个节点,指定创建模式(临时节点),附带初始化内容,并且自动递归创建父节点 这个creatingParentContainersIfNeeded()接口非常有用,因为一般情况开发人员在创建一个子节点必须判断它的父节点是否存在,如果不存在直接创建会抛出NoNodeException,使用creatingParentContainersIfNeeded()之后Curator能够自动递归创建所有所需的父节点。 删除一个节点 注意,此方法只能删除 叶子节点 ,否则会抛出异常。 删除一个节点,并且递归删除其所有的子节点 删除一个节点,强制指定版本进行删除 删除一个节点,强制保证删除 guaranteed()接口是一个保障措施,只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到删除节点成功。 注意: 上面的多个流式接口是可以自由组合的,例如: 读取一个节点的数据内容 注意,此方法返的返回值是byte[ ]; 读取一个节点的数据内容,同时获取到该节点的stat 更新一个节点的数据内容 注意:该接口会返回一个Stat实例 更新一个节点的数据内容,强制指定版本进行更新 注意:该方法返回一个Stat实例,用于检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath( )指定要操作的ZNode 注意:该方法的返回值为List<String>,获得ZNode的子节点Path列表。 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的父ZNode CuratorFramework的实例包含inTransaction( )接口方法,调用此方法开启一个ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交。一个例子如下: 上面提到的创建、删除、更新、读取等方法都是同步的,Curator提供异步接口,引入了 BackgroundCallback 接口用于处理异步接口调用之后服务端返回的结果信息。 BackgroundCallback 接口中一个重要的回调值为CuratorEvent,里面包含事件类型、响应吗和节点的详细信息。 CuratorEventType 响应码(#getResultCode()) 一个异步创建节点的例子如下: 注意:如果#inBackground()方法不指定executor,那么会默认使用Curator的EventThread去进行异步处理。 提醒:首先你必须添加curator-recipes依赖,下文仅仅对recipes一些特性的使用进行解释和举例,不打算进行源码级别的探讨 重要提醒:强烈推荐使用ConnectionStateListener监控连接的状态,当连接状态为LOST,curator-recipes下的所有Api将会失效或者过期,尽管后面所有的例子都没有使用到ConnectionStateListener。 Zookeeper原生支持通过注册Watcher来进行事件监听,但是开发者需要反复注册(Watcher只能单次注册单次使用)。Cache是Curator中对事件监听的包装,可以看作是对事件监听的本地缓存视图,能够自动为开发者处理反复注册监听。Curator提供了三种Watcher(Cache)来监听结点的变化。 Path Cache用来监控一个ZNode的子节点. 当一个子节点增加, 更新,删除时, Path Cache会改变它的状态, 会包含最新的子节点, 子节点的数据和状态,而状态的更变将通过PathChildrenCacheListener通知。 实际使用时会涉及到四个类: 通过下面的构造函数创建Path Cache: 想使用cache,必须调用它的 start 方法,使用完后调用 close 方法。 可以设置StartMode来实现启动的模式 ......to be continue

【Zookeeper系列】ZK命令基本使用

在了解 ZK 底层原理之前,咱们先简单了解常用的 ZK 命令,熟悉常用 ZK 命令有利于排查相关问题或了解基于 ZK 自研系统等场景。比如在开发的时候,发现有些Dubbo服务无法被调用,这有可能是服务没有注册到ZK或者断开连接;也有可能公司有自研的系统使用 ZK 作为配置中心,熟悉 ZK 命令就能知道是如何做到服务发现注册和配置动态更新。 话不多说,咱们先来了解常见的 ZK 命令吧! 实际上,ZK并没有help命令,你可以随意敲一两个字符也会这样显示,只不过基于使用Linux的习惯,姑且认为输入help能打印出ZK支持的命令吧。 ls 命令可以查看指定目录下的节点,使用可选的参数,能够更加详细的看到节点的相关信息 stat / 等价于 ls -s / 和 ls 命令相似的,加上-w参数添加监听 在ZK 3.5版本之后,新增了容器和TTL节点,分别是使用 -c 和 -t 创建。所以读者们要注意你当前使用的版本,如果版本低于3.5的,是没有容器和TTL节点。 特别说明一下容器节点和TTL节点的使用: 另外关于 TTL节点 的使用,需要特别注意的是,如果使用默认的配置文件启动zk,想创建有存活时间的节点,比如执行 create -t 10 /test 是会报 KeeperErrorCode = Unimplemented for XXX 这样的错误。解决办法是需要在ZK启动前,先在配置文件加上 extendedTypesEnabled=true 然后重启ZK(集群部署的话,所有ZK都需要修改配置文件再重启) 配置后重启,执行 create -t 10 /test 这样的命令就不会报错啦 例子:get -s /demo 例子:先查询节点版本号,模拟并发下修改同一节点 get -s /demo 可知当前 dataVersion = 1 客户端1:set -v 1 /demo demo-data1 客户端2:set -v 1 /demo demo-data2 客户端1比客户端2先执行,客户端2再执行的话,这时显示报错 -v version:和 set 命令相似,-v 参数用于判断当前操作的版本 例子:先创建一个delNode节点,然后删除 在前面使用create命令的时候,有一个acl参数是设置节点权限的,那么我们应该怎么设置? 举个例子: create /testAcl demo world:anyone:crwda 这行命令的意思是,创建 testAcl 这个节点,节点值为demo,其权限策略是所有人都可以执行 crwda 操作。那么接下来,咱们先看下 ACL 是什么东东? ACL 全称是 Access Control List ,也就是访问控制列表,ACL可以设置节点的操作权限。那么控制权限的粒度是怎样呢? 对于节点 ACL 权限控制,是通过使用: scheme:id:perm 来标识(也就是例子中的格式 -> world:anyone:crwda),其含义是: Scheme 有哪些授权策略? ID 授权对象有哪些? Permission 权限有哪些? 根据上面的参数可知,我们可以通过给所有人、特定的账号密码、特定的 ip 设置节点权限,这样能够更加方面地管理节点的访问。 值得注意的是,节点可以设置多种授权策略,但对于上下节点而言,权限的设置只对当前节点有效。换言之,权限不存在继承关系,即使节点被设置权限,但不会影响上下节点原来的权限! 上面执行了 create /testAcl demo world:anyone:crwda 命令给节点设置权限,那怎么看节点的权限咧? 很简单,执行 getAcl 节点路径 就可以查看对应节点的权限,比如 getAcl /testAcl,执行结果如下 除了在执行create命令创建节点的时候设置权限,还可以通过 setAcl 指定节点设置权限,比如我想指定/testAcl这个节点只可以通过特定 IP操作,并且限制执行权限为crdw,那么可以执行 setAcl /testAcl ip:127.0.0.1:crwd ,再次执行 getAcl /testAcl 结果如下: ZK 的命令还有部分没有演示,这并不阻碍咱们学习ZK的原理,先掌握常见的命令,如果日后有其他场景的话,再根据特定的命令学习就可以啦。 无意中发现有 Zookeeper的客户端,感兴趣的读者可以玩一下~ 友情提醒,可能在节点数量很多的时候,打开很慢,甚至卡死,所以这个可视化工具可以在自己本地玩玩,不建议应用在生产上哈。这也侧面的说明,学会 ZK 命令的重要性(认真脸.jpg) 解压缩后,进入ZooInspector的build目录,执行 java -jar zookeeper-dev-ZooInspector.jar 就可以启动工具。 连接上 ZK 后,就可以看到节点的信息和节点的ACL,具体玩法,可以再自己摸索哈~ 好了,以上是 ZK 常见命令的基本使用和可视化工具的基本使用。 参考资料: 《从Paxos到Zookeeper分布式一致性原理与实践》 如果觉得文章不错的话,麻烦点个赞哈,你的鼓励就是我的动力!对于文章有哪里不清楚或者有误的地方,欢迎在评论区留言~

《ZooKeeper:分布式过程协同技术详解分布式过程协同技术详解》pdf下载在线阅读,求百度网盘云资源

《ZooKeeper:分布式过程协同技术详解》(Flavio Junqueira)电子书网盘下载免费在线阅读资源链接:链接:https://pan.baidu.com/s/1HrACV0QnQUAmm9oK2Bw13w 提取码:y237书名:ZooKeeper:分布式过程协同技术详解作者:Flavio Junqueira译者:谢超豆瓣评分:7.0出版社:机械工业出版社出版年份:2016-1-1页数:208内容简介:本书分三部分,共10章。第一部分(第1~2章)阐述ApacheZooKeeper这类系统的设计目的和动机,并介绍分布式系统的一些必要背景知识。第1章介绍ZooKeeper可以做什么,以及其设计如何支撑这些任务。第2章介绍基本概念和基本组成模块,并通过命令行工具的具体操作介绍了ZooKeeper可以做什么。第二部分(第3~8章)阐述开发人员所需要掌握的ZooKeeper库调用方法和编程技巧。第3章介绍Java语言的API.第4章解释如何跟踪和处理ZooKeeper中的状态变更情况。第5章介绍如何在系统或网络故障时恢复应用。第6章介绍需要注意来避免故障的一些繁杂却很重要的场景。第7章介绍C语言版的API接口,也可以作为非Java语言实现的ZooKeeperAPI的基础,对非Java语言的开发人员非常有帮助。第8章介绍一款更高层级的封装的ZooKeeper接口。第三部分(第9~10章)主要介绍ZooKeeper内部原理及如何运行ZooKeeper.第9章介绍ZooKeeper的作者们在设计时所采用的方案。第10章介绍如何对ZooKeeper进行配置。作者简介:作者介绍Flavio Junqueira 是微软研究院在英国剑桥大学的研究人员之一。他拥有美国加州大学圣地亚哥分校计算机科学博士学位。他的研究范围涉及分布式系统的各个方面,包括分布式算法、并发性和可扩展性。他是Apache项目如Apache ZooKeeper(PMC主席和提交者)和Apache BookKeeper(提交者)的积极贡献者。他一有空就喜欢睡觉。Benjamin Reed 是一位负责Facebook中所有细节工作的软件工程师。他以前的职位包括雅虎研究院首席研究科学家(负责所有大的方向)和IBM Almaden Research的研究人员(负责所有事情,无论大小)。他拥有加州大学圣克鲁斯分校计算机科学博士学位。他从事的工作涉及分布式计算、大数据处理、分布式存储、系统管理和嵌入式框架等领域。他参加了各种开源项目,如Hadoop和Linux操作系统等。他帮助启动了由Apache软件基金会主办的项目如Pig、ZooKeeper和BookKeeper。

zookeeper怎么实现分布式锁

很多使用Zookeeper的情景是需要我们嵌入Zookeeper作为自己的分布式应用系统的一部分来提供分布式服务,此时我们需要通过程序的方式来启动Zookeeper。此时可以通过Zookeeper API的ZooKeeperServerMain类来启动Zookeeper服务。

如何使用zookeeper实现程序重启

记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有...

Zookeeper在哪些系统中使用,又是怎么用的

  ZooKeeper作为发现服务的问题   ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它 很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。   在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个 CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就 是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的 职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性 的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。   作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算 是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能 因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨 了!   而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的 故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的“法定人数”时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。   如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网 络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况 下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper 会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求 被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)   更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法 的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样 一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了 一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!   如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台 很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务 群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当 Service发现服务得不偿失。   做出正确的选择:Eureka的成功   我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作 服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开 始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平 台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!   首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切 换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务 注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广 的网络分割故障,并实现“0”宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新 的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。   但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些“濒死”的服务器;如果在Eureka中注册的服 务, 它的“心跳”变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时, 这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很”健康“的,只是因为网络分割故障把Eureka集群分割 成了独立的子网而不能互访而已。   幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入”自我保护模式“,同时保留那些“心跳死亡“的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对 于”死亡“的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出”自我保护模式“。所以Eureka的哲学是,同时保 留”好数据“与”坏数据“总比丢掉任何”好数据“要更好,所以这种模式在实践中非常有效。   最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接 口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过 Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。   Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制, 这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心 跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源 的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。   维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一 个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供 了Restful-API接口,方便第三方程序集成Eureka的功能。

【Zookeeper系列】基本介绍

在学习一样技术之前,咱们需要先想一下,为什么需要学这一门技术? 许多分布式系统都是基于ZK作为底层核心组件对外提供服务,比如Kafka中,将Broker注册到ZK中,此时ZK充当着多重角色,比如注册中心、选举等;再比如说,我公司目前很多项目都是Dubbo,都是需要基于ZK实现服务发现和注册。 另外,ZK内其实也有很多优秀的算法和设计思想,熟悉ZK源码,也可以提升自己的“内功”。 如何快速入门Zookeeper呢?最简单的方式就是直接看 Zookeeper官网 啦!建议读者多参考官方文档和博客内容一起食用,效果更佳噢~ Zookeeper的 Logo 看起来就像个“铲屎官”,服务动物园内的动物们。 “A Distributed Coordination Service for Distributed Applications”,这是摘取官方的解释,我们可以得知Zookeeper 是一个为 分布式框架 提供协调服务的东东。 举些例子,有哪些分布式框架使用Zookeeper: ZK的作用不止上面几个,其实还可以做到负载均衡、统一配置、分布式队列等,但使用场景相对少,企业级系统中,会使用其他更加专业的框架组件。 分布式锁、注册中心、Leader选举将会是ZK系列中,重点分享的内容,敬请期待哈~ 在ZK中,需要先了解一些专业名词的概念,但不会一下子都列出来,当之后遇到的时候,再重点分析... 在ZK集群中,会分为 Leader 、 Follower 和 Observer 角色。 Leader作为集群的大佬,承担写请求和部分读请求;Follower作为Leader的小弟,将会承担部分读请求,当接收到写请求的时候会转发给Leader,由Leader处理写请求;Observer就有点特殊,Observer节点不参与选举和消息过半机制,这个不清楚的读者可以暂时有个记忆就行,之后遇到会重点说明。 实际上,节点只分为持久节点和临时节点,但有些场景需要保证顺序,所以就会在持久或临时节点的基础上,添加序号(递增的方式),形成持久顺序节点和临时顺序节点。</br> 那么什么是持久节点,什么是临时节点呢?最直观的一个现象就是,每个ZK客户端连接ZK集群后,都会产生一个节点,如果ZK客户端下线后,节点还存在的就是持久节点,若ZK客户端下线后节点也随着消失,那么该节点就是临时节点。 在ZK客户端启动前,可以自定义监听回调函数,这个有什么作用呢?客户端启动后会将监听事件发送给Zookeeper集群,Zookeeper集群中有一个用于记录监听事件的列表,当客户端监听的目录节点发生变化,如节点数据变更、节点增删等,就会通过ZK集群的监听列表,找到对应的客户端回调监听函数,那么客户端这边就可以根据业务场景,做出相应的动作。 ZAB协议的全称是:ZooKeeper Atomic Broadcast。ZAB是Zookeeper保证数据一致性的核心算法。借鉴了Paxos算法的思想,特地为Zookeeper设计的支持崩溃恢复的原子广播协议。其包括两种基本模式: 消息广播 和 崩溃恢复 消息广播指的是,集群中只有一个Leader处理写请求,并将写请求的事件广播给所有Follower,且能够保证数据不丢失。(也就是说,消息的写入是原子性的,因为只能有leader写入) 崩溃恢复指的是,当ZK集群刚启动还没选举出Leader或Leader因故障、重启、网络等原因的时候,ZAB协议会进入崩溃恢复模式,其目的就是为了选举新的Leader,且保证新Leader的数据是最新的,这样就能够避免因为Leader故障而导致单点丢失消息的情况,至于ZAB具体的原理,各位可以先看下以下参考文章,后续有机会我再专门写一篇关于 ZAB 协议的文章~ ZAB 协议参考文章 ZK内的数据模型结构和Unix文件系统非常相似,是一个有层级关系的树形数据结构。在ZK内,树形的数据结构使用称为ZNode节点保存数据,ZNode是ZK中数据结构最小单元,不仅能够保存数据,还能挂载子节点,形成一个有层次关系的树。 值得注意的是,ZNode的创建是纯内存操作的,所以速度很快,然后在ZK内部会定期将ZNode的数据持久化到磁盘上。 众所周知,在实际的企业应用,面对高并发的场景下,肯定是不能单节点部署,而是通过集群部署保证 高并发、高性能、高可用 (简称三高)。 高性能 :由于ZNode节点是纯内存操作,只要ZK部署在高配置的服务器中,三台ZK服务器抗住每秒几万的请求都是没问题的。 高可用 :只要部署奇数的服务器集群(比如3台、5台、11台机器),只要不超过一半的服务器宕机,都能保证ZK集群可用。 高并发 :因为ZNode是纯内存操作,所以在写数据的时候,速度是很快;而ZK集群中Leader和Follower节点都能处理读请求,所以ZK集群高并发能力是很强的。 基于ZAB协议,写请求统一由Leader服务器处理,然后由Leader将写数据的请求广播给其他Follower。 但会不会由于种种原因,如网络波动、Leader脑裂、Follower宕机等,导致消息不一致? 实际上,在ZK中采用2PC两阶段提交的思想,结合ZAB消息广播保证数据一致性。值得注意的是,Zookeeper只能保证最终一致性,并不能保证强一致性 那么具体是怎么保证数据最终一致性的呢?感兴趣的读者可以看下我另外一篇拙作【TODO...】 参考资料: 《从Paxos到Zookeeper分布式一致性原理与实践》 如果觉得文章不错的话,麻烦点个赞哈,你的鼓励就是我的动力!对于文章有哪里不清楚或者有误的地方,欢迎在评论区留言~

为什么要使用zookeeper?有什么功能吗?

2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑

zookeeper服务注册和发现原理

zk的好处就是,服务注册和发现都是事实的。 微服务会对zk进行监听,如果服务有变动,则会实时更新注册信息。 集群建议部署单数个,集群可用服务器超过一半,zk才能对外提供服务。 最少部署3台。 集群模式下, 会有一个leader,和多个follower 。 leader会将服务注册的表同步到各个follower。 leader宕机后, follower会进行选举, 选举的过程中, zk是不对外提供服务的。 这时候,就保证不了可用性(A)。 这样的机制就可以保证一致性。 选举完成后, zk再对外提供服务。

Zookeeper深入原理(3) - Zab协议

Zab协议全称是 Zookeeper Atomic BroadCast (Zookeeper 原子广播),Zookeeper是通过Zab协议来保证分布式事务的一致性。 1.Zab协议是zookeeper专门设计的一种 支持崩溃恢复 的 原子广播协议, 是Zookeeper保证数据一致性的核心算法。 2.在Zookeeper当中依赖Zab协议来保证数据的一致性,基于这个协议,zookeeper实现了一种主备模型,(Leader+Follower)的架构在保证集群中各个副本之间数据的一致性。 Leader负责处理写事务请求,然后Leader将数据同步到Follower节点上。 3.zookeeper客户端会随机连接到集群中的一个节点上,如果是读请求,就会从当前节点进行读取数据,如果是写的请求,就会将事务请求提交到Leader节点,leader节点接收到事务提交,就会广播该事务,如果超过一半节点写入成功,那么该事务就会被提交。1.Zab协议需要确保那些已经在leader服务器上提交的事务最终被所有服务器提交。 2.Zab协议需要确保那些在leader服务器上被提出而没有被提交的事务。 1.使用主进程(leader)来接受客户端并处理客户端的事务请求,并采用Zab的原子广播协议,将服务器数据变更的状态以事务提议的形式广播到所有的follower副本上去。 2.当主进程出现异常,整个zk集群依然能够正常运行。 Zab协议每个leader需要经过三个阶段:发现、同步、广播 发现 :要求Zookeeper集群必须选取出一个leader进程,同时leader需要维护一个follower可用客户端列表,将来客户端可以和这些follower进行通信。 同步 :Leader要将本身的数据与follower进行同步,实现多副本存储,也体现了CAP中的高可用和分区容错。follower将队列中未处理完的消息消费完成后,写入到本地日志中。 广播 :leader接受客户端提出的事务请求,将新的事务请求广播给follower节点。 Zab协议核心:定义了事务请求的处理方式。 1.所有的事务请求必须由一个全局唯一的服务器来协调处理(Leader 服务器),其余的服务器是follower服务器。 2.leader服务器负责将客户端提出的事务请求,转换成一个事务proposal,并将事务proposal分发给集群中follower服务器,也就是向所有follower节点发送数据广播请求。 3.分发之后leader服务器需要等待follower服务器的反馈,在Zab协议中,只要超过半数的follower服务器进行确认了,那么leader就会再次向所有的follower发送commit消息,要求将上一个事务进行提交。 Zab协议包括两种模式: 崩溃恢复 和 消息广播 协议过程 当整个集群启动过程中,或者leader服务器出现宕机或者网络终端等异常时,Zab协议就会进入崩溃恢复模式,选举出新的leader。 当选举出新的leader之后,同时集群中有过半的服务器与该leader服务器完成了状态同步(数据同步),Zab协议就会退出崩溃恢复模型,进入消息广播模式。 如果新增一台服务器加入集群中,当前集群中已经选举出leader,那么加入进来的服务器自动进入恢复模式,找到leader服务器进行状态同步,完成同步后,与其他follower一起参与到广播流程中。 Zookeeper集群中,数据副本的传递策略采用的是消息广播模式。Zab协议中Leader等待follower 的ACK反馈消息,当到达半数以上follower成功反馈即可,不需要等所有的follower全部反馈。leader服务器出现宕机和网络原因等导致leader与过半的follower服务器不能联系,就会自动进入崩溃恢复模式。 在Zab协议中,为了保证程序的正常运行,整个恢复过程结束后需要重新选出一个leader服务器,因此Zab协议需要一个高效且可靠的算法,来保证快速选举出leader。 Leader算法不仅让leader自己知道自己已经被选取为leader,还需要让集群中的所有服务器快速的感知到选举出的新leader服务器。 崩溃恢复包括两个部分: Leader选举 和 数据恢复 Zab 协议如何保证数据一致性假设两种异常情况: 1、一个事务在 Leader 上提交了,并且过半的 Folower 都响应 Ack 了,但是 Leader 在 Commit 消息发出之前挂了。 2、假设一个事务在 Leader 提出之后,Leader 挂了。 要确保如果发生上述两种情况,数据还能保持一致性,那么 Zab 协议选举算法必须满足以下要求: Zab 协议崩溃恢复要求满足以下两个要求 : 1) 确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交 。 2) 确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal 。 根据上述要求 Zab协议需要保证选举出来的Leader需要满足以下条件: 1) 新选举出来的 Leader 不能包含未提交的 Proposal 。 即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点。 2) 新选举的 Leader 节点中含有最大的 zxid 。 这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。 Zab 如何数据同步 1)完成 Leader 选举后(新的 Leader 具有最高的zxid),在正式开始工作之前(接收事务请求,然后提出新的 Proposal),Leader 服务器会首先确认事务日志中的所有的 Proposal 是否已经被集群中过半的服务器 Commit。 2)Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务的 Proposal ,并且能将所有已经提交的事务 Proposal 应用到内存数据中。等到 Follower 将所有尚未同步的事务 Proposal 都从 Leader 服务器上同步过啦并且应用到内存数据中以后,Leader 才会把该 Follower 加入到真正可用的 Follower 列表中。 Zab 数据同步过程中,如何处理需要丢弃的 Proposal 在 Zab 的事务编号 zxid 设计中,zxid是一个64位的数字。 其中低32位可以看成一个简单的单增计数器,针对客户端每一个事务请求,Leader 在产生新的 Proposal 事务时,都会对该计数器加1。而高32位则代表了 Leader 周期的 epoch 编号。 epoch 编号可以理解为当前集群所处的年代,或者周期。每次Leader变更之后都会在 epoch 的基础上加1,这样旧的 Leader 崩溃恢复之后,其他Follower 也不会听它的了,因为 Follower 只服从epoch最高的 Leader 命令。 每当选举产生一个新的 Leader ,就会从这个 Leader 服务器上取出本地事务日志充最大编号 Proposal 的 zxid,并从 zxid 中解析得到对应的 epoch 编号,然后再对其加1,之后该编号就作为新的 epoch 值,并将低32位数字归零,由0开始重新生成zxid。 Zab 协议通过 epoch 编号来区分 Leader 变化周期 ,能够有效避免不同的 Leader 错误的使用了相同的 zxid 编号提出了不一样的 Proposal 的异常情况。 基于以上策略 当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal 的服务器启动时,当这台机器加入集群中,以 Follower 角色连上 Leader 服务器后,Leader 服务器会根据自己服务器上最后提交的 Proposal 来和 Follower 服务器的 Proposal 进行比对,比对的结果肯定是 Leader 要求 Follower 进行一个回退操作,回退到一个确实已经被集群中过半机器 Commit 的最新 Proposal 。 本文根据https://www.jianshu.com/p/2bceacd60b8a进行编写。

Zookeeper的功能以及工作原理_功能原理

1.ZooKeeper是什么? ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户 2.ZooKeeper提供了什么? 1)文件系统 2)通知机制 3.Zookeeper文件系统 每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。 有四种类型的znode: 1、PERSISTENT-持久化目录节点 客户端与zookeeper断开连接后,该节点依旧存在 2、PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点 客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 3、EPHEMERAL-临时目录节点 客户端与zookeeper断开连接后,该节点被删除 4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点 客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号4.Zookeeper通知机制 客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。 5.Zookeeper做了什么? 1.命名服务 2.配置管理 3.集群管理 4.分布式锁 5.队列管理 6.Zookeeper命名服务 在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。 7.Zookeeper的配置管理 程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好8.Zookeeper集群管理 所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。 新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。9.Zookeeper分布式锁 有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。 对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。 对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。10.Zookeeper队列管理 两种类型的队列: 1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。 2、队列按照 FIFO 方式进行入队和出队操作。 第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。 第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。 11.分布式与数据复制 Zookeeper作为一个集群提供一致的数据服务,自然,它要在所有机器间做数据复制。数据复制的好处: 1、容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作;2、提高系统的扩展能力 :把负载分布到多个节点上,或者增加节点来提高系统的负载能力;3、提高性能:让客户端本地访问就近的节点,提高用户访问速度。 从客户端读写访问的透明度来看,数据复制集群系统分下面两种: 1、写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,可以读取任何一个节点。这种情况下客户端需要对读与写进行区别,俗称读写分离;2、写任意(Write Any):对数据的修改可提交给任意的节点,跟读一样。这种情况下,客户端对集群节点的角色与变化透明。 对zookeeper来说,它采用的方式是写任意。通过增加机器,它的读吞吐能力和响应能力扩展性非常好,而写,随着机器的增多吞吐能力肯定下降(这也是它建立observer的原因),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,还是立即复制快速响应。 12.Zookeeper角色描述13.Zookeeper与客户端14.Zookeeper设计目的 1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。 2.可靠性:具有简单、健壮、良好的性能,如果消息被到一台服务器接受,那么它将被所有的服务器接受。 3.实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。 4.等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。 5.原子性:更新只能成功或者失败,没有中间状态。 6.顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布; 偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。 15.Zookeeper工作原理 Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。 为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。 16.Zookeeper 下 Server工作状态 每个Server在工作过程中有三种状态: LOOKING:当前Server不知道leader是谁,正在搜寻 LEADING:当前Server即为选举出来的leader FOLLOWING:leader已经选举出来,当前Server与之同步 17.Zookeeper选主流程(basic paxos) 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。 1.选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;2.选举线程首先向所有Server发起一次询问(包括自己);3.选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;4.收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;5.线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。 通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1. 每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图所示:18.Zookeeper选主流程(fast paxos) fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。19.Zookeeper同步流程 选完Leader以后,zk就进入状态同步过程。 1. Leader等待server连接;2 .Follower连接leader,将最大的zxid发送给leader;3 .Leader根据follower的zxid确定同步点;4 .完成同步后通知follower 已经成为uptodate状态;5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。20.Zookeeper工作流程-Leader 1 .恢复数据;2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;3 .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。 PING 消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。21.Zookeeper工作流程-Follower Follower主要有四个功能: 1.向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);2.接收Leader消息并进行处理;3.接收Client的请求,如果为写请求,发送给Leader进行投票;4.返回Client结果。 Follower的消息循环处理如下几种来自Leader的消息: 1 .PING消息: 心跳消息;2 .PROPOSAL消息:Leader发起的提案,要求Follower投票;3 .COMMIT消息:服务器端最新一次提案的信息;4 .UPTODATE消息:表明同步完成;5 .REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;6 .SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。

Zookeeper算法原理

zk算法的演进过程 1.Write-all-read-one 先讨论最简单的副本控制规则 Write-all-read-one(简称 WARO)是一种最简单的副本控制规则,顾名思义即在更新时写所有 的副本, 只有在所有的副本上更新成功,才认为更新成功, 从而保证所有的副本一致,这样在读取数据时可以读任一副本上的数据。 先做这样的约定 :更新操作(write)是一系列顺序的过程,通过其他机制 确定更新操作的顺序(例如 primary-secondary 架构中由 primary 决定顺序),每个更新操作记为 wi, i 为更新操作单调递增的序号,每个 wi执行成功后副本数据都发生变化,称为不同的数据版本,记作 vi。假设每个副本都保存了历史上所有版本的数据。 假设有一种 magic 的机制,当某次更新操作 wi一旦在所有 N 个副本上都成功,此时 全局都能知 道这个信息(现实情况是比较难的) ,此后读取操作将指定读取数据版本为 vi的数据,称在所有 N 个副本上都成功的更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。 在 WARO 中,如果某次更新操作 wi在某个副本上失败,此时该副本的最新的数据只有 vi-1,由于不满足在所有 N 个副本上都成功, 则 wi 不是一个“成功提交的更新操作”,此时,虽然其他 N-1 个副本上最新的数据是 vi,但 vi不是一个“成功提交的数据”,最新的成功提交的数据只是 vi-1 。 在工程实践中,这种 magic 的机制往往较难实现或效率较低。通常实现这种 magic 机制的方式就是 将版本号信息存放到某个或某组元数据服务器上 。假如更新操作非常频繁,那么记录更新成功的版本号 vi的操作将成为一个关键操作,容易成为瓶颈。另外,为了实现强一致性,在读取数据的前必须首先读取元数据中的版本号,在大压力下也容易因为元数据服务器的性能造成瓶颈。 缺点: WARO 的可用性。 由于更新操作需要在所有的 N 个副本上都成功,更新操作才能成功,所以一旦有一个副本异常,更新操作失败,更新服务不可用。对于更新服务,虽然有 N 个副本, 但系统无法容忍任何一个副本异常。另一方面, N 个副本中只要有一个副本正常,系统就可以提供读服务。对于读服务而言,当有 N 个副本时,系统可以容忍 N-1 个副本异常。 从上述分析可以发现 WARO 读服务的可用性较高,但更新服务的可用性不高 ,甚至虽然使用了 副本,但更新服务的可用性等效于没有副本. 2.Quorum 机制 将 WARO 的条件进行松弛,从而使得可以在 读写服务可用性之间做折中 ,得出 Quorum 机制. 在 Quorum 机制下,当某次更新操作 wi一旦在所有 N 个副本中的 W 个副本上都成功,则就称 该更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。令 R>N-W,由于更新 操作 wi仅在 W 个副本上成功,所以在读取数据时,最多需要读取 R 个副本则一定能读到 wi 更新后的数据 vi 。如果某次更新 wi在 W 个副本上成功,由于 W+R>N,任意 R 个副本组成的集合一定与成功的 W 个副本组成的集合有交集,所以读取 R 个副本一定能读到 wi更新后的数据 vi。 例一: 某系统有 5 个副本, W=3, R=3,最初 5 个副本的数据一致,都是 v1, 某次更新操作 w2 在前 3 副本上成功,副本情况变成(v2 v2 v2 v1 v1)。此时, 任意 3 个副本组成的集合中一定包括v2。 例二: N=5, W=2, R=3 时,若 4 个副本异常,更新操作始终无法完成。若 3 个副本异常时, 剩下的两个副本虽然可以提供更新服务,但对于读取者而言,在缺乏某些 magic 机制的,即如果读取者不知道当前最新已成功提交的版本是什么的时候,仅仅读取 2 个副本并不能保证一定可以读到最新的已提交的数据。 得出一个简单的结论: 仅 仅依赖 quorum 机制 是无法保证强一致性的。因为仅有 quorum 机制时 无法确定最新已成功提交的版本号 ,除非将最新已提交的版本号作为元数据由特定的元数据服务器或元数据集群管理,否则很难确定最新成功提交的版本号。 Quorum 机制只需成功更新 N 个副本中的 W 个,在读取 R 个副本时,一定可以读到 最新的成功 提交的数据。 但由于有不成功的更新情况存在,仅仅读取 R 个副本却不一定能确定哪个版本的数据是最新的已提交的数据(简而言之,就是说我读到的结果中包含了v1,v2我可以肯定最新的数据一定是他们两种的一个,但我却没办法确定是哪一个的) 例三: 在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v2 v1 v1)。注意,这里继续假设有 v2 的副本也有 v1,上述列出的只是最大版本号。此时,最新的成功提交的副本应该 是 v2,因为从全局看 v2已经成功更新了 3 个副本。 读取任何 3 个副本,一定能读到 v2。 但仅读 3 个副本时,有可能读到(v2 v1 v1)。 此时,由于 v2蕴含 v1, 可知 v1是一个成功提交的 版本, 但却不能判定 v2一定是一个成功提交的版本。 这是因为 ,假设**副本最大版本号为(v2 v1 v1 v1 v1), 当读取 3 个副本时也可能读到v2 v1 v1) ,此时 v2是一个未成功提交的版本。 所 以在本例中,仅仅读到(v2 v1 v1)时,可以肯定的是最新的成功提交的数据要么是 v1要么是 v2,却没办法确定究竟是哪一个。 对于一个强一致性系统,应该始终读取返回最新的成功提交的数据,在 quorum 机制下,要达 到这一目的需要对读取条件做进一步加强。 1. 限制提交的 更新操作必须严格递增 ,即只有在前一个更新操作成功提交后才可以提交后一 个更新操作,从而成功提交的数据版本号必须是连续增加的。 2. 读取 R 个副本,对于 R 个副本中版本号最高的数据, 2.1 若已存在 W 个,则该数据为最新的成功提交的数据 2.2 若存在个数据少于 W 个, 假设为 X 个, 则继续读取其他副本,直若成功读取到 W 个 该版本的副本,则该数据为最新的成功提交的数据;如果在所有副本中该数据的个数肯定不满 足 W 个,则 R 中版本号第二大的为最新的成功提交的副本。 例四: 依旧接例三,在读取到(v2 v1 v1)时,继续读取剩余的副本,若读到剩余两个副本为(v2 v2)则 v2 是最新的已提交的副本;若读到剩余的两个副本为(v2 v1)或(v1 v1)则 v1是最新成功提交的版本;若读取后续两个副本有任一超时或失败,则无法判断哪个版本是最新的成功提交的版本。 可以看出,在单纯使用 Quorum 机制时,若要确定最新的成功提交的版本,最多需要读取 R+ (W-R-1)=N 个副本,当出现任一副本异常时,读最新的成功提交的版本这一功能都有可能不可用。 实际工程中,应该尽量通过其他技术手段,回避通过 Quorum 机制读取最新的成功提交的版本。例如,当 quorum 机制与 primary-secondary 控制协议结合使用时,可以通过读取 primary 的方式读取到最新的已提交的数据。 在 primary-secondary 协议中,当 primary 异常时,需要选择出一个新的 primary,之后 secondary副本与 primary 同步数据。 通常情况下,选择新的 primary 的工作是由某一中心节点完成的,在引入quorum 机制后,常用的 primary 选择方式与读取数据的方式类似,即中心节点读取 R 个副本,选择R 个副本中版本号最高的副本作为新的 primary。新 primary 与至少 W 个副本完成数据同步后作为新的 primary 提供读写服务。首先, R 个副本中版本号最高的副本一定蕴含了最新的成功提交的数据。再者,虽然不能确定最高版本号的数是一个成功提交的数据,但新的 primary 在随后与 secondary 同步数据,使得该版本的副本个数达到 W,从而使得该版本的数据成为成功提交的数据。 以上这段其实就是zk的原理 简述下就是先用Quorum 机制选择出primary(版本号最高的,版本号是严格递增的),然后再用primary-secondary来同步数据,(我一定可以读取到版本号最高的,虽然此时有可能是已提交也有可能为未提交),但我同步之后可以保证该版本号的副本数达到w,从而使得该版本号的数据成为成功提交的数据. 例五: 在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v1 v1 v1),此时 v1是 系统的最新的成功提交的数据, v2 是一个处于中间状态的未成功提交的数据。假设此刻原 primary副本异常,中心节点进行 primary 切换工作。 这类“中间态”数据究竟作为“脏数据”被删除,还是作为新的数据被同步后成为生效的数据,完全取决于这个数据能否参与新 primary 的选举。此时有以下两种情况 情况一: 若中心节点与其中 3 个副本通信成功,读取到的版本号为(v1 v1 v1),则任 选一个副本作为 primary,新 primary以 v1 作为最新的成功提交的版本并与其他副本同步,当与第 1、第 2 个副本同步数据时,由于第 1、第 2 个副本版本号大于 primary,属于脏数据,删除脏数据,然后重新同步。 情况二: 若中心节点与其他 3 个副本通信成功,读取到的版本号为(v2 v1 v1), 则选取版本号为v2 的副本作为新的 primary,之后,一旦新 primary 与其他 2 个副本完成数据同步,则符合 v2 的副本个数达到 W 个,成为最新的成功提交的副本,新 primary 可以提供正常的读写服务。 一致性算法在实现状态机这种应用时,有以下常见的问题: 1.1 一般的leader选举过程 选举的轮次 1.2 leader选举的效率 1.3 加入一个已经完成选举的集群 怎么发现已完成选举的leader? 1.4 leader选举的触发 3.3.2 异常过程的顺序 follower挂掉又连接 raft与zk的对比 1 leader选举 为什么要进行leader选举? 在实现一致性的方案,可以像base-paxos那样不需要leader选举,这种方案达成一件事情的一致性还好,面对多件事情的一致性就比较复杂了,所以通过选举出一个leader来简化实现的复杂性。 1.1 一般的leader选举过程 更多的有2个要素: 1.1.1 选举投票可能会多次轮番上演,为了区分,所以需要定义你的投票是属于哪个轮次的。 他们都需要在某个轮次内达成过半投票来结束选举过程 1.1.2 投票PK的过程,更多的是日志越新越多者获胜 在选举leader的时候,通常都希望 选举出来的leader至少包含之前全部已提交的日志 自然想到包含的日志越新越大那就越好。 通常都是比较最后一个日志记录,如何来定义最后一个日志记录? 有2种选择,一种就是所有日志中的最后一个日志,另一种就是所有已提交中的最后一个日志。目前Raft和ZooKeeper都是采用前一种方式。日志的越新越大表示:轮次新的优先,然后才是同一轮次下日志记录大的优先 ZooKeeper:peerEpoch大的优先,然后zxid大的优先 但是有一个问题就是:通过上述的日志越新越大的比较方式能达到我们的上述希望吗? 特殊情况下是不能的,这个特殊情况详细可参见我们上面描述的 这个案例就是这种比较方式会 选举出来的leader可能并不包含已经提交的日志(和我们例三分析的一样) ,而Raft的做法则是对于日志的提交多加一个限制条件,即不能直接提交之前term的已过半的entry,即把这一部分的日志限制成未提交的日志,从而来实现上述的希望。 ZooKeeper呢?会不会出现这种情况?又是如何处理的? ZooKeeper是不会出现这种情况的,因为ZooKeeper在每次leader 选举完成之后,都会进行数据之间的同步纠正,所以每一个轮次,大家都日志内容都是统一的 而Raft在leader选举完成之后没有这个同步过程,而是靠之后的AppendEntries RPC请求的一致性检查来实现纠正过程,则就会出现上述案例中隔了几个轮次还不统一的现象 1.2 leader选举的效率 Raft中的每个server在某个term轮次内只能投一次票,哪个candidate先请求投票谁就可能先获得投票,这样就可能造成split vote,即各个candidate都没有收到过半的投票,Raft通过candidate设置不同的超时时间,来快速解决这个问题,使得先超时的candidate(在其他人还未超时时)优先请求来获得过半投票** ZooKeeper中的每个server,在某个electionEpoch轮次内,可以投多次票,只要遇到更大的票就更新,然后分发新的投票给所有人。这种情况下不存在split vote现象,同时有利于选出含有更新更多的日志的server,但是选举时间理论上相对Raft要花费的多。 1.3 加入一个已经完成选举的集群 1.3.1 怎么发现已完成选举的leader? 一个server启动后(该server本来就属于该集群的成员配置之一,所以这里不是新加机器),如何加入一个已经选举完成的集群 1.3.2 加入过程是否阻塞整个请求? 这个其实还要 看对日志的设计是否是连续的 如果 是连续的,则leader中只需要保存每个follower上一次的同步位置,这样在同步的时候就会自动将之前欠缺的数据补上,不会阻塞整个请求过程(****所以为什么redis的选举算法是raft?毕竟redis单线程****) 如果 不是连续的,则在确认follower和leader当前数据的差异的时候,是需要获取leader当前数据的读锁,禁止这个期间对数据的修改。差异确定完成之后,释放读锁,允许leader数据被修改,每一个修改记录都要被保存起来,最后一一应用到新加入的follower中。 1.4 leader选举的触发 触发一般有如下2个时机 2 上一轮次的leader 2.1 上一轮次的leader的残留的数据怎么处理? 首先看下上一轮次的leader在挂或者失去leader位置之前,会有哪些数据? 一个日志是否被过半复制,是否被提交,这些信息是由leader才能知晓的,那么下一个leader该如何来判定这些日志呢? 下面分别来看看Raft和ZooKeeper的处理策略: Raft的保守策略更多是因为Raft在leader选举完成之后,没有同步更新过程来保持和leader一致(在可以对外处理请求之前的这一同步过程)。而ZooKeeper是有该过程的 2.2 怎么阻止上一轮次的leader假死的问题 这其实就和实现有密切的关系了。 3 请求处理流程 3.1 请求处理的一般流程 这个过程对比Raft和ZooKeeper基本上是一致的,大致过程都是过半复制 先来看下Raft: 再来看看ZooKeeper: 备注:数据同步过程就有点类似于两阶段提交了。 假装是图2 3.2 日志的连续性问题 在需要保证顺序性的前提下,在利用一致性算法实现状态机的时候,到底是实现连续性日志好呢还是实现非连续性日志好呢? 还有在复制和提交的时候: 其他有待后续补充 3.3 如何保证顺序 具体顺序是什么? 这个就是先到达leader的请求,先被应用到状态机。这就需要看正常运行过程、异常出现过程都是怎么来保证顺序的 3.3.1 正常同步过程的顺序 3.3.2 异常过程的顺序保证 如follower挂掉又重启的过程: ZooKeeper:重启之后,需要和当前leader数据之间进行差异的确定,同时期间又有新的请求到来,所以需要暂时获取leader数据的读锁,禁止此期间的数据更改,先将差异的数据先放入队列,差异确定完毕之后,还需要将leader中已提交的议案和未提交的议案也全部放入队列,即ZooKeeper的如下2个集合数据 ConcurrentMap<Long, Proposal> outstandingProposals ConcurrentLinkedQueue<Proposal> toBeApplied 如果是leader挂了之后,重新选举出leader,会不会有乱序的问题? 3.4 请求处理流程的异常 一旦leader发给follower的数据出现超时等异常 4 分区的应对 目前ZooKeeper和Raft都是过半即可,所以对于分区是容忍的。如5台机器,分区发生后分成2部分,一部分3台,另一部分2台,这2部分之间无法相互通信 其中,含有3台的那部分,仍然可以凑成一个过半,仍然可以对外提供服务,但是它不允许有server再挂了,一旦再挂一台则就全部不可用了。 含有2台的那部分,则无法提供服务,即只要连接的是这2台机器,都无法执行相关请求。 所以ZooKeeper和Raft在一旦分区发生的情况下是是牺牲了高可用来保证一致性,即CAP理论中的CP。但是在没有分区发生的情况下既能保证高可用又能保证一致性,所以更想说的是所谓的CAP二者取其一,并不是说该系统一直保持CA或者CP或者AP,而是一个会变化的过程。在没有分区出现的情况下,既可以保证C又可以保证A,在分区出现的情况下,那就需要从C和A中选择一样。ZooKeeper和Raft则都是选择了C。

Zookeeper深入原理

Zookeeper 的视图结构是一个树形结构,树上的每个节点称之为数据节点(即 ZNode),每个ZNode 上都可以保存数据,同时还可以挂载子节点。并且Zookeeper的根节点为 "/"。 在 Zookeeper 中,每个数据节点都是有生命周期的,其生命周期的长短取决于数据节点的节点类型。在 Zookeeper 中有如下几类节点: 每个数据节点中除了存储了数据内容之外,还存储了数据节点本身的一些状态信息(State)。 在Zookeeper 中,事务是指能够改变 Zookeeper 服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。对于每一个事务请求,Zookeeper 都会为其分配一个全局唯一的事务ID,用 ZXID 来表示,通常是一个 64 位的数字。每一个 ZXID 对应一次更新操作,从这些 ZXID 中可以间接地识别出 Zookeeper 处理这些更新操作请求的全局顺序。 ZXID 是一个 64 位的数字,其中低 32 位可以看作是一个简单的单调递增的计数器,针对客户端的每一个事务请求,Leader 服务器在产生一个新的事务 Proposal 的时候,都会对该计数器进行加 1 操作;而高 32 位则代表了 Leader 周期 epoch 的编号,每当选举产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出其本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值,然后再对其进行加 1 操作,之后就会以此编号作为新的 epoch,并将低 32 位置 0 来开始生成新的 ZXID。 Zookeeper 中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息(在上面的状态信息中已经介绍了三种版本信息代表的意思),对数据节点的任何更新操作都会引起版本号的变化。其中我们以 dataVersion 为例来说明。在一个数据节点被创建完毕之后,节点的dataVersion 值是 0,表示的含义是 ”当前节点自从创建之后,被更新过 0 次“。如果现在对该节点的数据内容进行更新操作,那么随后,dataVersion 的值就会变成 1。即表示的是对数据节点的数据内容的变更次数。 版本的作用是用来实现乐观锁机制中的 “写入校验” 的。例如,当要修改数据节点的数据内容时,带上版本号,如果数据节点的版本号与传入的版本号相等,就进行修改,否则修改失败。 Zookeeper 提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。在 Zookeeper 中,引入了 Watcher 机制来实现这种分布式的通知功能。Zookeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。 从上图可以看出 Zookeeper 的 Watcher 机制主要包括客户端线程、客户端WatchMananger 和 Zookeeper 服务器三部分。在具体工作流程上,简单地讲,客户端在向 Zookeeper 服务器注册 Watcher 的同时,会将 Watcher 对象存储在客户端的 WatchMananger 中。当 Zookeeper 服务器端触发 Watcher 事件后,会向客户端发送通知,客户端线程从 WatchManager 中取出对应的 Watcher 对象来执行回调逻辑。 Watcher是一个接口,任何实现了Watcher接口的类就是一个新的Watcher。Watcher内部包含了两个枚举类:KeeperState、EventType 注 :客户端接收到的相关事件通知中只包含状态及类型等信息,不包括节点变化前后的具体内容,变化前的数据需业务自身存储,变化后的数据需调用get等方法重新获取; 上面讲到zookeeper客户端连接的状态和zookeeper对znode节点监听的事件类型,下面我们来讲解如何建立zookeeper的watcher监听。在zookeeper中采用zk.getChildren(path, watch)、zk.exists(path, watch)、zk.getData(path, watcher, stat)这样的方式为某个znode注册监听。 下表以node-x节点为例,说明调用的注册方法和可监听事件间的关系: Zookeeper 中提供了一套完善的 ACL(Access Control List)权限控制机制来保障数据的安全。 ACL 由三部分组成,分别是:权限模式(Scheme)、授权对象(ID)和权限(Permission),通常使用“scheme: u200bid:permission”来标识一个有效的ACL 信息。下面分别介绍: 1.7.4、ACL 超级管理员 zookeeper的权限管理模式有一种叫做super,该模式提供一个超管可以方便的访问任何权限的节点 假设这个超管是:super:admin,需要先为超管生成密码的密文 那么打开zookeeper目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行: 这就是脚本中启动zookeeper的命令,默认只有以上两个配置项,我们需要加一个超管的配置项 那么修改以后这条完整命令变成了 之后启动zookeeper,输入如下命令添加权限 在服务器集群初始化阶段,我们以 3 台机器组成的服务器集群为例,当有一台服务器server1 启动的时候,它是无法进行 Leader 选举的,当第二台机器 server2 也启动时,此时这两台服务器已经能够进行互相通信,每台机器都试图找到一个 Leader,于是便进入了 Leader 选举流程。 在zookeeper运行期间,leader与非leader服务器各司其职,即便当有非leader服务器宕机或新加入,此时也不会影响leader,但是一旦leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的Leader选举过程基本一致。 假设正在运行的有server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了,此时便开始Leader选举。选举过程如下: observer角色特点: 为了使用observer角色,在任何想变成observer角色的配置文件中加入如下配置: 并在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:

关于super junior 和kun-tun的资料

日本Johnnys偶像团体KAT-TUN于2001年3月结成,同年4月初登场!! 团名由成员6人姓氏头字母组成, 分别是: K Kamenashi Kazuya 龟梨和也 A Akanishi Jin 赤西仁 T Taguchi Jonnosuke 田口淳之介 T Tanaka Koki 田中圣 U Ueda Tatsuya 上田龙也 N Nakamuru Uyichi 中丸雄一 2006年3月22日正式出道!!! 龟梨和也 かめなしかずや kamenashi kazuya 生日:1986年 2月23日 出生地:枥木県 籍贯:东京都 血型:b型 星座:双鱼座 身高:171cm 体重:50kg 三围:b70|h60.5|w85 体脂肪率:6.5% 视力:右1.0 左1.0 足长:26.5cm 握力:右40kg、左39kg 家庭成员:父母,大4岁的哥哥,大2岁的哥哥,小2岁的弟弟 长处:实事求是,善于应答,常是别人商量的对象。自己却总是找泷泽商量。 短处:情绪起伏大,自我中心,容易恼羞成怒。 特殊才能:棒球 喜欢的颜色:黑色 喜欢的数字:223 喜欢的季节:秋天 喜欢的运动:棒球 平均睡眠时间:5~6小时 平均入浴时间:5分钟(= =b) 入社日期:1998年11月8日 尊敬的前辈:泷泽秀明,二宫和也 必需品:整发料 10年后的自己:2个小孩的父亲 失恋经验:1次(幼稚园) 煲电话粥记录:4个小时 叫他第一名的事:跳舞 目标:想多方面地尝试新的挑战 ,拓展自己的表演舞台。希望藉着6人亦敌亦友的关系,让彼此都能学习到各种事物,进而让KAT-TUN茁壮成长。 加入过的组合:「j2000」、「kat-tun」 参演过的电视:ntv——「怖い日曜日」(《恐怖星期天》) 「ジャパン☆ウォーカー」(《japan walker》) 「the夜もヒッパレ」(《今夜也疯狂》) 「ごくせん2」(《极道鲜师2》) tbs——「3年b组金八先生」(《3年b组金八老师》) 「3年b组金八先生スペシャル」(《3年b组金八老师特别篇》) nhk——「ポップジャム」(《pop jam》) 参演过的广告:lotte「クランキー」、「プラスx」(crunky、plusx) 参演过的舞台剧:「shock」、「dream boy」、「summary」、「hey! say! dream boy」 赤西仁(akanishi jin) 出生:1984年7月4日 出生地:东京都 血型:o 身高:176cm 体重:58kg 鞋码:26.5 视力:左右1.5 家人:父母/弟弟 家裏养的狗的名字:テン和マル(テン是マル的父亲^-^) 长处:有一定程度的完美。食欲旺盛。 短处:有点奇怪的没耐心。很讨厌等人,不过有让人等过。 特殊才能:寻找特技就是他的特技。不过目前为止还没找到。 喜欢做的事:睡觉,买东西。 喜欢的食物:烧肉 喜欢的饮料:碳酸饮料 喜欢的颜色:红,白,黑色 喜欢的动物:狗 喜欢的数字:4,7,12 喜欢的季节:春天 喜欢的科目:体育 喜欢的运动:足球 喜欢的牌子:ヒステリックグラマー 讨厌的时间:早上 讨厌的颜色:土黄色 平均睡眠时间:7个小时 平均入浴时间:30分钟以上 兴趣:音乐鉴赏 宝物:家人,朋友 尊敬的前辈:泷泽秀明,二宫和也,相叶雅纪 必需品:MD 失恋经验:国小6年级 叫他第一名的事:基本上,他的字典里找不到“输”这个字,因为他不想输。要是比不想输的心情,他算是第一。还有快吃也很行。(我地BAGA啊~~要偶说你什么好啊?~) 目标:想要表现出别人模仿不来的风格 田口淳之介 TAGUCHI JUNNOSUKE 生日:1985年11月29日 血型:AB 出生地:神奈川县 身高:180CM 体重:56KG 鞋码:27CM 长处:笑容 短处:不够稳重,最近老是会忘记刚刚所说过的话 特殊才能:随时随刻都能保持笑容。还有就是说老头子的笑话。 喜欢的食物:生果 喜欢的数字:1129 喜欢的季节:夏天 喜欢的花:百合 讨厌的食物:生野菜 叫他第一名的事:特技人员 目标:可以继续不同尝试。和其他成员一起成长。 田中圣 TANAKA KONI 生日:1985年11月5日 血型:B 出生地:千叶县 身高:170CM 体重:46KG 鞋码:25。5CM 长处:对朋友很真诚。绝对信守承诺。 短处:最近有点没耐性。 特殊才能:找大家干杯。开玩笑的,其实是游泳。钢琴和空手道,这3项花了他5年的时间,尤其是空手道,最近有接近黑带的实力。 喜欢的食物:牛肉 讨厌的食物:甜椒,柿子椒,胡萝卜 叫他第一名的事:腹肌。虽然小学时很瘦,但是进入中学后就开始可以锻炼腹肌,造成现在的成果。 目标:10年后,和现在的成员们办个“庆祝成军10周年”的活动。表面看似不和(有么??),其实是互补才能处在一起。 上田龙也 UEDA TATSUYA 生日:1983年10月4日 血型:B 出生地:神奈川县 身高:168(???) 体重:48。9KG 鞋码:26。5CM 长处:无论做什么事都很努力 短处:太过自我。没有主见(你可是LEADER啊····) 特殊才能:打篮球和玩拳击游戏,他的实力连游乐场的拳击机都投降了(强!!) 喜欢的事物:牛肉,牛扒 喜欢的话:努力 宝物:书,出演的戏剧剧本 尊敬的前辈:今井翼,堂本刚 叫他第一名的事:细心第一,温柔第一,灵活度第一,说到灵活度,他自认不输任何人 目标:想让KAT-TUN成为人人口中最佳的团体,无论是搞笑也好,耍帅也好,都希望能应对自如,演技自然 中丸雄一 NAKAMARU YUICHI 生日:1983年9月4日 血型:O 出生地:东京 身高:176CM 体重:51KG 鞋码:26。5CM 视力:1。0 兄弟:妹2人(小小丸子和小小小丸子~~HOHO) 长处:勤于学舞,开朗。每天骑脚踏车上下学。单程15分钟左右。不怕生。 短处:常在一时冲动下乱买东西,每次买东西都会超出预算。 特殊才能:足球跳舞和罚球(篮球的么?)虽然罚球技术还不是很精湛,但是有在努力练习,还有一项就是陪笑(晕倒啊~~) 喜欢的颜色:黑色 喜欢的食物:葡萄干 喜欢的科目:数学 讨厌的科目:英语 尊敬的前辈:米花刚史,町田慎吾 叫他第一名的事情:跳舞 目标:想举办一场让大家看了还想看的演唱会(小丸子啊~基本上我觉得呢~只要是你们KAT-TUN~什么也都是看了还想看的!!) 器图片可以到百度图片去搜

翻译一下全部(包括补充的)David Braben is a well-known game developer who tuns the UK development

fn297

prestigeperformance啥意思?

这些是什么语都不知道,是哪个国家更不知道,还是努力把国语说清楚吧。

hyperlucent是什么意思

透明双语对照词典结果:hyperlucent[英][hau026apu0259"lu:snt][美][hau026apu0259"lu:snt][医]过度透亮(光)的; 以上结果来自金山词霸

观点英语perspection

观点英语perspection如下:perspective。英语(英语:English)是一种西日耳曼语支,最早被中世纪的英国使用,并因其广阔的殖民地而成为世界使用面积最广的语言。英国人的祖先盎格鲁部落是后来迁移到大不列颠岛地区的日耳曼部落之一,称为英格兰。这两个名字都来自波罗的海半岛的Anglia。该语言与弗里斯兰语和下撒克森语密切相关,其词汇受到其他日耳曼语系语言的影响,尤其是北欧语(北日耳曼语),并在很大程度上由拉丁文和法文撰写。英语已经发展了1400多年。英语的最早形式是由盎格鲁-撒克逊人移民于5世纪带到英国的一组西日耳曼语支(Ingvaeonic)方言,被统称为古英语。中古英语始于11世纪末,诺曼征服英格兰;1476年,威廉·卡克斯顿将印刷机介绍给英国,并开始在伦敦出版第一本印刷书籍,扩大了英语的影响力。自17世纪以来,现代英语在英国和美国的广泛影响下在世界各地传播。通过各类这些国家的印刷和电子媒体,英语已成为国际主导语言之一,在许多地区和专业的环境下的语言也有主导地位,例如科学、导航和法律。

为什么android运行时总出现userdata-qemu.img, Permission denied

userdata.img,userdata-qemu.img是用户数据(如用户安装的程序等)的镜像文件请考虑你有没有权限访问

微信小程序怎样修改swiper组件中样式的修改

学小程序时写过一个B站demo,也遇到此问题,最后自定义Swiper的Dot来实现了。思路是:用view组件重写dot,给swiper组件绑定bindchange事件用来获取当前第几个dot,动态改变class。<!-- 滚动广告 begin --><view class="slider-wrapper"> <swiper bindchange="swiperChange" indicator-dots="{{indicatorDots}}"autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"> <block wx:for="{{imgUrls}}" wx:key="*this"> <swiper-item> <image src="{{item}}" class="slide-image"/> </swiper-item> </block> </swiper> <view class="swipe-btn-wrapper"> <view class="swipe-btn-list"> <view class="{{dotsClass[0]}}"></view> <view class="{{dotsClass[1]}}"></view> <view class="{{dotsClass[2]}}"></vi

swiper中a元素可以实现直接跳转页面吗

<div class="swiper-container swiper1"> <div class="arrows_left a_left1"><img src="images/bm_leftbtnpng.png" alt=""/></div> <div class="swiper-wrapper"> <div class="swiper-slide"> <img src="uploads/detail_pic.jpg" alt=""/> </div> <div class="swiper-slide"> <img src="uploads/detail_pic.jpg" alt=""/> </div> <div class="swiper-slide"> <img src="uploads/detail_pic.jpg" alt=""/> </div> <div class="swiper-slide"> <img src="uploads/detail_pic.jpg" alt=""/> </div> <div class="swiper-slide"> <img src="uploads/detail_pic.jpg" alt=""/> </div> </div> <div class="arrows_right a_right1"><img src="images/bm_rightbtn.png" alt=""/></div> </div>/* * swiper初始化 */var swiper1 = new Swiper(".swiper1", { loop:false, grabCursor: true, onSlideChangeStart: function(){ var index=swiper1.activeSlide; $(".p1").html(index+1); swiper2.swipeTo (index); }, onTouchEnd:function(){ /*手指滑动时,判断手指滑动的方向*/ // alert(swiper1.slides.length); goprev(); /*上一篇*/ gonext(); /*下一篇*/ }});
 首页 上一页  14 15 16 17 18 19 20 21 22 23 24  下一页  尾页