本文将使用一个gitHub开源的组件技术来读写redis数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作

github地址:https://github.com/dathlin/HslCommunication                             如果喜欢可以star或是fork,还可以打赏支持。

官网地址:http://www.hslcommunication.cn/

联系作者及加群方式(激活码在群里发放):http://www.hslcommunication.cn/Cooperation

Redis是什么?


这个是一个实时的数据库技术,主要采用键值操作来存储数据的。官网是 https://redis.io/ ,官方的解释为(摘自百度百科):

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 [1] 
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
redis的官网地址,非常好记,是redis.io。(特意查了一下,域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地)
目前,Vmware在资助着redis项目的开发和维护。

安装redis服务器


我们在使用前需要安装服务器,一般的windows的服务器来自于微软的项目:

https://github.com/MicrosoftArchive/redis/releases

虽然微软的项目只更新到了 redis3.2 版本。但是已经足够我们日常的使用了。

安装完成后,会自动的启动服务器。我们可以打开cmd来测试

服务器搭好后就可以使用C#来操作了。

再次随便聊聊,C#有个还可以的redis类库叫StackExchange.Redis

https://github.com/StackExchange/StackExchange.Redis

但是这个类库呢,总有些莫名其妙的问题,尤其是超时问题,始终没有得到很好的解决,所以我集成实现了redis的基本操作,给大家一个更多的选择。支持.net framework和.net standard

当你的程序实现了redis之后,程序架构变成了:

此处的redis相当于高速的数据缓存,可以部署在服务器的电脑上,可以部署在云端等等,任意其他的电脑上面。

接下来演示使用HSL来进行操作

从NUGET安装


Install-Package HslCommunication

  

关于两种模式


在PLC端,包括三菱,西门子,欧姆龙,AB以及Modbus Tcp客户端的访问器上,都支持两种模式,短连接模式和长连接模式,现在就来解释下什么原理。

短连接:每次读写都是一个单独的请求,请求完毕也就关闭了,如果服务器的端口仅仅支持单连接,那么关闭后这个端口可以被其他连接复用,但是在频繁的网络请求下,容易发生异常,会有其他的请求不成功,尤其是多线程的情况下。

长连接:创建一个公用的连接通道,所有的读写请求都利用这个通道来完成,这样的话,读写性能更快速,即时多线程调用也不会影响,内部有同步机制。如果服务器的端口仅仅支持单连接,那么这个端口就被占用了,比如三菱的端口机制,西门子的Modbus tcp端口机制也是这样的。以下代码默认使用长连接,性能更高,还支持多线程同步。

在短连接的模式下,每次请求都是单独的访问,所以没有重连的困扰,在长连接的模式下,如果本次请求失败了,在下次请求的时候,会自动重新连接服务器,直到请求成功为止。另外,尽量所有的读写都对结果的成功进行判断。

DEMO示例:


下面的一个项目是这个组件的访问测试项目,您可以进行初步的访问的测试,免去了您写测试程序的麻烦,三菱的界面和西门子的界面几乎是一致的。可以同时参考。该项目位于本篇文章开始处的Gitbub源代码里面的

下载地址为:HslCommunicationDemo.zip

可以用来浏览你的redis到底有什么数据,以及这个数据是什么,初步支持了  string,list,hash 数据类型。

当你写入的key名字带有:(英文状态)时。这个浏览器还会对数据进行分类整理、

关于redis指令


http://doc.redisfans.com/index.html

原生的指令有很多,这个库里也是支持了大部分的操作,如果你需要的功能还没有支持,比如 获取一个键的数据信息, 将指令参数按照空格输入进去就行

        private void button16_Click( object sender, EventArgs e )
{
OperateResult<string> read = redisClient.ReadCustomer("GET A" );
if (read.IsSuccess)
{
// read.Content 就是从服务器返回的数据 例如为 $2\r\n11\r\n 需要自己提炼真实的数据
MessageBox.Show( read.Content );
}
else
{
MessageBox.Show( read.Message );
}
}

  

下面列举一些示例

简单使用


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HslCommunication.Enthernet.Redis;
using HslCommunication; namespace WindowsFormsApp3
{
public partial class Form1 : Form
{
public Form1( )
{
InitializeComponent( );
} private RedisClient redisClient = new RedisClient( "127.0.0.1", 6379, "" );
private void button1_Click( object sender, EventArgs e )
{
OperateResult<string> read = redisClient.ReadKey( "a" );
if (read.IsSuccess)
{
MessageBox.Show( read.Content );
}
else
{
MessageBox.Show( read.Message );
}
}
}
}

  

结果如下:

显示的值就是我们之前写入的操作,主要,redis区分大小写,你读  A  和读 a 是不一样的。

上述的代码已经进行了严格的验证,上面情况会读取失败呢?网络异常或是 a 不存在

我们来看看写入键值:

        private void button2_Click( object sender, EventArgs e )
{
OperateResult write = redisClient.WriteKey( "a", "abcde" );
}

上述就没有对写入成功与否进行验证,只要是网络正常基本都是成功的。

写完后我们再读取一次:

如果想写入一个有生命周期的key,比如100s后自动消失的key

        private void button3_Click( object sender, EventArgs e )
{
OperateResult write = redisClient.WriteExpireKey( "b", "abcde", 100 );
}

这样就写入了一个带生命周期的key了。

批量读写


如果想要一次性写入或是读取很多键值:

        private void button4_Click( object sender, EventArgs e )
{
OperateResult<string[]> read = redisClient.ReadKey( new string[] { "a", "b" } );
if (read.IsSuccess)
{
string[] result = read.Content;
}
else
{
MessageBox.Show( read.Message );
}
}

写入的操作如下:

        private void button5_Click( object sender, EventArgs e )
{
redisClient.WriteKey( new string[] { "a", "b" }, new string[] { "abcde", "ihsdasd" } );
}

此处省略了对写入结果的验证,为了安全起见,你应该添加。

获取旧值,并设置一个新的值进去

        private void button6_Click( object sender, EventArgs e )
{
OperateResult<string> read = redisClient.ReadAndWriteKey( "a", "aaaaaa" );
if (read.IsSuccess)
{
MessageBox.Show( read.Content );
}
else
{
MessageBox.Show( read.Message );
}
}

  

递增递减操作。


这个基本功能也是很常见的、

我们先写 BB 为 0

然后我们再给这个值加1,并返回1的操作。

        private void button7_Click( object sender, EventArgs e )
{
OperateResult<int> read = redisClient.IncrementKey( "BB" );
if (read.IsSuccess)
{
MessageBox.Show( "Value:" + read.Content );
}
else
{
MessageBox.Show( read.Message );
}
}

同理也支持减一操作,增加指定的数据操作,减去指定的数据操作。

列表操作


redis也支持存储数组数据信息

我们创建一个数组,并往里面塞东西,当然支持从数组的左侧塞,也支持从右侧塞,下面就是左侧的例子

        private void button8_Click( object sender, EventArgs e )
{
redisClient.ListLeftPush( "C", "123" );
}

这样就创建了一个数组,数组数据的读取,并不是get了,而是变成了 LRANGE 0 -1 代表读取整个的数组

用代码来读取就是

        private void button9_Click( object sender, EventArgs e )
{
OperateResult<string[]> read = redisClient.ListRange( "C", 0, -1 );
if (read.IsSuccess)
{
// 列表变成了一个数组信息
string[] result = read.Content;
}
else
{
MessageBox.Show( read.Message );
}
}

当然,当你的数组很大时。比如1000个长度时,你可以读取中间任意个数组。

获取数组长度


当你不知道一个数组的长度,不想在读取所有的数组信息的情况下,读取到长度

        private void button10_Click( object sender, EventArgs e )
{
int length = redisClient.GetListLength( "C" ).Content; // 此处就是1
}

获取指定索引的数据


        private void button11_Click( object sender, EventArgs e )
{
string read = redisClient.ReadListByIndex( "C", 0 ).Content;
}

注意,当C不是list时,会引发错误。  

修剪列表信息


当数组过长时,我们可以修剪数组来达到收缩的目的

        private void button12_Click( object sender, EventArgs e )
{
redisClient.ListTrim( "C", 0, 9 );// 10个长度,保留0-9索引的数据
}

  

返回并移除开始处的列表


        private void button13_Click( object sender, EventArgs e )
{
OperateResult<string> read = redisClient.ListLeftPop( "C" );
if (read.IsSuccess)
{
MessageBox.Show( read.Content );
}
else
{
MessageBox.Show( read.Message );
}
}

  移除并返回测试的也是可以的。

哈希值读写


哈希值的意思是一个键的值是由多个键值组成的

        private void button14_Click( object sender, EventArgs e )
{
redisClient.WriteHashKey( "D", "A", "1" );
redisClient.WriteHashKey( "D", "B", "2" );
redisClient.WriteHashKey( "D", "C", "3" );
}

  

相当于是键 D 的域 A 写入1, B写入2,C写入3

你一次可以读取所有的C的域集合,或是值集合,或是域+值集合,下面演示了一个示例,读取域+值集合

        private void button15_Click( object sender, EventArgs e )
{
OperateResult<string[]> read = redisClient.ReadHashKeyAll( "C" );
if (read.IsSuccess)
{
// 列表变成了一个域+值信息
// A
// 1
// B
// 2
// C
// 3
string[] result = read.Content;
}
else
{
MessageBox.Show( read.Message );
}
}

  

C# 读写redis C#读写实时数据库的更多相关文章

  1. redis sentinel 读写分离

    redis sentinel 读写分离 https://www.jianshu.com/p/d1636776bb40

  2. Java Redis的Pipeline管道,批量操作,节省大量网络往返时间 & Redis批量读写(hmset&hgetall) 使用Pipeline

    一般情况下,大家使用redis去put/get都是先拿到一个jedis实例,然后操作,然后释放连接:这种模式是 请求-响应,请求-响应 这种模式,下一次请求必须得等第一次请求响应回来之后才可以,因为r ...

  3. jedis使用管道(pipeline)对redis进行读写(使用hmset、hgetall测试)

    一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client.这有点类似于HBase的Scan, ...

  4. windows下Redis 主从读写分离部署

    原文:windows下Redis 主从读写分离部署 1.可直接下载window下的运行文件(下面这个链接) 也可以浏览github 查看相应的版本说明文档 https://github.com/Ser ...

  5. 使用ServiceStack.Redis实现Redis数据读写

    原文:使用ServiceStack.Redis实现Redis数据读写 User.cs实体类 public class User { public string Name { get; set; } p ...

  6. 在项目中部署redis的读写分离架构(包含节点间认证口令)

    #### 在项目中部署redis的读写分离架构(包含节点间认证口令) ##### 1.配置过程 ---  1.此前就是已经将redis在系统中已经安装好了,redis utils目录下,有个redis ...

  7. Flink读写Redis(三)-读取redis数据

    自定义flink的RedisSource,实现从redis中读取数据,这里借鉴了flink-connector-redis_2.11的实现逻辑,实现对redis读取的逻辑封装,flink-connec ...

  8. Redis的读写分离

    1.概述 随着企业业务的不断扩大,请求的并发量不断增长,Redis可能终会出现无法负载的情况,此时我们就需要想办法去提升Redis的负载能力. 读写分离(主从复制)是一个比较简单的扩展方案,使用多台机 ...

  9. flinksql读写redis

    0.前言 最近有个需求,需要使用flinksql读写redis,由于官网上并没有redis的connector,在网上找了很久,开源的几个connector又没法满足要求,所有这里就自己动手实现了一个 ...

随机推荐

  1. Flask系列(三)蓝图、基于DButils实现数据库连接池、上下文管理

    知识点回顾 1.子类继承父类的三种方式 class Dog(Animal): #子类 派生类 def __init__(self,name,breed, life_value,aggr): # Ani ...

  2. rtcp多媒体控制协议应用

    rtcp package send/recv demo main.c #include <stdio.h> #include <rtp.h> #include <rtcp ...

  3. sqlnet.ora的作用

    sqlnet.ora的作用 1.限制客户端访问(如指定客户端域为不允许访问) 2.指定命名方法(local naming,directory nameing...)的优先级 3.启用日志及跟踪(log ...

  4. The adidas NMD Singapore is one of the brands top selling

    Like pointed out, we've two adidas NMD Singapore releases using the first arriving Blue and Black as ...

  5. Android ContentResolver

    在Android 应用程序之间数据共享—-ContentResolver中,已经说明了Android是如何实现应用程序之间数据共享的,并详细解析了如何获取其他应用 程序共享的数据.ContentPro ...

  6. (转载)找圆算法((HoughCircles)总结与优化

      Opencv内部提供了一个基于Hough变换理论的找圆算法,HoughCircle与一般的拟合圆算法比起来,各有优势:优势:HoughCircle对噪声点不怎么敏感,并且可以在同一个图中找出多个圆 ...

  7. Stitching模块中leaveBiggestComponent初步研究

    在Stitching模块中以及原始论文<Automatic Panoramic Image Stitching using Invariant Features>3.2中,都有" ...

  8. g711u与g729比较编码格式

    •g711a—编解码格式为G.711 alaw •g711u—编解码格式为G.711 ulaw (the default) •g729—编解码格式为G.729 •g729a—编解码格式为G.729a ...

  9. SPOJ BALNUM Balanced Numbers(数位DP+状态压缩)题解

    思路: 把0~9的状态用3进制表示,数据量3^10 代码: #include<cstdio> #include<map> #include<set> #includ ...

  10. sqlite中的时间

    插入时间的sql语句 ','-61') 时间格式'2014-11-17T19:37:32' 年月日和时分秒之间多了一个字母T,保存到数据库的时候,会自动给时间加8个小时. 保存的结果为2014-11- ...