我正在使用以下单例类为我的一项个人开发工作从Azure Redis缓存获取/设置/删除值。
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;
}
}
}
}
在这里,我在将值插入数据库或从数据库中删除值时使用了锁。但是从下面的帖子中,我知道Redis是一个单线程数据库,并且所有操作都是原子的-
Is there any lock mechanism in Azure Redis Cache while updating an item?
因此,我相信我使用的锁是不必要的,并且可能导致某些性能问题。如果我错了,请纠正我。我在
Application_Start
事件中设置了变量(端点,密码等)。希望能有所帮助。
最佳答案
您可以了解如何在Redis中使用WATCH
。 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();
关于c# - 从Azure Redis缓存插入或删除值时,是否需要在代码级别进行同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62337919/