Redis发布订阅无法正常工作

时间:2018-01-10 10:57:15

标签: c# publish-subscribe stackexchange.redis

我无法从pub / sub StackExchange.Redis功能中获益。 这是我的代码。

控制台应用

using StackExchange.Redis;
using System;
using System.Data;

namespace RedisHashSets
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Prepare Data

            var exampleData = new DataTable();
            exampleData.Columns.Add("session_guid", typeof(String));
            exampleData.Columns.Add("status_code", typeof(String));
            exampleData.Columns.Add("date_open", typeof(DateTime));
            exampleData.Columns.Add("date_expiry", typeof(DateTime));
            exampleData.Columns.Add("extra_id", typeof(long));
            exampleData.Columns.Add("current_real_balance", typeof(Decimal));

            DataRow row = exampleData.NewRow();
            row[0] = Guid.NewGuid();
            row[1] = 1;
            row[2] = DateTime.Now;
            row[3] = DateTime.Now.AddMinutes(30);
            row[4] = 44567;
            row[5] = 10.34;

            exampleData.Rows.Add(row);

            #endregion

            var redisClient = RedisProvider.Instance;
            string guid = Guid.NewGuid().ToString();

            // Add an Entry
            redisClient.Set(guid, RedisDataMapper.GetHashSet(exampleData)[0]);

            // Modify an Entry
            HashEntry entry = new HashEntry("exrta_id", 338349);
            redisClient.Set(guid, entry);

            // Get an Entry
            HashSet val = redisClient.Get(guid);

            //Invalidate the key
            redisClient.redisPubSub.Publish("InvalidateBalances", guid);
        }
    }
}

Redis Singletone客户端

namespace RedisHashSets
{
    /// <summary>
    /// Provide access to the Redis capabilites used to store sesion. Used as a Singleton
    /// </summary>
    public class RedisProvider
    {
        #region Private Fields

        private readonly static Lazy<RedisProvider> lazyObj = new Lazy<RedisProvider>(() => new RedisProvider());
        private ConnectionMultiplexer redisClient;
        private IDatabase redisDatabase;
        private IServer currentServer;
        private EndPoint[] endPoints;

        #endregion  Private Fields

        #region Public Fields

        public static RedisProvider Instance { get { return lazyObj.Value; } }
        public ISubscriber redisPubSub;

        public bool IsRedisEnableByConfig { get; set; }

        #endregion Public Fields

        #region Public Methods

        private RedisProvider()
        {
            if (!lazyObj.IsValueCreated)
            {
                var conf = RedisConfig.GetConfiguration();
                if (conf is null)
                {
                    IsRedisEnableByConfig = false;
                }
                else
                {
                    IsRedisEnableByConfig = true;
                    redisClient = ConnectionMultiplexer.Connect(conf);
                    redisDatabase = redisClient.GetDatabase(0);
                    endPoints = redisClient.GetEndPoints();
                    currentServer = redisClient.GetServer(endPoints.First());

                    ManageSubscriber();
                }
            }
        }

        private void ManageSubscriber()
        {
            redisPubSub = redisClient.GetSubscriber();
            redisPubSub.Subscribe(new RedisChannel("InvalidateBalances", RedisChannel.PatternMode.Pattern), (channel, message) => MessageAction(message));
        }

        private void MessageAction(RedisValue message)
        {
            HashEntry updatedEntry = new HashEntry(HashSet.IsUpdatedFlag, false);
            Set(message, updatedEntry);
        }

        public void Set(string key, HashSet value)
        {
            redisDatabase.HashSet(key, value.Entries);
            Set(key, value.IsUpdated);
        }

        public void Set(string key, HashEntry value)
        {
            redisDatabase.HashSet(key, value.Name, value.Value);
        }

        /// <summary>
        /// Get a value from Redis.
        /// </summary>
        /// <param name="key">The key of the vaule to retrive</param>
        /// <returns>Cast the value and retrurn a strongly typed object</returns>
        public HashSet Get(string key)
        {
            HashEntry[] value = redisDatabase.HashGetAll(key);
            return new HashSet(value.Length) { Entries = value };
        }

        /// <summary>
        /// Check if a value is in stored or not expired. Time consuming. Use onky if necessary.
        /// </summary>
        /// <param name="key">The key of the value</param>
        public bool IsInCache(string key)
        {
            return redisDatabase.KeyExists(key);
        }

        /// <summary>
        /// Remove a value from the cache.
        /// </summary>
        /// <param name="key">The key to remove</param>
        public bool Remove(string key)
        {
            return redisDatabase.KeyDelete(key);
        }

        /// <summary>
        /// Return the number of active keys stored inside the redis databaase.
        /// </summary>
        public int GetKeysNumber()
        {
            var retVal = 0;
            retVal = currentServer.Keys().Count();
            return retVal;
        }

        /// <summary>
        /// Return an enumerable of all the Keys.
        /// </summary>
        public IEnumerable<string> GetKeys()
        {
            return currentServer.Keys().Select(k => k.ToString());
        }

        #endregion
    }
}

当我发布消息时,订阅者不会抓住它。 你能救我吗?

1 个答案:

答案 0 :(得分:2)

尝试检查configuration。 您的代码对我来说是“localhost”作为连接字符串,即

 redisClient = ConnectionMultiplexer.Connect("localhost");

这是您在控制台应用中为我工作的代码的最小版本。

using StackExchange.Redis;
using System;
using System.Linq;
using System.Net;

namespace RedisHashSets
{
    class Program
    {
        static void Main(string[] args)
        {
            var redisClient = RedisProvider.Instance;
            for (int i = 0; i < 10; i++)
            {
                //Thread.Sleep(100);
                redisClient.redisPubSub.Publish("InvalidateBalances", Guid.NewGuid().ToString());
            }
            Console.ReadLine();
        }
    }


    public class RedisProvider
    {
        #region Private Fields

        private static readonly Lazy<RedisProvider> lazyObj = new Lazy<RedisProvider>(() => new RedisProvider());
        private ConnectionMultiplexer redisClient;
        private IDatabase redisDatabase;
        private IServer currentServer;
        private EndPoint[] endPoints;


        public static RedisProvider Instance => lazyObj.Value;
        public ISubscriber redisPubSub;

        public bool IsRedisEnableByConfig { get; set; }

        private RedisProvider()
        {
            if (!lazyObj.IsValueCreated)
            {
                IsRedisEnableByConfig = true;
                redisClient = ConnectionMultiplexer.Connect("localhost");
                endPoints = redisClient.GetEndPoints();

                currentServer = redisClient.GetServer(endPoints.First());
                ManageSubscriber();
            } 
        }

        private void ManageSubscriber()
        {
            redisPubSub = redisClient.GetSubscriber();
            redisPubSub.Subscribe(new RedisChannel("InvalidateBalances", RedisChannel.PatternMode.Pattern), (channel, message) => MessageAction(message));
        }

        private void MessageAction(RedisValue message)
        {
            Console.WriteLine("msg arrived: " + message);
        }

        #endregion
    }
}

另请注意您的代码示例minimal complete and verifiable.