zoukankan      html  css  js  c++  java
  • 思考问题的方式

    普通事情的思考方式

    1、行动的主体是谁?

    2、行动的对象时谁?

    3、行动的行为是什么?

    4、行为的描述是什么?

    如:护士给病人注射标准剂量的流感疫苗

    概念抽象为:

    护士(有注射疫苗的行为),病人,流感疫苗(设置剂量)

    Tair缓存的思考方式:

    1、缓存服务包括那几部分:

          一个Tair集群主要包括3个必选模块:configserver、dataserver和client,一个可选模块:invalidserver。

    2、缓存服务器中各部分的作用:

    2.1 ConfigServer的功能

    1) 通过维护和dataserver心跳来获知集群中存活节点的信息
    2) 根据存活节点的信息来构建数据在集群中的分布表。
    3) 提供数据分布表的查询服务。
    4) 调度dataserver之间的数据迁移、复制。

    2.2 DataServer的功能

    1) 提供存储引擎
    2) 接受client的put/get/remove等操作
    3) 执行数据迁移,复制等
    4) 插件:在接受请求的时候处理一些自定义功能
    5) 访问统计

    2.3 InvalidServer的功能

    1) 接收来自client的invalid/hide等请求后,对属于同一组的集群(双机房独立集群部署方式)做delete/hide操作,保证同一组集群的一致。
    2) 集群断网之后的,脏数据清理。
    3) 访问统计。

    2.4 client的功能

    1) 在应用端提供访问Tair集群的接口。
    2) 更新并缓存数据分布表和invalidserver地址等。
    3) LocalCache,避免过热数据访问影响tair集群服务。
    4) 流控

    3、缓存服务有哪些应用方式:

         Tair经过这两年的发展演进,除了应用于cache缓存外,在存储(持久化)上支持的应用需求也越来越广泛。现在主要有mdb,rdb,ldb三种存储引擎。

    3.1 mdb

    定位于cache缓存,类似于memcache。
    支持k/v存取和prefix操作

    3.1.1 mdb的应用场景
    在实际业务中,大部分当缓存用(后端有DB之类的数据源)。
    也可用做大访问少量临时数据的存储(例如session登录,防攻击统计等)。
    集团内绝对多数cache服务都是采用的tair mdb。

    3.2 rdb

    定位于cache缓存,采用了redis的内存存储结构。
    支持k/v,list,hash,set,sortedset等数据结构。

    3.2.1 rdb的应用场景
    适用于需要高速访问某些数据结构的应用,例如SNS中常见的的粉丝存储就可以采用set等结构;或者存储一个商品的多个属性(hashmap);高效的消息队列(list)等。现在有30个左右的应用在使用rdb服务。

    3.3 ldb

    定位于高性能存储,并可选择内嵌mdb cache加速,这种情况下cache与持久化存储的数据一致性由tair进行维护。 支持k/v,prefix等数据结构。今后将支持list,hash,set,sortedset等redis支持的数据结构。

    3.3.1 ldb的应用场景
    存储,里面可以细分如下场景:
    1) 持续大数据量的存入读取,类似淘宝交易快照。
    2) 高频度的更新读取,例如计数器,库存等。
    3) 离线大批量数据导入后做查询。参见fastdump
    也可以用作cache:
    数据量大,响应时间敏感度不高的cache需求可以采用。例如天猫实时推荐。

    4、 缓存系统中的基本概念

    4.1 configID

    唯一标识一个tair集群,每个集群都有一个对应的configID,在当前的大部分应用情况下configID是存放在diamond中的,对应了该集 群的configserver地址和groupname。业务在初始化tairclient的时候需要配置此ConfigID。

    4.2 namespace

    又称area, 是tair中分配给应用的一个内存或者持久化存储区域, 可以认为应用的数据存在自己的namespace中。
    同一集群(同一个configID)中namespace是唯一的。
    通过引入namespace,我们可以支持不同的应用在同集群中使用相同的key来存放数据,也就是key相同,但内容不会冲突。一个namespace 下是如果存放相同的key,那么内容会受到影响,在简单K/V形式下会被覆盖,rdb等带有数据结构的存储引擎内容会根据不同的接口发生不同的变化。

    4.3 quota配额

    对应了每个namespace储存区的大小限制,超过配额后数据将面临最近最少使用(LRU)的淘汰。
    持久化引擎(ldb)本身没有配额,ldb由于自带了mdb cache,所以也可以设置cache的配额。超过配额后,在内置的mdb内部进行淘汰。

    4.3.1 配额是怎样计算的
    配额大小直接影响数据的命中率和资源利用效率,业务方需要给出一个合适的值,通常的计算方法是评估在保证一定命中率情况下所需要的记录条数,这样配额大小即为: 记录条数 * 平均单条记录大小。

    4.3.2 管理员如何配置配额
    单份数据情况下,业务提供的配额就是需要配置在Tair系统中的配额。但对于多备份,在系统中实际计算的配额为: 业务配额 * 备份数

    4.4 expireTime:过期时间

    expiredTime 是指数据的过期时间,当超过过期时间之后,数据将对应用不可见,这个设置同样影响到应用的命中率和资源利用率。不同的存储引擎有不同的策略清理掉过期的数 据。调用接口时,expiredTime单位是秒,可以是相对时间(比如:30s),也可以是绝对时间(比如:当天23时,转换成距1970-1-1 00:00:00的秒数)。 小于0,不更改之前的过期时间
    如果不传或者传入0,则表示数据永不过期;
    大于0小于当前时间戳是相对时间过期;
    大于当前时间戳是绝对时间过期;

    4.5 version

    Tair中存储的每个数据都有版本号,版本号在每次更新后都会递增,相应的,在Tair put接口中也有此version参数,这个参数是为了解决并发更新同一个数据而设置的,类似于乐观锁。
    很多情况下,更新数据是先get,修改get回来的数据,然后put回系统。如果有多个客户端get到同一份数据,都对其修改并保存,那么先保存的修改就 会被后到达的修改覆盖,从而导致数据一致性问题,在大部分情况下应用能够接受,但在少量特殊情况下,这个是我们不希望发生的。
    比如系统中有一个值”1”, 现在A和B客户端同时都取到了这个值。之后A和B客户端都想改动这个值,假设A要改成12,B要改成13,如果不加控制的话,无论A和B谁先更新成功,它 的更新都会被后到的更新覆盖。Tair引入的version机制避免了这样的问题。刚刚的例子中,假设A和B同时取到数据,当时版本号是10,A先更新, 更新成功后,值为12,版本为11。当B更新的时候,由于其基于的版本号是10,此时服务器会拒绝更新,返回version error,从而避免A的更新被覆盖。B可以选择get新版本的value,然后在其基础上修改,也可以选择强行更新。

    4.5.1 如何获取到当前key的version
    get接口返回的是DataEntry对象,该对象中包含get到的数据的版本号,可以通过getVersion()接口获得该版本号。在put时,将该 版本号作为put的参数即可。 如果不考虑版本问题,则可设置version参数为0,系统将强行覆盖数据,即使版本不一致。

    4.5.2 version是如何改变的
    Version改变的逻辑如下:
    1) 如果put新数据且没有设置版本号,会自动将版本设置成1。
    2) 如果put是更新老数据且没有版本号,或者put传来的参数版本与当前版本一致,版本号自增1。
    3) 如果put是更新老数据且传来的参数版本与当前版本不一致,更新失败,返回VersionError。
    4) put时传入的version参数为0,则强制更新成功,版本号自增1。

    4.5.3 version返回不一致的时候,该如何处理
    如果更新所基于的version和系统中当前的版本不一致,则服务器会返回ResultCode.VERERROR。 这时你可以重新get数据,然后在新版本的数据上修改;或者设置version为0重新请求,以达到强制更新的效果,应用可以根据自身对数据一致性的要求 在这两种策略间进行选择。

    4.5.4 version具体使用案例
    如果应用有10个client会对key进行并发put,那么操作过程如下:
    1) get key。如果get key成功,则进入步骤2;如果数据不存在,则进入步骤3.
    2) 在调用put的时候将get key返回的verison重新传入put接口。服务端根据version是否匹配来返回client是否put成功。
    3) get key数据不存在,则新put数据。此时传入的version必须不是0和1,其他的值都可以(例如1000,要保证所有client是一套逻辑)。因为 传入0,tair会认为强制覆盖;而传入1,第一个client写入会成功,但是新写入时服务端的version以0开始计数啊,所以此时version 也是1,所以下一个到来的client写入也会成功,这样造成了冲突

    4.5.5 version分布式锁
    Tair中存在该key,则认为该key所代表的锁已被lock;不存在该key,在未加锁。操作过程和上面相似。业务方可以在put的时候增加expire,已避免该锁被长期锁住。
    当然业务方在选择这种策略的情况下需要考虑并处理Tair宕机带来的锁丢失的情况。

    4.5.6 什么情况下需要使用version
    业务对数据一致性有较高的要求,并且访问并发高,那么通过version可以避免数据的意外结果。
    如果不关心并发,那么建议不传入version或者直接传0。

  • 相关阅读:
    EveryOne Piano
    3D扫描商店
    Substance PBR Guide
    C2GOASM
    Unity调试外部DLL
    BinaryReader优化
    IL
    如何画头发
    Bitrix24
    Mac查找包含指定字符串的文件
  • 原文地址:https://www.cnblogs.com/xuelu/p/3788664.html
Copyright © 2011-2022 走看看