在从azure redis缓存中插入或删除值时,是否需要在代码级别进行同步?

2cmtqfgy  于 2021-06-09  发布在  Redis
关注(0)|答案(1)|浏览(359)

我正在使用下面的singleton类为我的一个个人开发工作从azureredis缓存中获取/设置/删除值。

using StackExchange.Redis;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace PoC
{
    public sealed class CacheManager
    {
        public static object mutex = new object();

        public static string EndPoint { get; set; }
        public static string Password { get; set; }
        public static bool UseSsl { get; set; }
        public static int ConnectRetry { get; set; }
        public static int KeepAlive { get; set; }
        public static int ConnectTimeout { get; set; }

        private static ConfigurationOptions ConfigurationOptions;

        private static readonly CacheManager instance = new CacheManager();

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static CacheManager() { }

        private CacheManager()
        {
            ConfigurationOptions = new ConfigurationOptions
            {
                Password = Password,
                Ssl = UseSsl,
                AbortOnConnectFail = false,
                ConnectRetry = ConnectRetry,
                KeepAlive = KeepAlive,
                ConnectTimeout = ConnectTimeout
            };
        }

        public static CacheManager Instance { get { return instance; } }

        public static string ConnectionString { get; set; }

        Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
        {
            return ConnectionMultiplexer.Connect(ConfigurationOptions);
        });

        IDatabase Database => lazyConnection.Value.GetDatabase();

        public void Set<T>(string key, T value)
        {
            lock (mutex)
            {
                Database.StringSet(key, ToByteArray(value));
            }
        }

        public T Get<T>(string key)
        {
            T result = FromByteArray<T>(Database.StringGet(key));
            return result;
        }

        public bool Remove(string key)
        {
            lock (mutex)
            {
                var removed = Database.KeyDelete(key);
                return removed;
            }
        }

        public byte[] ToByteArray<T>(T obj)
        {
            if (obj == null)
                return null;
            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        public T FromByteArray<T>(byte[] data)
        {
            if (data == null)
                return default(T);
            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream(data))
            {
                object obj = bf.Deserialize(ms);
                return (T)obj;
            }
        }
    }
}

在这里,我在将值插入数据库或从数据库中删除值时使用了lock。但是从下面的文章中我知道redis是一个单线程数据库,所有的操作都是原子的-
更新项目时,azure redis缓存中是否有任何锁定机制?
所以我认为我使用的锁是不必要的,可能会导致一些性能问题。如果我错了,请纠正我。我正在设置变量(端点、密码等)一次 Application_Start 事件。谢谢你的帮助。

u59ebvdq

u59ebvdq1#

你可以学习如何使用 WATCH 在redis。https://stackexchange.github.io/stackexchange.redis/transactions.html

WATCH key  
isFieldExists = HEXISTS key, field  
if isFieldExists is 1  
MULTI  
HSET key, field, value  
EXEC  
else  
UNWATCH  
return isFieldExists

例子:

var newId = CreateNewId();
var tran = db.CreateTransaction();
tran.AddCondition(Condition.HashNotExists(custKey, "UniqueID"));
tran.HashSetAsync(custKey, "UniqueID", newId);
bool committed = tran.Execute();

相关问题