Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍
目录
- 简介
- 安装
- 入门指令
- GUI 工具
- C# 驱动介绍
简介
ANSI C 编写,开源,基于内存,可持久化,一个键值对的数据库,用法简单。
支持的类型:字符串、散列、列表、集合和有序集合。
因为 Redis 默认将所有数据都存储到内存中,并且内存的读写速度远远高于硬盘,因此,比其他基于硬盘存储的数据库在性能上体现的优势非常明显。不过这样也引发了一个数据安全性的问题,程序异常或退出后数据会出现丢失的情形,现在新的版本已经提供了数据持久化(RDB + AOF)的支持,即可以将内存中的数据异步写入到硬盘上,同时不会影响其它功能的运行。
redis 可以为每个键设置生存时间,到期自动删除,也就是说可以作为缓存系统(这也是企业主要的运用场景)进行使用。
相对于 Memcached,简单的说:Redis 单线程模型,Memcached 支持多线程,但 Redis 支持的功能和数据类型更多,更简单易用,并且 redis 的性能在绝大部分场合下都不会成为系统瓶颈,不过在多核服务器上使用的情况下,理论上 Memcached 比 redis 性能更高。所以,在新项目中,建议使用 redis 代替 Memcached。
Redis 还可以限定数据占用的最大内存空间,在数据达到空间限制后按一定规则自动淘汰不需要的键;也支持构建高性能的队列(不过很多企业会选择第三方的 MQ,如:RabbitMQ)。
安装
它的约定次版本号(即第一个小数点后的数字)为偶数的版本是稳定版(如 v2.8,v3.0)。
为了减少学习成本,我们直接使用 windows 版本的就可以,想学习 Linux 部署的,先搜搜别人的文章吧。
redis-windows-3.0(搜索了一下,最新的正式版是 3.2):下载地址
文件简单说明:
入门指令
1.启动 CMD:
$ redis-server $ redis-server --port //自定义端口
2.停止:
$ redis-cli SHUTDOWN
3.PING 命令:
测试与 redis 的连接是否正常,正常返回 PONG
$ redis-cli PING
GUI 工具
Redis Client:一个基于Java SWT 和 Jedis 编写的 redis 客户端 GUI 工具。可从 https://github.com/caoxinyu/RedisClient 下载。
从图可知,redis 包含了 16 个数据库。上面的每个数据库默认从 0 开始的递增数字命名。
因为该程序打包后的压缩包 >10 M,无法上传到 cnblogs,如有需要的童鞋请加群在群文件中下载压缩包。
补充一下园友(心态要好)推荐的其它 GUI 工具 RedisDeskTopManager:https://redisdesktop.com/download。
C# 驱动
之前在 《使用 StackExchange.Redis 封装属于自己的 RedisHelper》 曾经发布了一篇使用 StackExchange.Redis 进行了简单封装的 RedisHelper,你可以选择查看之前的文章,从中借鉴一些思想或者给出一些建议。
这里是更新后的 Helper 代码(直接展开即可),代码的后续更新在 GitHub 上。
#region using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading.Tasks;
using StackExchange.Redis; #endregion namespace Wen.Helpers.Common.Redis
{
/// <summary>
/// Redis 助手
/// </summary>
public class RedisHelper
{
/// <summary>
/// 获取 Redis 连接对象
/// </summary>
/// <returns></returns>
public IConnectionMultiplexer GetConnectionRedisMultiplexer()
{
if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
lock (Locker)
{
if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
} return _connMultiplexer;
} #region 其它 public ITransaction GetTransaction()
{
return _db.CreateTransaction();
} #endregion 其它 #region private field /// <summary>
/// 连接字符串
/// </summary>
private static readonly string ConnectionString; /// <summary>
/// redis 连接对象
/// </summary>
private static IConnectionMultiplexer _connMultiplexer; /// <summary>
/// 默认的 Key 值(用来当作 RedisKey 的前缀)
/// </summary>
private static readonly string DefaultKey; /// <summary>
/// 锁
/// </summary>
private static readonly object Locker = new object(); /// <summary>
/// 数据库
/// </summary>
private readonly IDatabase _db; #endregion private field #region 构造函数 static RedisHelper()
{
ConnectionString = ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString;
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
DefaultKey = ConfigurationManager.AppSettings["Redis.DefaultKey"];
AddRegisterEvent();
} public RedisHelper(int db = )
{
_db = _connMultiplexer.GetDatabase(db);
} #endregion 构造函数 #region String 操作 /// <summary>
/// 设置 key 并保存字符串(如果 key 已存在,则覆盖值)
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet(string key, string value, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
return _db.StringSet(key, value, expiry);
} /// <summary>
/// 保存多个 Key-value
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public bool StringSet(IEnumerable<KeyValuePair<string, string>> keyValuePairs)
{
var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return _db.StringSet(pairs.ToArray());
} /// <summary>
/// 获取字符串
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public string StringGet(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.StringGet(redisKey);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet<T>(string key, T value, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
var json = Serialize(value); return _db.StringSet(key, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="key"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public T StringGet<T>(string key, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
return Deserialize<T>(_db.StringGet(key));
} /// <summary>
/// 在指定 key 处实现增量的递增,如果该键不存在,则在执行前将其设置为 0
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public double StringIncrement(string key, double value = )
{
key = AddKeyPrefix(key);
return _db.StringIncrement(key, value);
} /// <summary>
/// 在指定 key 处实现增量的递减,如果该键不存在,则在执行前将其设置为 0
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public double StringDecrement(string key, double value = )
{
key = AddKeyPrefix(key);
return _db.StringDecrement(key, value);
} #region async /// <summary>
/// 保存一个字符串值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
return await _db.StringSetAsync(key, value, expiry);
} /// <summary>
/// 保存一组字符串值
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(IEnumerable<KeyValuePair<string, string>> keyValuePairs)
{
var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return await _db.StringSetAsync(pairs.ToArray());
} /// <summary>
/// 获取单个值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<string> StringGetAsync(string key, string value, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
return await _db.StringGetAsync(key);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync<T>(string key, T value, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
var json = Serialize(value);
return await _db.StringSetAsync(key, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="key"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<T> StringGetAsync<T>(string key, TimeSpan? expiry = null)
{
key = AddKeyPrefix(key);
return Deserialize<T>(await _db.StringGetAsync(key));
} /// <summary>
/// 在指定 key 处实现增量的递增,如果该键不存在,则在执行前将其设置为 0
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<double> StringIncrementAsync(string key, double value = )
{
key = AddKeyPrefix(key);
return await _db.StringIncrementAsync(key, value);
} /// <summary>
/// 在指定 key 处实现增量的递减,如果该键不存在,则在执行前将其设置为 0
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<double> StringDecrementAsync(string key, double value = )
{
key = AddKeyPrefix(key);
return await _db.StringDecrementAsync(key, value);
} #endregion async #endregion String 操作 #region Hash 操作 /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashExists(string key, string hashField)
{
key = AddKeyPrefix(key);
return _db.HashExists(key, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashDelete(string key, string hashField)
{
key = AddKeyPrefix(key);
return _db.HashDelete(key, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="key"></param>
/// <param name="hashFields"></param>
/// <returns></returns>
public long HashDelete(string key, IEnumerable<string> hashFields)
{
key = AddKeyPrefix(key);
var fields = hashFields.Select(x => (RedisValue) x); return _db.HashDelete(key, fields.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HashSet(string key, string hashField, string value)
{
key = AddKeyPrefix(key);
return _db.HashSet(key, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="key"></param>
/// <param name="hashFields"></param>
public void HashSet(string key, IEnumerable<KeyValuePair<string, string>> hashFields)
{
key = AddKeyPrefix(key);
var entries = hashFields.Select(x => new HashEntry(x.Key, x.Value)); _db.HashSet(key, entries.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public string HashGet(string key, string hashField)
{
key = AddKeyPrefix(key);
return _db.HashGet(key, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="key"></param>
/// <param name="hashFields"></param>
/// <returns></returns>
public IEnumerable<string> HashGet(string key, IEnumerable<string> hashFields)
{
key = AddKeyPrefix(key);
var fields = hashFields.Select(x => (RedisValue) x); return ConvertStrings(_db.HashGet(key, fields.ToArray()));
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public IEnumerable<string> HashKeys(string key)
{
key = AddKeyPrefix(key);
return ConvertStrings(_db.HashKeys(key));
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public IEnumerable<string> HashValues(string key)
{
key = AddKeyPrefix(key);
return ConvertStrings(_db.HashValues(key));
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public bool HashSet<T>(string key, string hashField, T redisValue)
{
key = AddKeyPrefix(key);
var json = Serialize(redisValue); return _db.HashSet(key, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public T HashGet<T>(string key, string hashField)
{
key = AddKeyPrefix(key);
return Deserialize<T>(_db.HashGet(key, hashField));
} /// <summary>
/// 指定键递增
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public double HashIncrement(string key, string hashField, double value = )
{
key = AddKeyPrefix(key);
return _db.HashIncrement(key, hashField, value);
} /// <summary>
/// 指定键递减
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public double HashDecrement(string key, string hashField, double value = )
{
key = AddKeyPrefix(key);
return _db.HashDecrement(key, hashField, value);
} #region async /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashExistsAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashExistsAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashDeleteAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashDeleteAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
/// <returns></returns>
public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<string> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
var fields = hashFields.Select(x => (RedisValue) x); return await _db.HashDeleteAsync(redisKey, fields.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync(string redisKey, string hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashSetAsync(redisKey, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
public async Task HashSetAsync(string redisKey, IEnumerable<KeyValuePair<string, string>> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
var entries = hashFields.Select(x => new HashEntry(AddKeyPrefix(x.Key), x.Value));
await _db.HashSetAsync(redisKey, entries.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<string> HashGetAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashGetAsync(redisKey, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<IEnumerable<string>> HashGetAsync(string redisKey, IEnumerable<string> hashFields,
string value)
{
redisKey = AddKeyPrefix(redisKey);
var fields = hashFields.Select(x => (RedisValue) x); return ConvertStrings(await _db.HashGetAsync(redisKey, fields.ToArray()));
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<string>> HashKeysAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return ConvertStrings(await _db.HashKeysAsync(redisKey));
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<string>> HashValuesAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return ConvertStrings(await _db.HashValuesAsync(redisKey));
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(value);
return await _db.HashSetAsync(redisKey, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.HashGetAsync(redisKey, hashField));
} /// <summary>
/// 指定键递增
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<double> HashIncrementAsync(string key, string hashField, double value = )
{
key = AddKeyPrefix(key);
return await _db.HashIncrementAsync(key, hashField, value);
} /// <summary>
/// 指定键递减
/// </summary>
/// <param name="key"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<double> HashDecrementAsync(string key, string hashField, double value = )
{
key = AddKeyPrefix(key);
return await _db.HashDecrementAsync(key, hashField, value);
} #endregion async #endregion Hash 操作 #region List 操作 /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string ListLeftPop(string key)
{
key = AddKeyPrefix(key);
return _db.ListLeftPop(key);
} /// <summary>
/// 出列,移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string ListRightPop(string key)
{
key = AddKeyPrefix(key);
return _db.ListRightPop(key);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public long ListRemove(string key, string value)
{
key = AddKeyPrefix(key);
return _db.ListRemove(key, value);
} /// <summary>
/// 入列,在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public long ListRightPush(string key, string value)
{
key = AddKeyPrefix(key);
return _db.ListRightPush(key, value);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public long ListLeftPush(string key, string value)
{
key = AddKeyPrefix(key);
return _db.ListLeftPush(key, value);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public long ListLength(string key)
{
key = AddKeyPrefix(key);
return _db.ListLength(key);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public IEnumerable<string> ListRange(string key, long start = 0L, long stop = -1L)
{
key = AddKeyPrefix(key);
return ConvertStrings(_db.ListRange(key, start, stop));
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public T ListLeftPop<T>(string key)
{
key = AddKeyPrefix(key);
return Deserialize<T>(_db.ListLeftPop(key));
} /// <summary>
/// 出队,移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public T ListRightPop<T>(string key)
{
key = AddKeyPrefix(key);
return Deserialize<T>(_db.ListRightPop(key));
} /// <summary>
/// 入队,在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public long ListRightPush<T>(string key, T value)
{
key = AddKeyPrefix(key);
return _db.ListRightPush(key, Serialize(value));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public long ListLeftPush<T>(string key, T value)
{
key = AddKeyPrefix(key);
return _db.ListLeftPush(key, Serialize(value));
} #region List-async /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<string> ListLeftPopAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.ListLeftPopAsync(key);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<string> ListRightPopAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.ListRightPopAsync(key);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<long> ListRemoveAsync(string key, string value)
{
key = AddKeyPrefix(key);
return await _db.ListRemoveAsync(key, value);
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync(string key, string value)
{
key = AddKeyPrefix(key);
return await _db.ListRightPushAsync(key, value);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync(string key, string value)
{
key = AddKeyPrefix(key);
return await _db.ListLeftPushAsync(key, value);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<long> ListLengthAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.ListLengthAsync(key);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public async Task<IEnumerable<string>> ListRangeAsync(string key, long start = 0L, long stop = -1L)
{
key = AddKeyPrefix(key);
var query = await _db.ListRangeAsync(key, start, stop);
return query.Select(x => x.ToString());
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<T> ListLeftPopAsync<T>(string key)
{
key = AddKeyPrefix(key);
return Deserialize<T>(await _db.ListLeftPopAsync(key));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<T> ListRightPopAsync<T>(string key)
{
key = AddKeyPrefix(key);
return Deserialize<T>(await _db.ListRightPopAsync(key));
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync<T>(string key, T value)
{
key = AddKeyPrefix(key);
return await _db.ListRightPushAsync(key, Serialize(value));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync<T>(string key, T value)
{
key = AddKeyPrefix(key);
return await _db.ListLeftPushAsync(key, Serialize(value));
} #endregion List-async #endregion List 操作 #region SortedSet 操作 /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd(string key, string member, double score)
{
key = AddKeyPrefix(key);
return _db.SortedSetAdd(key, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <param name="order"></param>
/// <returns></returns>
public IEnumerable<string> SortedSetRangeByRank(string key, long start = 0L, long stop = -1L,
OrderType order = OrderType.Ascending)
{
key = AddKeyPrefix(key);
return _db.SortedSetRangeByRank(key, start, stop, (Order) order).Select(x => x.ToString());
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public long SortedSetLength(string key)
{
key = AddKeyPrefix(key);
return _db.SortedSetLength(key);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="key"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public bool SortedSetRemove(string key, string memebr)
{
key = AddKeyPrefix(key);
return _db.SortedSetRemove(key, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd<T>(string key, T member, double score)
{
key = AddKeyPrefix(key);
var json = Serialize(member); return _db.SortedSetAdd(key, json, score);
} /// <summary>
/// 增量的得分排序的集合中的成员存储键值键按增量
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="value"></param>
/// <returns></returns>
public double SortedSetIncrement(string key, string member, double value = )
{
key = AddKeyPrefix(key);
return _db.SortedSetIncrement(key, member, value);
} #region SortedSet-Async /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync(string key, string member, double score)
{
key = AddKeyPrefix(key);
return await _db.SortedSetAddAsync(key, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<IEnumerable<string>> SortedSetRangeByRankAsync(string key)
{
key = AddKeyPrefix(key);
return ConvertStrings(await _db.SortedSetRangeByRankAsync(key));
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<long> SortedSetLengthAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.SortedSetLengthAsync(key);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="key"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public async Task<bool> SortedSetRemoveAsync(string key, string memebr)
{
key = AddKeyPrefix(key);
return await _db.SortedSetRemoveAsync(key, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync<T>(string key, T member, double score)
{
key = AddKeyPrefix(key);
var json = Serialize(member); return await _db.SortedSetAddAsync(key, json, score);
} /// <summary>
/// 增量的得分排序的集合中的成员存储键值键按增量
/// </summary>
/// <param name="key"></param>
/// <param name="member"></param>
/// <param name="value"></param>
/// <returns></returns>
public Task<double> SortedSetIncrementAsync(string key, string member, double value = )
{
key = AddKeyPrefix(key);
return _db.SortedSetIncrementAsync(key, member, value);
} #endregion SortedSet-Async #endregion SortedSet 操作 #region key 操作 /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyDelete(string key)
{
key = AddKeyPrefix(key);
return _db.KeyDelete(key);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="keys"></param>
/// <returns></returns>
public long KeyDelete(IEnumerable<string> keys)
{
var redisKeys = keys.Select(x => (RedisKey) AddKeyPrefix(x));
return _db.KeyDelete(redisKeys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyExists(string key)
{
key = AddKeyPrefix(key);
return _db.KeyExists(key);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="key"></param>
/// <param name="newKey"></param>
/// <returns></returns>
public bool KeyRename(string key, string newKey)
{
key = AddKeyPrefix(key);
return _db.KeyRename(key, newKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="key"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool KeyExpire(string key, TimeSpan? expiry)
{
key = AddKeyPrefix(key);
return _db.KeyExpire(key, expiry);
} #region key-async /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<bool> KeyDeleteAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.KeyDeleteAsync(key);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="keys"></param>
/// <returns></returns>
public async Task<long> KeyDeleteAsync(IEnumerable<string> keys)
{
var redisKeys = keys.Select(x => (RedisKey) AddKeyPrefix(x));
return await _db.KeyDeleteAsync(redisKeys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public async Task<bool> KeyExistsAsync(string key)
{
key = AddKeyPrefix(key);
return await _db.KeyExistsAsync(key);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="key"></param>
/// <param name="newKey"></param>
/// <returns></returns>
public async Task<bool> KeyRenameAsync(string key, string newKey)
{
key = AddKeyPrefix(key);
return await _db.KeyRenameAsync(key, newKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="key"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> KeyExpireAsync(string key, TimeSpan? expiry)
{
key = AddKeyPrefix(key);
return await _db.KeyExpireAsync(key, expiry);
} #endregion key-async #endregion key 操作 #region 发布订阅 /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = _connMultiplexer.GetSubscriber();
sub.Subscribe(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish(RedisChannel channel, RedisValue message)
{
var sub = _connMultiplexer.GetSubscriber();
return sub.Publish(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish<T>(RedisChannel channel, T message)
{
var sub = _connMultiplexer.GetSubscriber();
return sub.Publish(channel, Serialize(message));
} #region 发布订阅-async /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = _connMultiplexer.GetSubscriber();
await sub.SubscribeAsync(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync(RedisChannel channel, RedisValue message)
{
var sub = _connMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync<T>(RedisChannel channel, T message)
{
var sub = _connMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, Serialize(message));
} #endregion 发布订阅-async #endregion 发布订阅 #region private method /// <summary>
/// 添加 Key 的前缀
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private static string AddKeyPrefix(string key)
{
return $"{DefaultKey}:{key}";
} /// <summary>
/// 转换为字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
private static IEnumerable<string> ConvertStrings<T>(IEnumerable<T> list) where T : struct
{
if (list == null) throw new ArgumentNullException(nameof(list));
return list.Select(x => x.ToString());
} #region 注册事件 /// <summary>
/// 添加注册事件
/// </summary>
private static void AddRegisterEvent()
{
_connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
_connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
_connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
_connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
_connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
_connMultiplexer.InternalError += ConnMultiplexer_InternalError;
_connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
} /// <summary>
/// 重新配置广播时(通常意味着主从同步更改)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
} /// <summary>
/// 发生内部错误时(主要用于调试)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
} /// <summary>
/// 更改集群时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
{
Console.WriteLine(
$"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");
} /// <summary>
/// 配置更改时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
} /// <summary>
/// 发生错误时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
} /// <summary>
/// 物理连接失败时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
} /// <summary>
/// 建立物理连接时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
} #endregion 注册事件 /// <summary>
/// 序列化
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static byte[] Serialize(object obj)
{
if (obj == null)
return null; var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, obj);
var data = memoryStream.ToArray();
return data;
}
} /// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
private static T Deserialize<T>(byte[] data)
{
if (data == null)
return default(T); var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream(data))
{
var result = (T) binaryFormatter.Deserialize(memoryStream);
return result;
}
} #endregion private method
}
}
RedisHelper.cs
下期将分析 redis 的五大类型,及介绍他们常用的指令。
系列
《Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍》
《Redis 小白指南(二)- 聊聊五大类型:字符串、散列、列表、集合和有序集合》
《Redis 小白指南(三)- 事务、过期、消息通知、管道、优化内存空间》
【博主】反骨仔
【原文】http://www.cnblogs.com/liqingwen/p/6917426.html
【GitHub】https://github.com/liqingwen2015/Wen.Helpers/blob/master/Wen.Helpers.Common/Redis/RedisHelper.cs
【参考】《redis 入门指南》