共有経験にバブルの背景Couchbaseのキャッシュ

I.はじめに

社交的なビジネスファンタスティックアート「バブル」、6000万+のユーザーと日活、バックグラウンドシステム・インターフェースは、最大80K +にピーク期間中に毎日QPSの主な違いは、より多くのユーザインタラクションの導入に関連したバブルとビデオサービス事業でありますデータの読み取りとボリュームの多くを書きます。それは大量のデータ、または比較的高いQPSであるかどうかは、ほとんどのシナリオでは、私たちは、高い信頼性、高性能、およびオンラインストレージキャッシュシステムの膨大な量に依存することができます。この記事では、キャッシングと最適化方法の使用での経験のいくつかの側面を説明し、我々は手助けをしたいです。

二、Couchbaseのプロフィール

(以下、CBと呼ばれる)のCouchbaseは2011年初頭に両社の合併(memcachedのの主要な開発者によって確立された)とMemBase値(CouchDBのデザイナーの創設者を含む)CouchOneです。MemBase値の会社がMemBase値と呼ばれる製品を持っている、それは、memcachedのワイヤプロトコルとSqlLite埋め込まれたストレージエンジンを使用して永続的な、スケーラブルなソリューションのキー/値です。CouchOneはCouchDBのモバイルデータセンターの異なる場所に分散するのに非常に有用であるエンドツー複製方法を、提供する文書データベースであるサポート。Couchbaseのは、新製品のMemBase値とCouchDBの開発に基づいており、それは両方の長所を兼ね備えています。

Redisの対三、Couchbaseの

CouchbaseのとRedisのは非常に良いのキャッシング製品である、iQIYIバブル社会的背景が異なるアプリケーションシナリオに応じてそれらを多用します以下に要約として、一般的に、彼らは、長所と短所を持っています:

Redisの利点:

(1)Redisのは、複数のデータ構造をサポートすることができます。

Redisのは、より多くのシナリオ(キュー、パブリッシュおよびサブスクライブ、チャート)をサポートしています(2)。

(3)は、多くの操作はIOネットワークを低減する、サーバにすることができるのRedis。

(4)Redisのコミュニティより豊か少し豊かな文書は、より迅速に問題を解決します。

(5)Redisのサポート取引。

Couchbaseの利点:

Redisの好ましくは20Gより大きい容量、またはフェイルオーバーの後に非常に遅い回復をサポートすることができる(1)CB。

(2)CBは、より専門的な管理インターフェースを有します。

(3)一貫性のハッシュは、クライアント上で高いパフォーマンスを発生します。

(4)駅は、サービスサーバのダウンタイムの使用に影響を与えるが、使用可能なメモリ、上位の可用性に影響を受けません。

(5)スケーラビリティ。

Redisの明るいスポットは、高いビジネスフィットは、CBの明るいスポットはその可用性であるということです。比較関数の具体的ないくつかの点から次の抜粋:

第四に、基礎:vBucketでCB

CBにおいて、各バケットの論理分割を、我々はvBucket動作1024 vBucket記憶あたりに格納され、データは、このように呼ばれる、記憶構造に対応する各vBucketサーバーノードにマップされるであろうクラスタマッピング。、ときにアプリケーション対話サーバのCouchbaseと、SDKは、バケットの鍵適用演算の値は、SDKは、式CRC32(キー)を使用して、一方向ハッシュによって計算されるときに、サーバとのデータ交換によって示されるように%1024はキー値がvBucket 1024属する決定し、マッピングされたvBucket・ノード・サーバーに応じてデータを操作します。

分散ストレージシステムの信頼性と可用性を確保するために、データの複数のコピーは、典型的には、システムに格納されています。ストレージノードの存在のコピーが失敗した場合、分散ストレージシステムは、自動的に自動フォールトトレランスを実現するために、他のサービスのコピーに切り替えることができます。

V.優しいWebコンソール

CBは、運用・保守を行うと非常に便利な操作を監視し、非常にフレンドリーなWebコンソールが付属しています。

シックス・ケース1:親指は、システムキャッシュを最適化

まず、システムのビジネスシナリオのようないくつかのポイント:

供給流と呼ばれる流れによって運ば我々チューブバブルサークル情報、及び各々がポストは、フィードと呼ばれる:親指システム親指は、賞賛の最初と呼ばれる給電点を2つのサービスを運びます。理解を容易にするために、我々は国家のポストフィードでそれぞれのフィード流れとして友人のマイクロチャンネル円を、することができます。そのようなサービス・システムが必要とされる、システムなどの地元供給流クエリ点の漏れが存在するであろう、クエリは、UID(一意のユーザ局ID)+基[feedId]一覧です。

第二事業はコメントの事業と同様にポイントで、このような地域のお問い合わせ・ポイント・システムの漏れのリストを確認します、クエリがセットのuid + [commentid]リスト(各コメントにもcommentid呼ばれるグローバルにユニークなIDを持っている)です。

ステージ1:Redisのキャッシュ

キャッシュとしてのRedis、キャッシュ30GはLRU置換キーで演奏しました。

点赞系统的第一个阶段,缓存结构中的key是实体id(即feedid或commentid),value是点赞过该实体的uid 集合。按照实体id查询所有给这个实体点过赞的uid,并且更新Redis缓存。采用这种设计的系统情况是成功率经常抖动,响应时间不稳定。

通过业务日志分析,发现hbase穿透很频繁,缓存命中率不高,原因是缓存容量过低。由于公司云平台提供的是主从模式非集群的Redis,理论上最大缓存量(max_memory)不宜过大(30G已经是上限了),否则会引起主节点故障后failover到备用节点时间过长、甚至循环failover的情况。

当时考虑了两种可能的优化方案:使用CB;或使用 Redis cluster。调研之后发现,原生的Redis cluster不支持批量查询,而如果使用Redis cluster proxy的话可能会有较大性能损耗,并且Redis cluster不支持cluster集群之间的数据同步(我们的场景会用到三个IDC之间的集群同步),所以最终舍弃掉这个方案,考虑使用CB。

阶段二:使用CB替换Redis

缓存key的考虑:uid维度,浪费空间,很多过时的数据会被加载到内存,并且受制于hbase表结构,无法实时拿到某用户点过的所实体。而使用实体id维度,CB不支持server端查询,需要把数据拉到客户端来判断,对于比较热门的实体,uid可能成千上万,数据量太大。uid+实体id维度,CB用量可能比较大,不过查询数据量很小。

最终我们的key采用了uid+实体id的维度,value为是否点过赞。根据uid+实体id进行exist操作(缓存没命中则找不到key,命中的话会返回true或false表明是否点过赞),查询结果更新缓存。

但是很快发现了一些问题:由于缓存命中率低(同一个人再次访问同一个feed才会命中,这种情况比较少见),造成hbase压力过大。不过因为查询hbase使用exist操作,不需要读取数据,所以响应时间很短,成功率基本没有受影响。同时分析了当时的缓存用量的增长趋势,发现CB容量可能扛不住。

阶段三:key的优化

采用实体id+shard方式存储(shard=uid%factor ,实体id维度的变种)

缓存中key使用实体id+shard的方式,value是点过赞的用户列表。穿透到hbase后,根据实体id查询出所有给该实体id点过赞的uid,然后分shard更新缓存,没有数据的shard也要更新上标识。这种方案需要考虑shard个数,在空间和时间上取一个平衡。shard数越大,浪费的CB空间越多,但是每次查询结果集越小。

下面用一个例子来解释两种方案:实体id为e1,factor=20。

优化后的效果如下图,可见成功率相对趋于稳定,且缓存命中率已经高于了99%。

至此优化告一段落了,在这个案例中,有个事情是值得思考的:怎样才能获得更高的命中率呢?我们的答案是谁重复的次数多,以谁为维度缓存。某一个用户可能浏览的feed个数是有限的几十个或者几百个,而某个feed可以被几百万甚至几千万的用户看到。很明显实体重复次数多,所以我们是以实体id为维度(key)来存储。

七、案例2: 投票系统缓存优化

项目背景:投票计数器缓存结构,一个投票可以简单理解为vid(投票id)+多个oid(选项),需要如下缓存,用做计数器。

此次优化主要是针对某热门综艺活动暴露出来的问题。该活动的投票分多个渠道(4个),每个渠道对应一个投票,同时还有一个汇总的投票,每个渠道的选项数是70个。每次业务查询投票接口,各渠道带过来的投票vid都是自己渠道的投票vid,后端需要查询子渠道投票和汇总投票信息,整合之后返回给App端上。

计数器读写模型如下:

之所以每个选项都是一个key,是因为这里考虑到分布式并发操作,需要用到原子的incr操作来增加投票计数。该模式的问题是业务高峰期间对CB的OPS达到到1,400,000次/秒,CB物理机CPU报警。经排查监控分析,发现该综艺活动查询接口QPS有明显变化,并且发现问题时候,大部分流量来自该接口。分析该接口相关代码,发现如果选项过多,一次业务查询,该段逻辑需要批量查300个左右的key,如果业务QPS达到5k(其实并不高),那么CB的OPS将达到1,400,000次/秒左右,确认OPS增加是导致该问题的原因。

定位了原因,优化就很简单了:用一个异步task任务,每隔3s(具体时间间隔需根据业务情况确认)汇总一次所有CB的key,相当于业务的一次查询请求,只需要读一次CB的汇总key的操作,而写请求基本不变(只多了每3秒一次的汇总操作,基本可以忽略),OPS大大降低,减轻物理机CPU压力。

优化后效果非常明显,对CB的OPS大幅降低:

八、案例3: CB客户端SDK版本升级

项目背景:低版本SDK在CB集群rebalance完之后,需要重启,否则可能会有很多超时情况,此为第一个原因。此外,某些后台系统发现新扩容的worker机经常抛出如下异常,然后自动重连,并且不断重复这个过程,导致接口成功率下降。对比了新老机器的nginx、tomcat、代码、jdk、能想到的linux系统参数、QPS、目标访问数据等等,都是完全一致的,且夜间QPS低时候,该问题没有那么明显。在找不到具体触发该异常原因的情况下,由于异常是在CB的SDK中抛出来的(看起来像是读取某个buffer时候越界),因此最直接的方法肯定是尝试升级SDK。

最后我们的方案是将老版本的SDK 1.4.11 升级到 2.3.2。由于操作的都是线上系统,因此升级时需要考虑几点:

(1)新老API兼容问题;

(2)升级不能污染老数据,保证有问题可以回滚;

(3)由于新版本SDK提供了很多新功能,可以考虑顺便优化缓存设计

最终我们根据两个系统的不同情况,采用了两种不同的升级策略:

系统A:缓存中的value都是string,可以跟CB 2.x中的StringDocument完美兼容,所以直接在原来的CB集群上面操作上线。

系统B:缓存中的value类型比较多,如果直接在线上CB集群操作,风险较大,可能会造成数据被污染,且无法回滚,并且因为历史原因线上集群中有一些ttl=0的脏数据,所以采用切换到临时集群的方式:

九、其它注意事项

1.关于热缓存中的数据,有两种方式

需要根据具体业务来选择:

方式1:用线上虚机热数据,即挑选1~2台worker机切换到新CB,相当于一上来这几台worker机的请求是100%到存储上的,但是穿透完后会将数据种回缓存。待缓存命中率达到80%左右就可以继续增加worker机,直到所有worker机都切换到新缓存上。这种方案的优点是简单,缺点就是过程可能会有点慢,且切换过程中可能因为新、旧缓存不一致导致不同worker查出来的数据短暂不同步。

方式2:用作业热缓存。根据指定的规则跑MapReduce作业(比如持久化数据是像我们一样存在hbase中的),一次性把数据刷到缓存中,并且需要把刷存量数据期间产生的增量数据做一个特殊记录,在刷完存量数据后再刷一遍增量的数据。这种方案的优点是过程比较快,缺点是复杂度高。

2.关于跨IDC数据同步的常用两种方式

Couchbase本身就是集群,但通常所谓的集群指的是单一IDC内部的集群,由于机制的限制通常也不会推荐一个集群中存在跨IDC的CB实例。因此像我们这样比较大型的、牵扯到多IDC的后台系统,就需要考虑CB的跨IDC同步问题了。通常有两种方案:

(1)使用CB自带的XDCR,简单快捷,对业务方透明,一致性有保障。比较推荐

(2)业务自己做同步数据。如使用kafka等消息服务来同步数据,即更新CB的worker机发送一条消息到kafka队列,每个IDC都部署一台consumer消费这条kafka消息,种自己本地IDC的CB缓存。这样,相当于多个IDC之间的CB集群本身是独立的,仅仅通过业务方自己的consumer来进行数据同步。该方式比较依赖消息服务,稳定性不是很高,一致性保障难度比较高,业务方需衡量。在早期的XDCR不是很稳定时我们曾有业务系统使用了这种方案,后续也逐步切换成了XDCR的方案。

3.关于遍历所有key

CB不像Redis那样有个keys(*)方法,可以用于遍历所有缓存中的key。因此识别并清除CB中的脏数据(比如早期存了一些ttl=0的数据,后来又不用了)是一件比较难的事情。但是有一种替代方案:同步线上数据到离线CB集群(可以用XDCR),构建view,使用restful api分页查询,遍历所有key。找到脏数据,删除在线集群对应的key。注意该方式value必须是json。

对于value为非json类型的数据,处理起来就很麻烦了。如果业务上有其它能够用来索引key的方式,那么可以采用这样的业务上的数据来遍历所有key。否则,只有像前文所述,申请一个新的CB集群->热缓存->废弃旧的CB集群。

4.开发运维的注意事项

还有一些开发的注意事项,再此一并分享一下:

(1)incr方法,要用String;

(2)ttl超过一个月,需要设置为绝对时间;

(3)新业务请用新版本client,功能更强大,bug更少,低版本坑太多

运维注意事项:

(1)最好装一个ping工具监控worker机与CB集群之间的ping延时;

(2)订阅报警,将问题解决在萌芽状态;

(3)关注CB容量,CB使用内存要低于分配内存的75%,当bucket使用内存达到分配内存的75%时,由于内存不足,Couchbase会通过LRU算法将部分数据从内存中踢出,只存储在磁盘上,下一次读取这部分数据时,再从磁盘取出并加载到内存。从磁盘取数据会使Couchbase的读取性能降低。当bucket使用内存达到或接近分配内存的85%时,bucket可能会出现写不进数据的情况,同时集群读取性能受到较大影响。

十、总结

讲了这么多,最后总结一下对Couchbase缓存优化,其实一般就是指:

(1)提高缓存命中率:往往需要非常了解业务层面的用户行为(如点赞系统须了解用户如何刷feed)

(2)尽量减少OPS vs 一次获取或写入的数据量:取一个平衡

(3)优化缓存用量 vs 提高缓存命中率:取一个平衡

(4)业务复杂,空间不足:按照业务来拆分!

(5)节省空间:先考虑key的设计,再考虑使用protobuf等方式压缩数据(较麻烦)。

おすすめ

転載: www.cnblogs.com/jack4518/p/couchbase.html