您好,欢迎访问三七文档
TAIRTair是一个高性能,分布式,可扩展,高可靠的key/value结构存储系统。Tair提供两种存储方式:非持久,相当于cacheomdb引擎:支持key/value,prefix,单机性能30wqps(测试条件:单条记录200字节,响应时间2ms内)ordb引擎:不仅支持key/value,还支持list/hashmap/set/sortedset等复杂数据结构。持久化存储,类似数据库。数据直接存放进硬盘,并且至少会有两份。oldb引擎:采用了leveldb做为引擎,并且自带cache。服务器采用了ssd,性能在5wqps以上。Leveldb是一个google实现的非常高效的kv数据库,目前的版本1.2能够支持billion级别的数据量了。在这个数量级别下还有着非常高的性能,主要归功于它的良好的设计。LevelDb性能非常突出,官方网站报道其随机写性能达到40万条记录每秒,而随机读性能达到6万条记录每秒。总体来说,LevelDb的写操作要大大快于读操作,而顺序读写操作则大大快于随机读写操作。写快速的原因是,先写commitlog,此时这个是bufferio,宕机也会有数据丢失。Tair现在支持Java和C/C++版本的客户端。Tair架构:tair作为一个分布式系统,是由一个中心控制节点和一系列的服务节点组成.我们称中心控制节点为configserver.服务节点是dataserver.configserver负责管理所有的dataserver,维护dataserver的状态信息.dataserver对外提供各种数据服务,并以心跳的形式将自身状况汇报给configserver.configserver是控制点,而且是单点,目前采用一主一备的形式来保证其可靠性.所有的dataserver地位都是等价的.tair的server端是C++写的,因为server和客户端之间使用socket通信,理论上只要可以实现socket操作的语言都可以直接实现成tair客户端.目前实际提供的客户端有java和C++.客户端只需要知道configserver的位置信息就可以享受tair集群提供的服务了.Tair缓存使用的场景1.数据可以以key/value的形式存储2.数据可以接受丢失3.访问速度要求很高4.单个数据大小不是很大,一般在KB级别5.数据量很大,并且有较大的增长可能性6.数据更新不频繁Tair持久化适用的场景1.数据可以以key/value的形式存储2.数据需要持久化3.数据量很大,并且有较大的增长可能性4.单个数据大小不是很大,一般在KB级别5.数据的读写比例较高Tair不适用的场景1.对数据有查询需求,比如对key的模糊查询,或者根据value反查询key等2.单条数据很大3.读写比例很低【基本概念和知识相关】group_name指的是什么?tair集群由configserver管理,configserver可以管理多个集群,为了将集群区分,引入了group概念,一个group对应一个集群,group_name用于配置所使用的集群。什么是area?什么是namespace?area是在tair中分配给应用的一个区域,可以认为应用的数据存在自己的area中。同一group中area是唯一的。namespace是area的马甲称呼,二者等同。什么是配额(quota)?配额是每个area对应的储存区的大小的限制,超过配额后数据将面临最近最少使用(LRU)的淘汰。持久化引擎(ldb/kdb)本身没有配额,ldb由于自带了cache,所以也可以设置cache的配额怎么预估该申请多大配额?记录条数*单条记录大小管理员怎么配置配额?如果集群备份是单份的,则按业务预估出来的数据配置即可。如果备份是2,那么在配置的时候需要将quota*2什么是expiredTime?expiredTime是指数据的过期时间,当超过过期时间之后,数据将对应用不可见。不同的存储引擎有不同的策略清理掉过期的数据。调用接口时,expiredTime单位是秒,可以是相对时间(比如:30s),也可以是绝对时间(比如:当天23时,转换成距1970-1-100:00:00的秒数)。如果不传或者传入0,则表示数据永不过期;大于0小于当前时间戳是相对时间过期,大于当前时间戳是绝对时间过期。什么是version?version有什么用?在Tair的put接口中,有一个version参数,这个参数是为了解决并发更新同一个数据而设置的。很多情况下,更新数据是先get,修改get回来的数据,然后put回系统。如果有多个客户端get到同一份数据,都对其修改并保存,那么先保存的修改就会被后到达的修改覆盖,从而导致数据丢失问题,在有些情况下,这个是我们不希望发生的。比如客户端A和B取到数据{key,value},A将value修改为value,value_a,B将value修改为value,value_b,A先保存,B然后保存,则最终的value为value,value_b,这时A的修改就不可见了。version是为了防止这中情况而设置的,tair中的数据每次更新都会将version加一。每次get时,服务器都会返回当前数据的版本,如果Tair中的数据版本与传入的version相同,此次更新才会成功,否则如果在get与更新之间,数据被更新,导致Tair中的version与client传来的version不一致,该次更新会失败,返回versionerror。如果应用不关心并发更新的一致性,调用客户端接口时,version必须不传或者传入0.version怎么使用?get接口返回的是DataEntry对象,该对象中包含get到的数据的版本号,可以通过getVersion()接口获得该版本号。在put时,将该版本号作为put的参数即可。如果不考虑版本问题,则可设置version参数为0,系统将强行覆盖数据,即使版本不一致。如果返回version不一致,我该怎么办?如果更新所基于的version和系统中当前的版本不一致,则服务器会返回ResultCode.VERERROR。这时你可以选择重新get数据,然后在新版本的数据上修改;或者设置version为0重新请求,以达到强制更新的效果。version具体使用案例如果应用有10个client会对key进行并发put,那么操作过程如下:1.getkey。如果getkey成功,则进入步骤2;如果数据不存在,则进入步骤3.2.在调用put的时候将getkey返回的verison重新传入put接口。服务端根据version是否匹配来返回client是否put成功。3.getkey数据不存在,则新put数据。此时传入的version必须不是0和1,其他的值都可以(例如10,要保证所有client是一套逻辑)。因为传入0,tair会认为强制覆盖;而传入1,第一个client写入会成功,但是新写入时服务端的version以0开始计数啊,所以此时version也是1,所以下一个到来的client写入也会成功,这样造成了冲突。案例分析:分布式锁tair中存在该key,则认为该key所代表的锁已被lock;不存在该key,在未加锁。操作过程和上面相似。业务方可以在put的时候增加expire,已避免该锁被长期锁住。我该不该使用Version?这取决于应用对数据一致性的要求,如果对数据一致性有较高的要求,并且访问并发高,有很多类似append的操作,那么通过version可以避免数据的意外结果。当不需要关心并发的时候,不传入或者传入version为0。什么情况下version会重置为1?第一次put到tair什么是失效(invalid)?什么是失效(invalid)?可能会在多个机房中部署多个Tair集群,而用户的数据可能同时分布在这多个集群,所以当删除时,除了要删除本地集群中数据,还要删除其他集群上的数据,以保证数据的一致性。区别于删除(delete:只删除本机房的数据),将这个操作称为失效(invalid)。失效有专门的失效服务器(invalidserver)处理。失效后服务器会马上删除数据吗?失效后服务器端不会马上删除数据,但是服务器保证该数据不会被get到客户端使用失效要做特别配置吗?失效由失效服务器处理。失效服务器地址是配置在configserver上的,自动推送到客户端,所以对用户是透明的,也不需要用户配置。【申请以及使用相关】使用Tair需要提供什么信息?使用Tair前,请先确认以下事项:1.存储的数据是key-value的形式2.key和value的size不应过大(key小于1K,value小于1M);key和value在推送到服务端之前会被压缩,1K/1M的限制是针对压缩后大小的,但由于压缩比会随数据类型不同而不同,所以不应该对压缩比做任何假设。3.存储的数据是否需要持久化4.数据的存储方式(比如:一次大量写入,后续读取;?更新很频繁?数据一段时间可废弃?。。。)5.需要的数据存储量6.访问的高峰qps,读写比。7.期望的响应时间,容忍的最大响应时间8.是否在交易的流程中(出现问题,可能会影响到交易)一些基本概念在进行具体的开发前,有几个概念需要先了解一下,包括:1.key和value允许的最大值2.key和value参数的要求3.版本4.失效和删除key和value允许的最大值Tair的设计目标是用于存放小数据的,所以我们对key和value的大小都做了限制,如果你需要存放的数据大于这个限制,那么请出门右拐:。Tair在存储前会将key和value序列化,所以这里的最大值都是针对序列化后而言的。Key的最大值为:1KBValue的最大值为:1MB超过这个大小的数据将分别返回*ResultCode.KEYTOLARGE*和*ResultCode.VALUETOLARGE*key和value参数的要求Key和Value都需要实现序列化接口.Value在接口中已经明确规定需要实现序列化接口。Key在这里没有规定使用序列化的原因是我们建议key应该尽可能只使用简单的对象,比如Integer、Long、String等,而不是复杂的对象。复杂的对象不仅仅在福序列化和反序列化上需要消耗时间,而且也会影响服务器端的查找效率。版本Tair的put接口中可以传入一个版本的参数,这个参数适用于控制并发更新的问题而设置的。假设系统中有一个数据{1,a,b,c},即key为1,value为a,b,c的字符串,线程T1和T2先后获取到这个值,T1在value后面添加d,即value修改为a,b,c,d并保存,同时T2在value后面添加e,即value修改为a,b,c,e并保存,那么无论T1先保存成功还是T2先保存成功,总是有一个更新丢失了,结果要么是a,b,c,d,要么是a,b,c,e。我们并不能完全解决这个问题,但是我们认为在发生这种问题前,用户有权知道这个问题。所以我们引入了版本的概念,每个数据都有一个和其相关的版本,这个版本在每次更新成功后都+1。get一个数据时,系统会同时返回这个数据当前的版本,更新数据时将该版本号传给系统,当系统中的版本号和更新传入的版本号不一致时,更新将会被拒绝,返回*ResultCode.VERERROR*错误代码。我们来看加了版本后前面的问题会怎么样,假设两个线程获取数据时,数据在系统中的版本为3,当T1和T2修改数据后更新时同时传入版本3,无论T1成功还是T2成功,系统中的版本号都会变成4,当另一个更新到来时,系统发现更新基于的版本是3,而系统中版本已经是4,则拒绝更新,返回错误代码,保持原有数据不变。当传入的版本参数为0时,系统不判断版本而强制更新,系统中的数据版本仍旧会+1。应用在得知版本错误后,可以选择重新get数据,在新的数据上修改然后更新,或者将版本设置为0强制更新。失效和删除失效和删除的结果都是将对应的数据删除,但是失效
本文标题:TAIR资料
链接地址:https://www.777doc.com/doc-2862008 .html