キャッシュとデザインの使用
1.利益
加速度リーダー
CPU L1 / L2 / L3キャッシュ、ブラウザキャッシュ、Ehcacheのキャッシュデータベース結果
負荷バックエンド低減する
バックエンドサーバーをフロントバッファを介して負荷を軽減:減少のRedisのMySQLの後端部を使用してロードサービス端末
2.コスト
一貫性のないデータ:キャッシュとデータ層は、時間の矛盾の問題のウィンドウを持っている、とに関連するアップデートポリシー
コードのメンテナンスコスト:キャッシュロジックの層よりも
運用・保守費:例えば、Redisのクラスタ
3.シーンを使用してください
後端負荷低減
高い消費SQLの:結果セット/グループキャッシュ統計参加
加速要求応答を
Memcacheの最適化するためのRedis / IO応答時間を使用して
大規模な書き込みバッチを書き込むように組み合わされた
DB Redisの書き込み次にバッチを蓄積するカウンタ
キャッシュの更新ポリシー
LRUアルゴリズム除外:maxmemoryポリシーなど
2.除く残業:例えば、有効期限が切れ
3.更新イニシアチブ:開発ライフサイクル管理
4. 2推奨
データの低一貫性:最大メモリ戦略とは排除
残業を除くと、最大メモリと排除戦略の組み合わせを更新するためのイニシアチブをとる、すべての詳細を明らかにする:高一貫性を
キャッシュサイズの問題
汎用性:資産の合計額より良い
スペース:いくつかのより良い属性
コードの保守を:表面特性の合計量は、より良いです
キャッシュ貫通の最適化
キャッシュにヒットされていないデータベースクエリから必要とされるため、クエリデータは、データベースクエリに行くべきデータがデータ要求に存在していない時間になりますキャッシュに書き込まれていない見つけ、存在しません。
理由
ビジネスコード自分の問題
悪意のある攻撃は、爬虫類は
、問題を発見した
応答時間が監視することで見つけることができる増加につながるだろう、サービス、悪意のある攻撃の応答時間は、要求は、一般的に、記憶層にヒットしたとき
のビジネス自体が問題
関連指標を:コールの合計数ヒットのキャッシュ層、ストレージ層のヒット数
解決方法1:キャッシュ空のオブジェクト(有効期限を設定)
データ記憶層を見つけることができない場合には、記憶層へのキャッシュがnullのとき、その後、クエリ後は、キャッシュがnullを返す場合があります。
欠点の
キャッシュ層は、複数のキー保存する必要がある
「短期」一貫性のないバッファ層とデータ層のデータを
1 公共ストリングgetPassThrough(文字列キー){ 2 列cacheValue = cache.get(キー)。 3 であれば(StringUtils.isEmpty(cacheValue)){ 4 列storageValue = storage.get(キー)。 5 cache.set(キー、storageValue)。 6 場合(StringUtils.isEmpty(storageValue)){ 7 cache.expire(キー、* 5 60 )。 8 } 9 リターンstorageValue。 10 } 他{ 11 リターンcacheValue。 12 } 13 }
溶液2:(固定データ用)ブルームフィルタインターセプト
ビットマップデータは、このように基本的なストレージシステム上でクエリの圧力を避け、遮断されるに十分な大きさのビットマップにハッシュ可能なすべてのデータが、1は存在しません。
キャッシュ最適化の雪崩
リクエストの数が多い、異常オフラインキャッシュサービスをホストしているキャッシュサーバので、トラフィックが直接カスケード故障が生じ、アセンブリの後端部に押し付け。バッファリングや時間の故障期間に集中し、キャッシュの浸透がたくさん起こります
解決策1:高可用性のキャッシュを確保するために
でも、マルチノード、マルチマシン、マルチルームをキャッシュでください。
Redisのクラスタ、RedisのSentinelは
、二次キャッシュを行います
溶液2:流量制限器の後端に依存分離アセンブリ
Hystrixが劣化したサービスを行う使用
解決策3:早期行使(ストレステスト)
解決策4:ランダムセット異なるキーの有効期限
底なしの問題
あなたは、マシンを追加すると、クライアントのパフォーマンスは増加しなかっただけでなく、減少
キーポイント
=高い性能を複数のマシンを!
もっとマシン=データの増加とscale-
バッチ・インターフェース要件:増加に伴いMGETマシン、ネットワーク・アクセス・ノードの数をもっと。> O( - O(1)によってネットワークノードの時間複雑ノード)
IOの最適化の方法
キー、hgetall、bigKeyを照会し、最適化:スロークエリを低減:コマンド自体最適化
ネットワーク通信の数減らすために
、O(キー)によってMGETをO(ノード)にアップグレードし、O(max_slow (ノード))、 偶数およびO(1)
アクセスのコストを削減する:例えば、長い接続クライアント/接続プール、NIO等
ホットキー再構築の最適化
ホットキー(より多くの量へのアクセス)は、+長い時間(時間のかかる復興のプロセスをより多くのAPIまたはインタフェース)を再構築し
、データ・ソースを照会し、キャッシュを再構築するために多数のスレッド、メモリ層は、驚異的な原因:起因する問題圧力は、応答時間が非常に遅くなります
1.三つの目標
再キャッシュの数減らす
できるだけ一貫性のあるデータを
潜在的な危険を減らすために:例えば、デッドロック、スレッドプールは、ライブ(サスペンション)の多数を掛けるあります
2.どちらのソリューション
ミューテックス(DLM)は、
最初のスレッドは、分散ロックに参加するキーを再構築が完了した後に復興のロックを解除するために、再構築する時間を必要とし
、このアプローチキャッシュとストレージ層を再構築するために多くの圧力を回避し、まだたくさんのを持っていますブロックするスレッド
jedis.set(lockKey、requestId、SET_IF_NOT_EXIST、SET_WITH_EXPIRE_TIME、expireTime) 文字列(文字列キー)を取得{ 文字列SET_IF_NOT_EXISTは = "NX" 。 文字列のSET_WITH_EXPIRE_TIME = "PX" 。 文字列値 = jedis.get(キー)。 もし(ヌル == 値){ 文字列lockKey = "lockKey:" + キー。 もし( "OK" .equals(jedis.set(lockKey、 "1" 、SET_IF_NOT_EXIST、 SET_WITH_EXPIRE_TIME、 180 ))){ 値 = db.get(キー)。 jedis.set(キー、 jedis。 } 他{ のThread.sleep( 50 )。 (キー)を取得します。 } } 戻り値。 }
有効期限が切れることはありません
キャッシュレベル:有効期限を設定していない(有効期限は使用しない)
の機能レベル:各論理有効期限のための付加価値は、より多くの単一の論理有効期限よりも、キャッシュを再構築するために別のスレッドを使用することがわかりました。
データの矛盾の状況もあります。ロジックは、比較的削減された有効期間が比較的される実際の有効期限とすることができます
問題のRedisのスケール
面倒な、プライベート乗るLuangaiの構築リリース
ノード&機械やその他の運用・保守コスト
の監視警報比較的低レベルの
CacheCloud主な機能
Redisの(シングルポイント、センチネル、クラスタ)を開くための鍵
マシン、アプリケーション、モニタリングの例と警告
透明の使用、報告パフォーマンス:クライアントを
視覚的に運用・保守を:設定、展開を、フェイルオーバー、オフラインマシン/アプリケーション/インスタンスが
すでにに直接Redisのが存在しますデータ移行
ブルームフィルタ抽出
迅速かつ正確に電話番号が既に存在するかどうかを判断するために10万の電話番号があり、既存の50億個の電話番号:問題につながる
1.データベースクエリを:速い少し難しい
2.データ収集予めメモリに:50億* 8バイト= 40ギガバイト(*** ***メモリ消耗または十分でない)
3. hyperloglog:少し難しい正確に
ブルームフィルタの原理
パラメータはに必要
Mバイナリーベクター(Mバイナリ桁)
(電話番号50億同様の問題)は、n番目の予備データ
(指定されたベクトル1として識別された各データに対して1つの、一つのハッシュ一つ)ハッシュ関数番目K
建設ブルームフィルタ
n個のデータのハッシュ処理は上下一つずつ
の要素が存在するか否かを判定する
ハッシュ実行バイ要素
全てのベクターで得られた場合は1であり、それは存在、現在の要素およびその逆が存在しないことを示してハッシュ結果を
ブルームフィルタエラーレート
データの結果が正確でなければならない戻りが、エラーデータはまた、上にあってもよい
視覚的要素
M / N比:より大きい比、小さい誤り率
関数のハッシュ番号:より多く、より多くの誤り率小さな
ローカルブルームフィルタ
グァバ:ライブラリを達成
1つのファンネル<整数>漏斗= Funnels.integerFunnel()。 2 INTのサイズ= 1000_000。 3 二重 errorChance = 0.001。 // 错误率 4ブルームフィルタ<整数> =フィルタBloomFilter.create(漏斗、サイズ、errorChance)。 5 ためには、(int型 i = 0; iが大き<; Iは++ ){ 6 filter.put(I)。 7 } 8 ため(int型 ; iはサイズが<I = 0 iは++ ){ 9 もし(!filter.mightContain(I)){ 10 のSystem.out.println( "发现不存在的数据:" +私); 11 } 12 }
ブルームフィルタの問題
制限されている容量
のアプリケーションの複数のブルームフィルタを複数、複雑なフィルタ構築の同期
シングルブルームフィルタのRedis
setbitによって達成ビットマップを基に、getbitコマンドが実装されている
ハッシュ関数を:
MD5
murmur3_128
murmur3_32
SHA1
SHA256
SHA512は、
ベースのRedisは、単一の問題を実装し
たネットワークで失われ、より機械で:遅い
個別に配備され、同じ部屋または同じを適用するには:ソリューション1ラック展開
溶液2:パイプラインの使用
容量の制限を:Redisの512メガバイトの最大列、Redisのユニット容量の
溶液:実現ベースRedisCluster
ブルームフィルタは、Redisのクラスタの実装しました
ブルームフィルタの複数の二次ルーティング
ベースのパイプライン効率
メモリ管理
メモリ使用量の統計
情報メモリ
2.メモリ消費量分割
used_memory一部
独自のメモリ(約800K)
のバッファメモリ
クライアントバッファ
コピーバッファ
AOFバッファ
メモリオブジェクト
キーオブジェクトの
Valueオブジェクト
LuaのRAM
メモリの断片化= used_memory_rss - used_memory(アプリケーションのメモリ使用より多くのメモリ、メモリおよびメモリ予約よりまだリリース)
3.子プロセスのメモリ消費量
フォークが子プロセスを作成する際のRedisは、書き込みが発生したときにフォークが、それはメモリコピー・オン・ライト複製されますされ、bgsaveとbgrewriteaofで使用する
最適化を
THPの機能を削除するには:新しいカーネル2.6.38に機能。この機能は、フォークをスピードアップすることができますが、メモリページをコピーするときに、元のメモリページより512倍を拡大していきます。例えば、それは後から2Mに拡大し、4Kであることが判明しました。より大きな書くときに、不必要な障害物やメモリ爆発の原因となります。
overcommit_memory = 1フォークが正常に完了したことを保証することができます
#は、クライアントの接続に関する基本情報を見ます
情報クライアント
#すべてのクライアントの詳細のすべてのRedis-サーバーを参照してください。
クライアントリスト
入力バッファ
Redisの実行各クライアントコマンドは、シングルスレッドによってキューに入れられ、入力バッファのRedisに格納されている
-注:最大入力バッファ1ギガバイト、それは切断され、動的ではない構成よりも後に強制されます
出力バッファ
1クライアント出力バッファ・リミット-側$ { クラス}} $ {$ {限界ハードソフトソフト秒制限} {} $ 2 ## クラスのクライアントタイプ 3 ##標準標準クライアント 4 複製のための##スレーブノードからクライアントとして、変装 5 ## PubSubのは、クライアントにサブスクライブパブリッシュ 6 の出力バッファがクライアントによって使用されている場合##ハード限界がハード限界よりも大きい場合、クライアントはただちにシャットダウンされます 7 、出力バッファがクライアントによって使用されている場合##、ソフト限界をして、ソフト限界を超えますsoftSecondsは、クライアントがすぐにオフになります秒続い 8を ##どのハード限界を0に制限し、ソフト限界ません
1.通常のクライアント
デフォルトの設定:クライアント-出力バッファリミットノーマル0 0 0
注:あなたが大規模なコマンドやモニターを防ぐために必要があるが、どちらの場合は、出力バッファサージになります
2.slaveクライアント
デフォルトの設定:クライアント-出力バッファ制限スレーブ256メガバイト60の64メガバイト
長い待ち時間からメイン可能性を、またはコピーバッファから目詰まりの主なりやすいからノードの過剰な数を高速に再生される場合:推奨事項が上げ。最終的にフルボリュームコピーをもたらす
注:マスタースレーブネットワークではないつ以上のノードから
3.pubsubクライアント
デフォルトの設定:クライアント-出力バッファ制限のpubsub 32メガバイトの60の8メガバイト
のブロッキングの理由:消費率よりも大きな生産速度
注:あなたは、実際の状況をデバッグする必要があります
バッファメモリ
1.コピーバッファ
このメモリの排他的な部分は、デフォルトの1メガバイトは、コピーの一部と考え、あなたは大きなを設定することができ、いくつかのメモリコピーの費用を避けるために100メガバイト、完全な量に設定することができます。
2.AOFバッファ
かかわらず、常に、everysecsはまだ戦略は、ディスクブラシAOFバッファに格納されたデータの前に、ブラシセットできなくなります。
また、AOF書き換え時、AOFは、バッファを割り当て、それらを書き換えるバッファに格納される書き換えデータを書き込む書き換え。
データの矛盾を回避するためにバッファの内容を書き換え、書き換えが完了した後に発生したAOFは、AOFバッファに同期します。
AOFは、バッファ容量の制約とは関係ありません。
オブジェクトのメモリ
キー:長すぎない、大量のは、39バイトに制御することが推奨され、無視することはできません。(Embstr)
値:圧縮の彼らの内部コードをコントロールしよう。
メモリ断片化は
jemallocにメモリの断片に存在しなければならない
理由
順番に各範囲は、メモリ部の多数の小ブロックに分割し;小、大、巨大な3つの範囲に分割され、jemalloc関連jemallocメモリ空間を選択するときにデータを格納しますメモリブロックの最適なサイズが格納されています。
redis作者为了更好的性能,在redis中实现了自己的内存分配器来管理内存,不用的内存不会马上返还给OS,从而实现提高性能。
修改cache的值,且修改后的value与原先的value大小差异较大。
优化方法
重启redis服务,
redis4.0以上可以设置自动清理 config set activedefrag yes,也可以通过memory purge手动清理,配置监控使用性能最佳。
修改分配器(不推荐,需要对各个分配器十分了解)
避免频繁更新操作
内存回收策略
1.删除过期键值
惰性删除
1. 访问key
2. expired dict
3. del key
定时删除:每秒运行10次,采样删除
2.maxmemory-policy
Noevition:默认策略,不会删除任何数据,拒绝所有写入操作并返回错误信息。
volatile-lru:根据lru算法删除设置了超时属性的key,直到腾出空间为止。如果没有可删除的key,则将退回到noevition。
allkeys-lru:根据lru算法删除key,不管数据有没有设置超时属性,直到腾出足够空间为止。
allkeys-random:随机删除所有键,直到腾出足够空间为止。
volatile-random:随机删除过期键,直到腾出足够空间为止。
volatile-ttl:根据键值对象的ttl属性,删除最近将要过期的数据。如果没有,回退到noevicition。
客户端缓冲区优化
案例:一次线上事故,主从节点配置的maxmemory都是4GB,发现主节点的使用内存达到了4GB即内存已打满。而从节点只有2GB。
思考方向
考虑Redis的内存自身组成
主从节点之前数据传输不一致(会导致对象内存不一致)
dbsize
查看info replication中的slave_repl_offset
查看缓冲区方面
通过info clients查看最大的缓冲区占用
通过client list查看所有客户端的详细信息
问题发现:
存在一个monitor客户端对命令进行监听,由于Redis的QPS极高,monitor客户端无法及时处理,占用缓冲区。
问题预防
运维层面:线上禁用monitor(rename monitor "")
运维层面:适度限制缓冲区大小
开发层面:理解monitor原理,可以短暂寻找热点key
开发层面:使用CacheCloud可以直接监控到相关信息
内存优化其他建议
不要忽视key的长度:1个亿的key,每个字节都是节省
序列化和压缩方法:拒绝Java原生序列化,可以采用Protobuf、kryo等
不建议使用Redis的场景
数据:大且冷的数据
功能性:关系型查询、消息队列
完