.NET redis 客户端开源组件 FreeRedis (继 CSRedisCore 之后重写)
什么是 FreeRedis
FreeRedis 是一款 .NET redis 客户端开源组件,以 MIT 协议开源托管于 github,目前支持 .NET 5、.NETCore 2.1+、.NETFramework 4.0+、Xamarin,有可能已经支持 AOT 编译(目前未测试,但会往这个方向走)。
FreeRedis 会严格按照 FreeSql 的开源方式,做好单元测试,兼容平台,简单易用,有问必答,有求必应的态度,为中国 .NET 开源事业做一点点贡献。
感谢大家的支持,项目还未公开就已经获得 66 星。目前项目仍在起步阶段,欢迎小伙伴参与进来,贡献测试、或代码、或建议都可以。
项目当前的状态:
- 版本 0.0.8(目前不建议使用在生产环境)
- 单元测试 268 个
- 支持 集群、哨兵、主从(已通过测试)
- 支持 连接池
- 支持 .NET5/.NETCore 2.1+/.NET4.0+
- 支持 Redis6.0 所有类型
- 支持 Redis6.0 RESP3 协议
- API 仍然与 redis-cli 命令保持一致
- 采用最宽松的开源协议 MIT https://github.com/2881099/FreeRedis
项目由来
说来话长,2016 年之前本人写了一年多 nodejs 服务端应用,使用过 node-redis 组件,真心好用。在此期间有同事不停安利 .NET 可以跨平台了,劝我快回来搞 .NET,开始我是抗拒做螃蟹第一人的,不知道是哪天下午闲着蛋疼去体验了一把 .NETCore 1.0-previewXX(不记得哪个版本了)。试了一把被吸引住了,体验感受和 expressjs 像极了,再也看不见以往 webform/mvc 的缺点。
于是我准备入坑了,入坑第一件事除了 hello world,还需要做相关调研:
- 性能OK
- 设计OK
- 发展OK(暂时的定级)
- 相关组件OK(HttpClient、Redis、Ado.NET、等等基础组件)
初始调研完成之后,接下下就要抽时间选型框架了,最终从众多框架中选择了合适团队的一款:https://github.com/simplcommerce/SimplCommerce ,在这个项目原有基础之上,结合企业规范要求定制改造,大约两个月时间完成了可生产的状态。(框架不求开始尽善尽美,只求使用中不断打磨,最终走向完美)
理想丰满现实骨干,接下来的故事就是遇到生产故障了,StackExchange.Redis、HttpClient 关于这两个组件的问题,以前讲过现在就不说了(万万没想到这么大的组件使用都能出现问题)。吃螃蟹就会掉坑,掉了坑就要想办法解决,最终与 csredis 组件结缘。
以当时的情形纵观 .NET 所有 redis 客户端组件,只有 csredis 源码最易改造支持 .NETCore(水平有限见谅),csredis 2014 年停止更新,本人于 2016 年将其改造支持 .NETCore 为主,以及增加连接池管理、集群、哨兵、redis2.8 以上的命令,在公司项目生产环境使用一年半载之后开源。
- csredis 原源码地址:https://github.com/ctstone/csredis
- CSRedisCore 源码地址:https://github.com/2881099/csredis
CSRedisCore 开源这到久,nuget 下载量达到 60W,收集需求若干,bug 若干(有解决了的、也有未能重现的),基于我已经对 redis 这块很熟悉,然后 redis 5.0/6.0 又新增了蛮多特性,重新写一款 bug 更少、可维护性更好的想法产生了。
经过几个月的墨迹终于走通可用了,项目最终命名:FreeRedis
如何使用
Single machine redis (单机)
public static RedisClient cli = new RedisClient("127.0.0.1:6379,password=123,defaultDatabase=13");
//cli.Serialize = obj => JsonConvert.SerializeObject(obj);
//cli.Deserialize = (json, type) => JsonConvert.DeserializeObject(json, type);
cli.Notice += (s, e) => Console.WriteLine(e.Log); //print command log
cli.Set("key1", "value1");
cli.MSet("key1", "value1", "key2", "value2");
string value1 = cli.Get("key1");
string[] vals = cli.MGet("key1", "key2");
API 仍然与 redis-cli 命令保持一致,所以如果想了解 FreeRedis 每个方法怎么使用,去百度搜索 “redis 命令”,有很多很多很多资料。don't say so much!!!
支持 Redis6.0 支持的所有数据类型:strings, hashes, lists, sets, sorted sets, bitmaps, hyperloglogs, geo, streams And BloomFilter.
Parameter | Default | Explain |
---|---|---|
protocol | RESP2 | If you use RESP3, you need redis 6.0 environment |
user | <empty> | Redis server username, requires redis-server 6.0 |
password | <empty> | Redis server password |
defaultDatabase | 0 | Redis server database |
max poolsize | 100 | Connection max pool size |
min poolsize | 5 | Connection min pool size |
idleTimeout | 20000 | Idle time of elements in the connection pool (MS) |
connectTimeout | 10000 | Connection timeout (MS) |
receiveTimeout | 10000 | Receive timeout (MS) |
sendTimeout | 10000 | Send timeout (MS) |
encoding | utf-8 | string charset |
ssl | false | Enable encrypted transmission |
name | <empty> | Connection name, use client list command to view |
如果需要连接 IPv6,连接串请使用: [fe80::b164:55b3:4b4f:7ce6%15]:6379
Master-Slave (读写分离)
public static RedisClient cli = new RedisClient(
"127.0.0.1:6379,password=123,defaultDatabase=13",
"127.0.0.1:6380,password=123,defaultDatabase=13",
"127.0.0.1:6381,password=123,defaultDatabase=13"
);
var value = cli.Get("key1");
这样创建的 cli,所有写入命令都会连接 127.0.0.1:6379 执行,所有读取命令只会随机连接 127.0.0.1:6380 或 127.0.0.1:6381 执行。(内部已经为每个命令做好了读写标记)
Redis Sentinel (哨兵高可用)
public static RedisClient cli = new RedisClient(
"mymaster,password=123",
new [] { "192.169.1.10:26379", "192.169.1.11:26379", "192.169.1.12:26379" },
true //是否读写分离
);
哨兵是一个分布式系统,为 Redis 提供高可用性解决方案,当主机 master 宕机之后,会马上出现一个新的 master 可使用,确保服务的正常运作。
哨兵模式还可以设置读写分离,缓解 master 频繁读取数据的压力,缺点:有可能读到的数据不是最新,因为 redis 从 master 同步到 slave 有延时。
Redis Cluster (集群)
假如你有一个 Redis Cluster 集群,其中有三个主节点(7001-7003)、三个从节点(7004-7006),则连接此集群的代码:
public static RedisClient cli = new RedisClient(
new ConnectionStringBuilder[] { "192.168.0.2:7001", "192.168.0.2:7001", "192.168.0.2:7003" }
);
Subscribe (订阅)
using (cli.Subscribe("abc", ondata)) //wait .Dispose()
{
Console.ReadKey();
}
void ondata(string channel, string data) =>
Console.WriteLine($"{channel} -> {data}");
Scripting (脚本)
var r1 = cli.Eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
new[] { "key1", "key2" }, "first", "second") as object[];
var r2 = cli.Eval("return {1,2,{3,'Hello World!'}}") as object[];
cli.Eval("return redis.call('set',KEYS[1],'bar')",
new[] { Guid.NewGuid().ToString() })
Pipeline (管道)
using (var pipe = cli.StartPipe())
{
pipe.IncrBy("key1", 10);
pipe.Set("key2", Null);
pipe.Get("key1");
object[] ret = pipe.EndPipe();
Console.WriteLine(ret[0] + ", " + ret[2]);
}
// or Async Callback
using (var pipe = cli.StartPipe())
{
var tasks = new List<Task>();
long t0 = 0;
task.Add(pipe.IncrByAsync("key1", 10).ContinueWith(t => t0 = t.Result)); //callback
pipe.SetAsync("key2", Null);
string t2 = null;
task.Add(pipe.GetAsync("key1").ContinueWith(t => t2 = t.Result)); //callback
pipe.EndPipe();
Task.WaitAll(tasks.ToArray()); //wait all callback
Console.WriteLine(t0 + ", " + t2);
}
Transaction (事务)
using (var tran = cli.Multi())
{
tran.IncrBy("key1", 10);
tran.Set("key2", Null);
tran.Get("key1");
object[] ret = tran.Exec();
Console.WriteLine(ret[0] + ", " + ret[2]);
}
// or Async Callback
using (var tran = cli.Multi())
{
var tasks = new List<Task>();
long t0 = 0;
task.Add(tran.IncrByAsync("key1", 10).ContinueWith(t => t0 = t.Result)); //callback
tran.SetAsync("key2", Null);
string t2 = null;
task.Add(tran.GetAsync("key1").ContinueWith(t => t2 = t.Result)); //callback
tran.Exec();
Task.WaitAll(tasks.ToArray()); //wait all callback
Console.WriteLine(t0 + ", " + t2);
}
.NET redis 客户端开源组件 FreeRedis (继 CSRedisCore 之后重写)的更多相关文章
- Redis .NET开源组件Beetle.Redis
Redis .NET开源组件Beetle.Redis Beetle.Redis是一款开源的Redis Client for .net组件,它提供非常简便的操作方式可以让开发人员轻松地访问Redis,同 ...
- .Net 开源项目 FreeRedis 实现思路之 - Redis 6.0 客户端缓存技术
写在开头 FreeRedis 是一款继 CSRedisCore 之后重写的 .NET redis 客户端开源组件,以 MIT 协议开源托管于 github,目前支持 .NET 5..NETCore 2 ...
- Redis 客户端重试指南
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可. 在互联网服务中,特别是在云环境下,网络及硬件环境复杂,所有应用程序都可能遇到暂时性故障.暂时性故障包括瞬时的网络抖动,服务暂时不可 ...
- [开源福利] FreeRedis 历时两年正式发布 v1.0 [C#.NET Redis Client]
最近很多 .net QQ 群无故被封停,特别是 wpf 群几乎全军覆没.依乐祝的 .net6交流群,晓晨的 .net跨平台交流群,导致很多码友流离失所无家可归,借此机会使用一次召唤术,有需要的请加群: ...
- redis在游戏服务器中的使用初探(二) 客户端开源库选择
上文提到 搭建完成后 我们选择客户端的开源库进行连接 有以下三种选择 1 acl-redis 原因是支持VC 国产 作者博客 acl 框架库简介 用 acl 库编写高效的 C++ redis ...
- 国人开源了一款超好用的 Redis 客户端,真香!!
大家都知道,Redis Desktop Manager 是一款非常好用的 Redis 可视化客户端工具,但可惜的是 v0.9.4 版本之后需要收费了: 这个工具不再免费提供安装包了,要对所有安装包收费 ...
- .net 开源组件推荐 之 StackExchange
已经两年没更新过博客了!!! StackExchange,地址:https://github.com/StackExchange,开源的这些项目都是在StackOverflow线上使用的. 说起Sta ...
- .Net Core 三大Redis客户端对比和使用心得
前言 稍微复杂一点的互联网项目,技术选型都可能会涉及Redis,.NetCore的生态越发完善,支持.NetCore的Redis客户端越来越多, 下面三款常见的Redis客户端,相信大家平时或多或少用 ...
- 分享几个.NET WinForm开源组件,纪念逐渐远去的WinForm。。。
前面3个月的时间内,这些.NET开源项目你知道吗?系列文章已经发表了3篇,共计45个平时接触比较少,曾经默默无闻的.NET开源项目,展示给大家,当然不是每个人都能用得上,但也的确是有些人用了,反响还不 ...
随机推荐
- Java知识系统回顾整理01基础02面向对象02属性
一.根据实例给出"属性"的定义 一个英雄有姓名,血量,护甲等等状态 这些状态就叫做一个类的属性 二.属性的类型 属性的类型可以是基本类型,比如int整数,float 浮点数 也可以 ...
- Python基本数据类型详细介绍
Python提供的基本数据类型主要有:布尔类型.整型.浮点型.字符串.列表.元组.集合.字典等等 1.空(None)表示该值是一个空对象,空值是Python里一个特殊的值,用None表示.None不能 ...
- matlab中repmat函数的用法
转载:https://blog.csdn.net/facetosea1/article/details/83573859 B = repmat(A,m,n)B = repmat(A,[m n])B = ...
- C++中memset函数的用法
转载:https://blog.csdn.net/qq_22122811/article/details/52738029 //复习数组的时候,第一次见到了memset,学之. memset:char ...
- Cisco思科模拟器 交换机IP地址的配置 入门详解 - 精简归纳
Cisco思科模拟器 交换机IP地址的配置 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 10 转载请注明出处!️ 目录 Cisco思科模拟器 交换机IP地址的配置 入门详解 ...
- git冲突的表现
<<<<<<< HEAD b789 ======= b45678910 >>>>>>> 6853e5ff961e68 ...
- kafka-manage管理工具
1 github地址 https://github.com/sheepkiller/kafka-manager-docker 2 启动 将参数传递给kafka-manager 对于版本 ...
- centos8平台使用parted管理分区
一,parted的用途 parted是GNU发布的强大的分区工具, parted命令可以划分单个分区大于2T的GPT格式的分区,也可以划分普通的MBR分区. 因为fdisk命令对于大于2T的分区无法划 ...
- <noscript> 实例
实例 JavaScript <body> ... ... <script type="text/javascript"> <!‐‐ ...
- 【多次实践】win10+ubuntu18.04lts双系统安装葵花宝典(安装篇)
这个教程诞生的缘由很简单,吃的太饱,硬是要折腾,结果,这一折腾便是20余小时,故写此文,帮助后来者少走弯路! 在本文开始,请先允许我对网上很多类似的教程嗤之以鼻,很成功地让我走了很多的弯路,一些有效简 ...