8

次のようにキー/値を更新および取得するときに、ServiceStackRedisのAcquireLockメソッドを使用しています。

public virtual void Set(string key, T entity)
{
    using (var client = ClientManager.GetClient())
    {
        using (client.AcquireLock(key + ":locked", DefaultLockingTimeout, DefaultLockExpire))
        {
            client.Set(key, entity);
        }
    }
}

AcqurieLockメソッドを拡張して、ロックキーの有効期限の追加パラメーターを受け入れます。だから私はAcquireLockが必要かどうか疑問に思っていますか?私のクラスは、Get <>、GetAll <>、ExpireAt、SetAll<>などのすべての操作でAcquireLockを使用します。

しかし、このアプローチは常に機能するとは限りません。たとえば、ロック内の操作で例外がスローされた場合、キーはロックされたままになります。この状況では、「ロックされた」キーを期限切れにするために、AcquireLockメソッドにDefaultLockExpireパラメーターを追加しました。

より良い解決策はありますか、またはマルチスレッドプログラミングで「ロック」ブロックのようなロックを取得する必要があるのはいつですか。

4

3 に答える 3

11

Real Billの回答が述べているように、Redis自体にロックは必要ありません。ロックに関してServiceStackクライアントが提供するのは、Redisではなく、アプリケーション用です。C#アプリケーションではlock(obj)、何かが同時に発生しないようにローカルでロックできます(一度に1つのスレッドのみがロックされたセクションにアクセスできます)が、これはWebサーバーが1つある場合にのみ機能します。何かが同時に発生するのを防ぎたい場合は、Webサーバーの外部にあるロックメカニズムが必要です。Redisはこれにぴったりです。

顧客がすでにショッピングカートを持っているかどうかをチェックし、持っていない場合は作成する場合があります。チェックしてから作成するまでの間に、カートが存在しないことを別のリクエストが見つけて、カートの作成に進む可能性がある場合があります。これはロックの古典的なケースですがlock、リクエストがまったく異なるWebサーバーから到着した可能性があるため、ここでは単純なものは機能しません。そのため、このために、ServiceStack Redisクライアント(ある程度の抽象化を含む)を使用してRedisを使用してロックし、一度に1つのリクエストのみが「カートの作成」セクションに入るのを許可します。

したがって、実際の質問に答えるには、いいえ、Redisに値を取得/設定するためのロックは必要ありません。

于 2013-03-02T22:40:00.950 に答える
3

get/set操作にはロックを使用しません。Redisはこれらのアクションをアトミックに実行するため、設定または取得時に「下で変更」される可能性はありません。私は、何百ものクライアントが同時に値を更新/操作し、それらの操作(特に期限切れ)を実行するためにロックを必要としないシステムを構築しました。

Service Stack redisがどのようにロックを実装しているかわからないので、なぜ失敗するのかわかりません。ただし、データ操作のためにRedis側で真のロックが必要ないことを考えると、信頼できるかどうかはわかりません。Redisはシングルスレッドであるため、そこでロックしても意味がありません。

値を取得し、それに基づいて操作し、しばらくしてから値を変更できない複雑な操作を行っている場合は、http://redis.ioを読んで成長させることをお勧めします。 / topics / transactionsを使用して、必要なものがRedisに適しているかどうか、問題を排除するためにコードをリファクタリングする必要があるかどうか、または少なくともそれを行うためのより良い方法を見つけるかどうかを確認します。

たとえば、SETNXは必要なものを取得するために必要なルートかもしれませんが、詳細がなければ、うまくいくとは言えません。

于 2013-03-02T19:45:38.183 に答える
1

@JulianRが言うように、ServiceStack.Redisでのロックは、アプリケーションレベルの分散ロック(つまり、分散ファイルシステムでDBまたは空の.lockファイルを使用して置き換える)専用であり、他のプロセスで他のServiceStack.Redisクライアントに対してのみ機能します。ロックを取得するための同じキー/API。

これらはすべてアトミックであるため、通常のRedis操作ではこれを行う必要はありません。Redisトランザクション内でそれらを組み合わせるよりも、redis操作の組み合わせがアトミックに行われるようにしたい場合、またはサーバー側のLuaスクリプト内でそれらを実行できる場合は、どちらもバッチ操作のアトミック実行を許可します。

于 2013-03-03T01:46:21.087 に答える