2015-02-11 58 views
2

最近我一直有服務堆棧的一些問題 - 我已經發現它似乎是由多個線程引起的,每個線程都連接到Redis來執行操作。如果我一次只運行一個線程,它可以正常工作,但是我還會遇到幾個不同的錯誤。我在其他地方看到最好使用PooledRedisClientManager並調用GetClient,但它仍然給我帶來麻煩。我只想知道Redis是否是線程安全的,並且您可以採取哪些步驟來確保它不會在併發線程上中斷。線程安全的服務堆棧Redis連接

我已經創建了一個專門用於測試的程序,下面是它。

class Program 
{ 
    static IRedisClient redis = new PooledRedisClientManager(ConfigurationManager.AppSettings["RedisServer"]).GetClient(); 

    static void Main(string[] args) 
    { 
     LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(10); 

     List<Task> tasks = new List<Task>(); 

     // Create a TaskFactory and pass it our custom scheduler. 
     TaskFactory factory = new TaskFactory(scheduler); 

     for (int i = 0; i < 100; i++) 
     { 
      Task task = factory.StartNew(() => AsyncMethod1(i)); 
      tasks.Add(task); 
     } 

     Task.WaitAll(tasks.ToArray()); 

     for (int i = 0; i < 100; i++) 
     { 
      Task task2 = factory.StartNew(() => AsyncMethod2(i)); 
      tasks.Add(task2); 
     } 

     Task.WaitAll(tasks.ToArray()); 

     Console.ReadKey(); 
    } 

    public static void AsyncMethod1(int i) 
    { 
     redis.SetEntry("RedisTest" + i, "TestValue" + i); 
    } 

    public static void AsyncMethod2(int i) 
    { 
     List<string> result = redis.ScanAllKeys("RedisTest" + i).ToList(); 
     if (result[0] == "RedisTest" + i) Console.Out.Write("Success! " + result[0] + "\n"); 
     else Console.Out.Write("Failure! " + result[0] + " :(\n"); 
    } 
} 

回答

3

不應該在多個線程之間共享RedisClient實例,因爲它們不是ThreadSafe。相反,您應該從線程安全的Redis客戶端管理器解決並釋放它們 - also mentioned in the docs

+1

非常感謝。我現在正在使用RedisManagerPool併爲每個線程獲取客戶端。沒問題。我也遇到了麻煩,因爲我吮吸多線程 - 我需要傳遞局部變量,當我沒有得到100個負載時。 無論如何,這很好地解決了我的問題。 順便說一句,感謝ServiceStack本身 - 一項令人印象深刻的工作。 – PointlessSpike 2015-02-11 10:03:58