どのようにの姿勢まで、ローカルキャッシュを設計します!

作者:ksfzhaohui。https://my.oschina.net/OutOfMemory/blog/3133013

最近だけMyBatisのキャッシュと二次キャッシュが設けられているキャッシュを確認するために、MyBatisのソースを読み取り、キャッシュが比較的簡単で、優れた機能は、二次キャッシュ、実質的に満たされているキャッシュされていますいくつかの機能。

もちろん、持ってきた場合に比較するために、特別なキャッシュフレームワークは、私たちが物事を検討する必要があるかを認識すべきであるローカルキャッシュを整理わずかにehcacheなどギャップ、将来の記事かもしれません。

ポイントを考えてみましょう

主なポイントは、格納できるデータの量、どのようにデータ処理および他のいくつかの点冗長の各点の詳細な説明を考えると、どのように達成するために、データが中に記憶されている方法を検討します。

1.データ構造

主な検討事項は、直接マップストレージを使用して、最も単純なデータで保存されたどのようなデータ構造、データを格納する方法であり、あるいは、データ型のハッシュを数多く提供してリスト、セットなどのコレクションを、注文のRedisのような複雑な二重リンクリストなどの圧縮、集合、データ構造、テーブル、ジャンプのリストを使用して下端。

2.オブジェクトのキャップ

それがローカルキャッシュであるため、メモリは上限があるため、通常、このような制限は、余分なデータを削除するための戦略のいくつかの種類を持っている必要がありますに達している1024、キャッシュされたオブジェクトの数を指定します。

3.明確な戦略

それはオブジェクトの上限に達したときに上記後に言えば、このような共通がLRU(最低使用頻度)、FIFO(先入れ先出し)、LFU(最低使用頻度)、SOFT(ソフト参照)、貧弱(弱い参照)のように、明確な戦略を必要としますそして他の戦略。

4.有効期限

パージ・ポリシーを使用することに加えて、一般的なローカルキャッシュの有効期限の設定があるでしょう、などのRedisは、各キーセットに有効期限を与えることができますので、直接削除するとき、それは明確な戦略+ダブル保証を使用して、その有効期限、有効期限に達した後、

5.スレッドセーフ

Redisのは、シングルスレッドプロセスとして直接使用するので、何のスレッド安全性の問題が存在していない、と我々は今、スレッドが安全性の問題を無視することはできませんので、多くの場合、同時に複数のスレッドによってアクセス可能なローカルキャッシュを提供し;およびスレッドの安全性の問題はないはず確実にするために、ユーザーに投げ。

6.簡潔なインターフェース

外部インタフェースの愚か者が必要であり、ユーザのためにキャッシュを使用する負担が、喜びはありません。一般的なGET、PUT、削除を提供し、クリアする、のgetSizeメソッドが可能。

7.永続的

実際には、これは必要ではなく、ニーズ永続キャッシュされたデータを参照する必要があります。ehcacheをサポート持続性、永続性とグアバなどのローカルキャッシュは機能しません;ないが、永続的な機能としてキャッシュを分散memcachedをされるのRedis永続的な機能;

8.ブロッキング機構

他のスレッドではなく、データベースを打つ、充填されて、この要素をお待ちしておりますので、MyBatisのソースを見ると、二次キャッシュは、キャッシュにない要素は、それがキャッシュキーのロックを設定したときにすることを阻止手段アイデンティティを提供します。

実際には、我々は時間のかかる大きな成果の量とその上を計算するために、クエリのデータベース、外部インタフェースを呼び出すように、生成するために、キャッシュされたデータのキャッシュされたターゲットを使用し、この時間は、複数のスレッドが同時に呼び出した場合の結果がnullで取得するメソッドを取得します再度、時間のかかる計算を実行するために、各スレッドは、実際には、リソースの無駄です。

唯一つのスレッドを実行することで、他のスレッドが一度計算待ちの最良の方法は十分にある。しかし、この機能は、基本的には非常に少ないが、このローカルキャッシュ機能を持っている、に対処するために、ユーザに引き渡されます。

どのように達成するために

我々が考慮しなければならないローカルキャッシュを実現するための場所へのより一般的な紹介はもちろん、アカウントの他のポイントに入れない場合があります。、どのようなアイデアに焦点を実装する方法である必要があり、各点について、以下を見ていき、

1.データ構造

最も一般的なのは、このようなグアバ使用のConcurrentHashMap、ehcacheをも使用されるような、直接店舗に地図を使用してローカルキャッシュ、あるのConcurrentHashMap 、店舗へのMyBatisの二次キャッシュ使用のHashMap:

Map<Object, Object> cache = new ConcurrentHashMap<Object, Object>()

MyBatisの使用HashMapのはスレッドセーフではありません自体、あなたがスレッドの安全性を確保するためにパッケージ化するためSynchronizedCacheを使用して、内側から見ることができるように。

もちろんこれは、インターフェイスが非常に豊富なRedisのは、外部の追加ハッシュを提供される主な理由であると、もちろん、店に地図を使用することに加えて、また、リスト、整数、ジャンプや辞書を梱包ダブルエンドRedisのリンクリストを使用する、などの他のデータ構造を格納するために使用することができます関数のセットを注文したリスト、セットは、あります。

2.オブジェクトのキャップ

一般的には、ローカルキャッシュの属性、キャッシュは、一般に、1024のようなデフォルト値を有することになる、デフォルトの場合には、ユーザが指定されていない指定された、キャッシュされたデータは、指定された最大値に達したときに、そのキャッシュから関連するポリシーの削除冗長データの必要性を明確な戦略は次のように紹介して関与しました。

3.明確な戦略

次のような嵌合キャップパージポリシーシナリオ、使用した後、LRU(最も最近使用された)を、FIFO(先入れ先出し)、LFUは、SOFT(ソフト参照)弱い(弱参照)(最低使用)
LRU最近最小ログ。使用される略語は、最近最も使用されていないオブジェクトを削除するには、最大時間を使用し、のLinkedHashMapは、一般的な使用を実現するために、多くのローカルキャッシュ戦略は、デフォルトで使用され、
FIFO:FIFOを、オブジェクトのキャッシュにそれらを除去するために、 ;通常、キューキューを使用して実装;
LFU:少なくとも頻繁に使用される略語は、おそらく最低使用の意味で、LRUは、のようなビット;により、段差解消のポイントは、LRUはアクセス時間に基づいており、そしてLFUは訪問の数に基づいているルールHashMapのと達成するために、訪問の数を記録し、
ソフト:ソフト参照は、ガベージコレクタの状態とソフトに基づいてオブジェクトを削除するルールを引用し、SoftReferenceは、一般的な使用を達成するために、
弱い:弱い、より積極的にガベージコレクタ状態に基づいて参照と弱参照のルールは、オブジェクトを削除します;一般的な使用を達成するために弱い参照。

4.有効期限

パッシブとアクティブは削除削除;:二つの方法で、共通の期限切れのデータ削除ポリシーを、自動的に指定した時間後に削除され、キャッシュされたデータの有効期限を設定します

削除パッシブ:GET / PUT操作は、削除期限が切れた場合、現在のキーが期限切れになったかどうかを確認するには、次のコードに似ているように起こっているたびに:

if (System.currentTimeMillis() - lastClear > clearInterval) {
  clear();
}

削除するためのイニシアチブは:特別なジョブは、データの有効期限が切れているかどうかを確認するために定期的にバックグラウンドであり、実際には効果的に風邪のデータを扱うことができ、削除期限が切れ;

マイクロチャンネルの公共の番号にフォーカス:インターネットの建築家は、バックグラウンドの回答に:8、私はソート乾燥品を得ることができます。

5.スレッドセーフ

そのようなハッシュマップのConcurrentHashMapの代わりに使用するようなスレッドセーフなクラスが格納されたデータを、使用しようと、または対応する同期タイプを提供し、そのようなMyBatisのはSynchronizedCacheを提供しました。

public synchronized void putObject(Object key, Object object) {
  ...省略...
}

@Override
public synchronized Object getObject(Object key) {
  ...省略...
}

6.簡潔なインターフェース

共通GET、PUT、削除を提供し、クリアする、のgetSizeメソッドをすることができ、例えばキャッシュ・インタフェースをMyBatisの:

public interface Cache {
  String getId();
  void putObject(Object key, Object value);
  Object getObject(Object key);
  Object removeObject(Object key);
  void clear();
  int getSize();
  ReadWriteLock getReadWriteLock();
}

提供キャッシュインターフェースグアバを見て、それはまた、比較的簡単です。

public interface Cache<K, V> {
  V getIfPresent(@CompatibleWith("K") Object key);
  V get(K key, Callable<? extends V> loader) throws ExecutionException;
  ImmutableMap<K, V> getAllPresent(Iterable<?> keys);
  void put(K key, V value);
  void putAll(Map<? extends K, ? extends V> m);
  void invalidate(@CompatibleWith("K") Object key);
  void invalidateAll(Iterable<?> keys);
  void invalidateAll();
  long size();
  CacheStats stats();
  ConcurrentMap<K, V> asMap();
  void cleanUp();
}

7.永続的

;データファイルを再びロードすることができた後に永続利点は、同様の熱負荷の影響を果たしたように、再起動されehcacheを、永続ディスクキャッシュ機能を提供するかどうか、例えば、キャッシュされたデータは、.DATAファイルに格納されています。

diskPersistent="false" //是否持久化磁盘缓存

Redisのは限界に永続的な機能であり、そしてゆっくりとビットデータベース等; AOFとRDBの永続的な方法の2種類を提供することと、当然のことながら、多くの場合、2つの方法でと併せて使用することができます。

8.ブロッキング機構

見る前に、これを行うにはBlockingCacheでMyBatisのを見てすることに加え<< Javaの並行プログラミング>>本当の完璧なキャッシュを達成した時、大体次のコード:

public class Memoizerl<A, V> implements Computable<A, V> {
    private final Map<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizerl(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V compute(A arg) throws InterruptedException, ExecutionException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> eval = new Callable<V>() {
                    @Override
                    public V call() throws Exception {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                    f = ft;
                    ft.run();
                }
                try {
                    return f.get();
                } catch (CancellationException e) {
                    cache.remove(arg, f);
                }
            }
        }
    }
}

計算方法を計算するので、ここでは、非常に時間がかかり、キャッシュされた計算の結果であるが、問題は2つのスレッドが同時にこの方法を入力した場合、一度だけ数えていることを確実にする方法であり、ここで最も中心的な場所は、ConcurrentHashMapののputIfAbsentメソッドを使用することですのみFutureTaskを書きながら、

概要

一般的に、ローカルキャッシュを設計するために導入されたこの論文は、考慮すべきポイントは何ですか:データ構造、天井オブジェクト、明確な戦略、有効期限、スレッドセーフ、メカニズムを遮断する、実用的なインターフェース、持続するかどうか、もちろん他の考慮点が存在する必要があり、追加してください。

あなたも好きかもしれ

1、GitHubのは3.2ワットを主演しました!最も完全な歴史と技術者がマニュアルインタビュー!FackBoo開始と概要

2、良い建築家になるためにどのように?

3、バックエンド技術スタックスタートアップ企業を構築するためにゼロから始めます

4、プログラマは一般的にどのようなプラットフォームからプライベートライブを取ることができますか?

5、カット、120日、残念ながら中小企業への無意味な結果を仕事を見つけるではなくなるように37歳のプログラマー...

図6は、第一回の露光のために、ビジネスの実践を構築するために台湾に低下します

7、彼らの運命、作業プログラムGoogleの元、湖南省の姉妹のインスピレーションを与える話に組立ラインの労働者から10年を受け入れません

8、15、図16は、効率的な違いを理解して大騒ぎ!

リリース8元の記事 ウォン称賛17 ビュー60000 +

おすすめ

転載: blog.csdn.net/emprere/article/details/104322833