接上篇c#实现redis客户端(一),重新整理些了下。

阅读目录:

  1. 项目说明
  2. Hredis设计图
  3. 单元测试场景
  4. 总结

项目说明

背景:因为有地方要用,而又没找到对sentinel良好支持的Net客户端,所以就简单重写了个。

目标:尽可能的简单,轻量级,不进行过度的封装,使用方便。

代码说明:

1. 与Redis服务端的Socket通信、协议格式封装。在RedisBaseClient里 

2. 只对Set、Get封装,暴露出Send接口。在RedisCommand里面添加自己想要的支持。

var info = rcClient.Send(RedisCommand.INFO);

3.  RedisBaseClient是通信层。 如果扩展其他用途继承即可,比如RedisPubSub:RedisBaseClient,RedisSentinel:RedisBaseClient

4.  供上层良好调用的话,可以做成partial类扩展redisclient。比如RedisClient.String

5.  订阅的监听使用while的,可在触发事件里面做阻塞。

6.  PoolRedisClient池的实现使用ConcurrentStack,仅达到了复用socket连接的目的。

7.  支持socket重连,做法是关闭旧连接,重新建立新socket。

8.  多个命令使用管道实现。见set实现

后续思路:

      一:PoolRedisClient池里面连接的释放问题?

1. 使用using

2. 不用使用using,会自动检测并回收 。

不做成自动检测的话,就会出现连接无法释放的问题,总会有人忘记释放的,所以要优化成1+2结合的方式。

二:client池和socket池分离,socket单独做一个池? 还在考虑中。

Hredis设计图

命令执行流程图、解决方案图、类图。

  

单元测试场景

一. Info命令通信、密码配置。

 [TestMethod, TestCategory("Server")]public void Redis_PassWord(){using (var rcClient = new RedisClient(new RedisConfiguration(){Host = ip,Port = 6381,PassWord = "123465"})){var info = rcClient.Send(RedisCommand.INFO);Debug.Write(info.ToString());}}

二. 普通订阅,及模式匹配订阅。这里订阅的是Sentinel事件信息。

        [TestMethod, TestCategory("PushSub")]public void Subscribe_Sentinel_Test(){using (RedisPubSub rsc = new RedisPubSub("127.0.0.1", 20001)){rsc.SubscriptionReceived += rsc_SubscriptionReceived;//rsc.Subscribe("+sdown");}}

[TestMethod, TestCategory("PushSub")]public void PSubscribe_Sentinel_Test(){using (RedisPubSub rsc = new RedisPubSub("127.0.0.1", 20001)){rsc.SubscriptionReceived += rsc_SubscriptionReceived;// rsc.PSubscribe("*");
            }}private void rsc_SubscriptionReceived(object sender, object args){if (args is object[]){var list = args as object[];foreach (var o in list){Debug.Write("\r\n" + o.ToString());}}else{Debug.Write("\r\n" + args.ToString());}var sr = sender as RedisPubSub;sr.UnSubscribe("*");}

View Code

三.  client连接池、Parallel并发模拟。

  [TestMethod, TestCategory("poolRedisclient")]public void GetClient_Test(){PoolRedisClient prc = new PoolRedisClient(new PoolConfiguration(){Host = ip,Port = port,MaxClients = 100});using (var client = prc.GetClient()){client.Set("GetClient_Test", "GetClient_Test");var info2 = client.Get("GetClient_Test");Assert.AreEqual(info2.ToString(), "GetClient_Test");}prc.Dispose();}

View Code

        [TestMethod, TestCategory("poolRedisclient")]public void Parallel_PoolClient_Test(){PoolRedisClient prc = new PoolRedisClient(new PoolConfiguration(){Host = ip,Port = port,MaxClients = 100});Parallel.For(0, 1000, new ParallelOptions() {MaxDegreeOfParallelism = 100}, (index, item) =>{using (var client = prc.GetClient()){Thread.Sleep(100);client.Set("Parallel_PoolClient_Test" + index, "Parallel_PoolClient_Test");var info2 = client.Get("Parallel_PoolClient_Test" + index);Assert.AreEqual(info2.ToString(), "Parallel_PoolClient_Test");}});prc.Dispose();}

View Code

三.  超时重连、多线程并发超时重连。

        [TestMethod, TestCategory("poolRedisclient")]public void PoolClient_TimeOut_Test(){PoolRedisClient prc = new PoolRedisClient(new PoolConfiguration(){Host = ip,Port = port,MaxClients = 100});object info2;using (var client = prc.GetClient()){var result = client.Set("PoolClient_TimeOut_Test", "PoolClient_TimeOut_Test");Thread.Sleep(15000);info2 = client.Get("PoolClient_TimeOut_Test");}Assert.AreEqual(info2.ToString(), "PoolClient_TimeOut_Test");prc.Dispose();}

View Code

  [TestMethod, TestCategory("poolRedisclient")]public void Thread_PoolClient_Test(){PoolRedisClient prc = new PoolRedisClient(new PoolConfiguration(){Host = ip,Port = port});Parallel.For(0, 1000, new ParallelOptions() {MaxDegreeOfParallelism = 100}, (index, item) =>{var t = new Thread(() =>{Thread.Sleep(1000);object info2;using (var client = prc.GetClient()){client.Set("Parallel_PoolClient_Test" + index, "Parallel_PoolClient_Test");Thread.Sleep(15000);info2 = client.Get("Parallel_PoolClient_Test" + index);}Assert.AreEqual(info2.ToString(), "Parallel_PoolClient_Test");});t.Start();});Thread.Sleep(20000);prc.Dispose();}

四. String类型添加、过期时间添加。

[TestMethod, TestCategory("String")]public void Set_Get_key(){using (var rcClient = new RedisClient(ip, port)){rcClient.Set("Set_Get_key", "Set_Get_key");var info2 = rcClient.Get("Set_Get_key");Assert.AreEqual(info2.ToString(), "Set_Get_key"); } }

  [TestMethod, TestCategory("String")]public void Set_key_Expire(){using (var rcClient = new RedisClient(ip, port)){rcClient.Set("Set_key_Expire", "Set_key_Expire", 10);var info1 = rcClient.Get("Set_key_Expire");Assert.AreEqual(info1.ToString(), "Set_key_Expire");Thread.Sleep(11000);var info2 = rcClient.Get("Set_key_Expire");Assert.AreEqual(info2, null);}}

View Code

总结

开源地址:https://github.com/mushroomsir/HRedis  有需要的同学,可以参考下。

Hredis后续会跟实际需求来写,如果有更好的实现思路,欢迎一起交流。

Redis系列(二)-Hredis客户端设计及开源相关推荐

  1. redis 系列二 -- 常用命令

    2019独角兽企业重金招聘Python工程师标准>>> 1.基础命令 info    ping    quit    save dbsize    select    flushdb ...

  2. Redis系列二:reids介绍

    一.什么是redis.redis有哪些特性.redis有哪些应用场景.redis的版本 1. 什么是redis redis是一种基于键值对(key-value)数据库,其中value可以为string ...

  3. Redis系列二、redis的五种数据结构和相关指令之String

    redis是一种基于键值对(key-value)的内存数据库,redis数据结构可以分为string.hash.list.set.sorted set.本节中将介绍Redis支持的主要数据结构中的st ...

  4. redis搭建主从哨兵模式+分片集群部署(redis系列二)

    前言:在前一章了解redis的基本介绍后,这一章主要介绍redis的实战部署,文章有点长请一步步耐心看完,我相信肯定会有收获的,这里用的资源包是2022年最新的redis版本可能会跟旧版本不同,在此章 ...

  5. Redis系列(十四)、Redis6新特性之RESP3与客户端缓存(Client side caching)

    Redis6引入新的RESP3协议,并以此为基础加入了客户端缓存的新特性,在此特性下,大大提高了应用程序的响应速度,并降低了数据库的压力,本篇就带大家来看一下Redis6的新特性:客户端缓存. 目录 ...

  6. 开源一款强大的文件服务组件(QJ_FileCenter)(系列二 安装说明)

    系列文章 1. 开源一款强大的文件服务组件(QJ_FileCenter)(系列一) 2. 开源一款强大的文件服务组件(QJ_FileCenter)(系列二 安装说明) 3. 开源一款强大的文件服务组件 ...

  7. 深入剖析Redis系列(七) - Redis数据结构之列表

    前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...

  8. 深入剖析Redis系列(三) - Redis集群模式搭建与原理详解

    前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 ...

  9. Redis系列(五):Redis的过期键删除策略

    Redis系列(五):Redis的过期键删除策略 - 申城异乡人 - 博客园 本篇博客是Redis系列的第5篇,主要讲解下Redis的过期键删除策略. 本系列的前4篇可以点击以下链接查看: Redis ...

  10. 深入剖析Redis系列(五) - Redis数据结构之字符串

    前言 字符串类型 是 Redis 最基础的数据结构.字符串类型 的值实际可以是 字符串(简单 和 复杂 的字符串,例如 JSON.XML).数字(整数.浮点数),甚至是 二进制(图片.音频.视频),但 ...

最新文章

  1. GDB attach到进程
  2. 5G NGC — NWDAF 网络智能分析功能
  3. solr4.1 DataImport MYSQL批量导入
  4. MooseFS使用问题分析总结
  5. 【任务脚本】0530更新淘宝618活动领喵币脚本,OrangeJs基于autojs全自动程序稳定运行,向大神致敬...
  6. Segment-段(SAP)
  7. 快速谱峭度matlab,一种基于快速谱峭度分析的泵潜在空化故障检测方法与流程
  8. Win10下安装LabelImg以及使用(绝对是全网最简单的教程)
  9. vscode ---- 插件
  10. 程序员修神之路--分布式高并发下Actor模型如此优秀
  11. SDNLAB技术分享(二):从Toaster示例初探ODL MD-SAL架构
  12. python模块使用手册_Python中文手册-Python模块
  13. suse 12 sp5安装bug
  14. 汇编语言简明教程习题答案
  15. div 设置a4大小_转载 网页打印时设置A4大小
  16. 轻量级Kubernetes之k3s:15:firewalld对应方法
  17. 头条小程序可以使用uniapp的地图选择(uni.chooseLocation)
  18. 多个勤于奋,到底那个是真的?勤于奋被他人抄袭
  19. 柯伊玟导演作品《黑暗迷踪》顺利杀青
  20. 【Chrome】图片批量下载扩展zzllrr Imager小乐图客V1.4 (支持正则表达式、自定义JS代码、自定义引擎、多网站取图规则)...

热门文章

  1. 【IPC通信】基于管道的popen和pclose函数
  2. CheckBox的触发
  3. Silverlight中的ControlTemplate
  4. MyBatis中解决字段名与实体类属性名不相同的冲突
  5. SLA服务可用性怎么达到?
  6. 36. 打印数组的主次对角线
  7. 【软考】(五)网络互联设备
  8. Windows API Unicode 和 多字节转化demo
  9. [Swift]LeetCode306. 累加数 | Additive Number
  10. ELK之LogStacs