如何解決hangfire使用redis儲存時,如果採用了prefix報“Key has MOVED from Endpoint”的錯
當我們使用redis作為hangfire的儲存時,如果使用了下面紅色字型的配置
GlobalConfiguration.Configuration.UseRedisStorage(@"192.168.0.3:7002",
new Hangfire.Redis.RedisStorageOptions
{
Prefix = "{hangfire-A}:",
// Db =2
});
app.UseHangfireDashboard();
則你很有可能會看到下面的錯誤
Key has MOVED from Endpoint 127.0.0.1:7001 and hashslot 6991 but CommandFlags.NoRedirect was specified - redirect not followed for MGET. IOCP: (Busy=0,Free=1000,Min=4,Max=1000), WORKER: (Busy=1,Free=32766,Min=4,Max=32767), Local-CPU: n/a
在Hangfire的官網,對這種現象有一個說明,但常常被我們忽略掉。具體說明如下
Redis Cluster support ofollow,noindex" target="_blank">¶
You can use a single endpoint to connect to a Redis cluster, Hangfire will detect other instances automatically by querying the node configuration. However, it’s better to pass multiple endpoints in order to mitigate connectivity issues, when some of endpoints aren’t available, e.g. during the failover process.
Since Hangfire requires transactions, and Redis doesn’t support ones that span multiple hash slots, you also need to configure the prefix to assign it to the same hash tag:
GlobalConfiguration.Configuration.UseRedisStorage(
"localhost:6379,localhost:6380,localhost:6381",
new RedisStorageOptions { Prefix = "{hangfire-1}:" });
This will bind all the keys to a single Redis instance. To be able to fully utilize your Redis cluster, consider using multiple JobStorage instances and leveraging some load-balancing technique (round-robin is enough for the most cases). To do so, pick different hash tags for different storages and ensure they are using hash slots that live on different masters by using commands CLUSTER NODES and CLUSTER KEYSLOT.
來自 < http://docs.hangfire.io/en/latest/configuration/using-redis.html >
文章中明確說明,這種操作會讓hangfire的key被繫結到一個單獨的redis例項上。這個例項就是我們需要配置的連線地址(注:這裡如果配置叢集的地址,一樣會出錯,只能配置繫結的那個地址)。但怎麼找到這個地址呢?
首先,我們使用CLUSTER NODES命令檢視每個節點的hash slots分佈情況,效果如下:
上圖顯示了每個節點的分佈情況,然後我們需要使用CLUSTER KEYSLOT 命令找出我們需要做為key的值會hash成什麼值,然後找到對應值分配 的伺服器。 如上“hangfire-A" hash後對應的slor是16173, 對應的是7200埠對應的節點。
所以在程式碼中,我們配置伺服器地址時就要使用這個埠。具體如下:
GlobalConfiguration.Configuration.UseRedisStorage(@" 192.168.0.3:7002 ",
new Hangfire.Redis.RedisStorageOptions
{
Prefix = "{hangfire-A}:",
// Db =2
});
然後我們的服務就可以正常起動了