ASP.NET Redis 开发

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介:

文件并发(日志处理)--队列--Redis+Log4Net

Redis简介

Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高并发的应用场景。Redis纯粹为应用而产生,它是一个高性能的key-value数据库,并且提供了多种语言的API

性能测试结果表示SET操作每秒钟可达110000次,GET操作每秒81000次(当然不同的服务器配置性能不同)。

Redis目前提供五种数据类型:string(字符串),list(链表), Hash(哈希),set(集合)及zset(sorted set)  (有序集合)

Redis开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

RedisMemcached的比较.

1.Memcached是多线程,而Redis使用单线程.

2.Memcached使用预分配的内存池的方式,Redis使用现场申请内存的方式来存储数据,并且可以配置虚拟内存。

3.Redis可以实现持久化,主从复制,实现故障恢复。

4.Memcached只是简单的keyvalue,但是Redis支持数据类型比较多。

Redis的存储分为内存存储、磁盘存储 .从这一点,也说明了RedisMemcached是有区别的。Redis Memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改 操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aofappend only mode,在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作上,这样就看出aof是一个非常不协调的部分。

其实aof目的主要是数据可靠性及高可用性.

Redis安装

文章的最后我提供了下载包,当然你也可以去官网下载最新版本的Redis https://github.com/dmajkic/redis/downloads 

将服务程序拷贝到一个磁盘上的目录,如下图:

文件说明:

redis-server.exe:服务程序  

redis-check-dump.exe:本地数据库检查 

redis-check-aof.exe:更新日志检查 

redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询.

redis-cli.exe: 服务端开启后,我们的客户端就可以输入各种命令测试了 

1、打开一个cmd窗口,使用cd命令切换到指定目录(F:\Redis)运行 redis-server.exe redis.conf 

2、重新打开一个cmd窗口,使用cd命令切换到指定目录(F:\Redis)运行 redis-cli.exe -h 127.0.0.1 -p 6379,其中 127.0.0.1是本地ip6379redis服务端的默认端口 (这样可以开启一个客户端程序进行特殊指令的测试).

可以将此服务设置为windows系统服务,下载Redis服务安装软件,安装即可。(https://github.com/rgl/redis/downloads 

如果你的电脑是64bit系统,可以下载redis-2.4.6-setup-64-bit.exe

安装完成Redis服务后,我们会在计算机的服务里面看到

然后启动此服务。

接下来在使用Redis时,还需要下载C#驱动(也就是C#开发库),如下图:

Redis常用数据类型

使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数据结构和数据操作,为不同的大象构建不同的冰箱。

 Redis最为常用的数据类型主要有以下五种: 

  •    String
  •    Hash
  •    List
  •    Set
  •    Sorted set

String类型

String是最常用的一种数据类型,普通的key/value存储都可以归为此类 。一个Key对应一个Value,string类型是二进制安全的。Redisstring可以包含任何数据,比如jpg图片(生成二进制)或者序列化的对象。基本操作如下:

  1.  var client = new RedisClient("127.0.0.1", 6379);  
  2.             client.Set<int>("pwd", 1111);  
  3.             int pwd=client.Get<int>("pwd");  
  4.             Console.WriteLine(pwd);  
  5.    
  6. UserInfo userInfo = new UserInfo() { UserName = "zhangsan", UserPwd = "1111" };//</span>(底层使用json序列化 )  
  7. client.Set<UserInfo>("userInfo", userInfo);  
  8. UserInfo user=client.Get<UserInfo>("userInfo");  
  9. Console.WriteLine(user.UserName);  
  10.   
  11. List<UserInfo> list = new List<UserInfo>() { new UserInfo(){UserName="lisi",UserPwd="111"},new UserInfo(){UserName="wangwu",UserPwd="123"} };  
  12. client.Set<List<UserInfo>>("list",list);  
  13. List<UserInfo>userInfoList=client.Get<List<UserInfo>>("list");  
  14.   
  15.  foreach (UserInfo userInfo in userInfoList)  
  16.    {  
  17.        Console.WriteLine(userInfo.UserName);  
  18.    }  

Hash类型

Hash是一个string 类型的fieldvalue的映射表。hash特别适合存储对象。相对于将对象的每个字段存成单个string 类型。一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。

作为一个key value存在,很多开发者自然的使用set/get方式来使用Redis,实际上这并不是最优化的使用方法。尤其在未启用VM情况下,Redis全部数据需要放入内存,节约内存尤其重要.

增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回 

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争 .. redis是个单线程的程序,为什么会这么快呢 ?

1、大量线程导致的线程切换开销

2、锁、

3、非必要的内存拷贝。 

4. Redis多样的数据结构,每种结构只做自己爱做的事.

Hash对应的Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个HashMap的成员比较少时,Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,当成员量增大时会自动转成真正的HashMap. 

Key仍然是用户ID, value是一个Map,这个Mapkey是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部MapKey(Redis里称内部Mapkeyfield), 也就是通过 key(用户ID) + field(属性标签就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和反序列化

  1. client.SetEntryInHash("user", "userInfo", "aaaaaaaaaa");  
  2. List<string> list = client.GetHashKeys("user");  
  3. List<string> list = client.GetHashValues("userInfo");//获取值  
  4. List<string> list = client.GetAllKeys();//获取所有的key。  

Redis为不同数据类型分别提供了一组参数来控制内存使用,我们在前面提到过的Redis Hashvalue内部是一个

HashMap,如果该Map的成员比较少,则会采用一维数组的方式来紧凑存储该MAP,省去了大量指针的内存开销,这个参数在redis,conf配置文件中下面2项。

Hash-max-zipmap-entries 64

Hash-max-zipmap-value 512.

含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个以下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap.

Hash-max-zipmap-value含义是当value这个MAP内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。以上两个条件任意一个条件超过设置值都会转成真正的HashMap,也就不会再节省内存了,这个值设置多少需要权衡,HashMap的优势就是查找和操作时间短。

一个key可对应多个field,一个field对应一个value   

这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意 

建议使用对象类别和ID构成键名,使用字段表示对象属性,字

段值存储属性值,例如:car:2 price 500

List类型

list是一个链表结构,主要功能是push,pop,获取一个范围的所有的值等,操作中key理解为链表名字。 Redislist类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,又可以作为队列。Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构

  1. //队列使用  
  2.   
  3.  client.EnqueueItemOnList("name", "zhangsan");  
  4.            client.EnqueueItemOnList("name", "lisi");  
  5.            int count= client.GetListCount("name");  
  6.            for (int i = 0; i < count; i++)  
  7.            {  
  8.               Console.WriteLine(client.DequeueItemFromList("name"));  
  9.            }  
  10.   
  11. //栈使用  
  12.             client.PushItemToList("name2", "wangwu");  
  13.             client.PushItemToList("name2", "maliu");  
  14.             int count = client.GetListCount("name2");  
  15.             for (int i = 0; i < count; i++)  
  16.             {  
  17.                 Console.WriteLine(client.PopItemFromList("name2"));  
  18.             }  

Set类型

它是string类型的无序集合。set是通过hash table实现的,添加,删除和查找,对集合我们可以取并集,交集,差集.

  1. //对Set类型进行操作  
  2.             client.AddItemToSet("a3", "ddd");  
  3.             client.AddItemToSet("a3", "ccc");  
  4.             client.AddItemToSet("a3", "tttt");  
  5.             client.AddItemToSet("a3", "sssh");  
  6.             client.AddItemToSet("a3", "hhhh");  
  7.             System.Collections.Generic.HashSet<string>hashset=client.GetAllItemsFromSet("a3");  
  8.             foreach (string str in hashset)  
  9.             {  
  10.                 Console.WriteLine(str);  
  11.             }  
  12.   
  13. //求并集  
  14. client.AddItemToSet("a3", "ddd");  
  15.             client.AddItemToSet("a3", "ccc");  
  16.             client.AddItemToSet("a3", "tttt");  
  17.             client.AddItemToSet("a3", "sssh");  
  18.             client.AddItemToSet("a3", "hhhh");  
  19.             client.AddItemToSet("a4", "hhhh");  
  20.             client.AddItemToSet("a4", "h777");  
  21.  System.Collections.Generic.HashSet<string>hashset=  client.GetUnionFromSets(new string[] { "a3","a4"});  
  22.   
  23.           foreach (string str in hashset)  
  24.           {  
  25.               Console.WriteLine(str);  
  26.           }  
  27.   
  28. //求交集  
  29.  System.Collections.Generic.HashSet<string> hashset = client.GetIntersectFromSets(new string[] { “a3”, “a4” });  
  30.   
  31. //求差集.  
  32.  System.Collections.Generic.HashSet<string> hashset = client.GetDifferencesFromSet("a3",new string[] { "a4"});  

返回存在于第一个集合,但是不存在于其他集合的数据。差集

Sorted Set类型

sorted set set的一个升级版本,它在set的基础上增加了一个顺序的属性,这一属性在添加修改   .元素的时候可以指定,每次指定后,zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表,一列存 value,一列存顺序。操作中key理解为zset的名字.

Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构, 

  1. client.AddItemToSortedSet("a5", "ffff");  
  2.            client.AddItemToSortedSet("a5","bbbb");  
  3.            client.AddItemToSortedSet("a5", "gggg");  
  4.            client.AddItemToSortedSet("a5", "cccc");  
  5.            client.AddItemToSortedSet("a5", "waaa");  
  6.            System.Collections.Generic.List<string> list =client.GetAllItemsFromSortedSet("a5");  
  7.            foreach (string str in list)  
  8.            {  
  9.                Console.WriteLine(str);  
  10.            }  

给Redis设置密码

安装redis服务器后,不能让其在外网环境下面裸奔啊,我们可以为其设置一个复杂的访问密码,最好20位以上,这样可以有效防止别人暴力破解。

找到redis的配置文件,默认在这个地方:C:\Program Files\Redis\conf\redis.conf,查找requirepass选项配置

把这个选项前面的#注释干掉,然后在后面添加一个复杂的密码

# use a very strong password otherwise it will be very easy to break.
#
requirepass 2016@Test.88210_yujie

# Command renaming.

带密码的访问

  var client = new RedisClient("192.168.2.154", 6379); //ip和端口
  client.Password = "2016@Test.88210_yujie"; //redis访问密码

ServiceStack.Redis源码:https://github.com/ServiceStack/ServiceStack.Redis

注:此文使用的redis C#驱动是1.0版本,目前最新版本为4.0,而且已经开源。

4.0版操作Demo如下:

  View Code

RedisHelper类如下:

复制代码
   public static class RedisHelper
    {
        #region static field

        static string host = "192.168.2.154";/*访问host地址*/
        static string password = "2016@Msd.1127_kjy";/*实例id:密码*/
        static readonly RedisClient client = new RedisClient(host, 6379, password);

        #endregion
        #region
        /// <summary>
        /// 获取信息
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <returns>对象</returns>
        public static T Get<T>(string token) where T : class,new()
        {
            return client.Get<T>(token);
        }
       /// <summary>
       /// 设置信息
       /// </summary>
       /// <typeparam name="T">对象类型</typeparam>
       /// <param name="token">key</param>
       /// <param name="obj">对象</param>
       public static void Set<T>(string token,T obj) where T:class,new()
       {
         client.Set<T>(token, obj);
       }
       /// <summary>
       /// 设置指定Key的过期时间
       /// </summary>
       /// <param name="token">具体的key值</param>
       /// <param name="seconds">过期时间,单位:秒</param>
       public static void Expire(string token,int seconds)
       {
           client.Expire(token, seconds);
       }
        #endregion
    }
复制代码

特别说明:ServiceStack.Redis从4.0开始商用,有每小时6000次访问的限制,如果要在生产环境使用,建议使用低版本。

Redis工具和所需资料代码全下载,地址:http://pan.baidu.com/s/155F6A


本文转自邹琼俊博客园博客,原文链接:http://www.cnblogs.com/jiekzou/p/4487356.html,如需转载请自行联系原作者

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
9天前
|
设计模式 开发框架 JavaScript
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
108 3
|
8天前
|
存储 缓存 NoSQL
2款使用.NET开发的数据库系统
2款使用.NET开发的数据库系统
|
8天前
|
开发框架 JavaScript 前端开发
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
|
1月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
34 1
|
1月前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
1月前
|
NoSQL API Redis
如何使用 C++ 开发 Redis 模块
如何使用 C++ 开发 Redis 模块
|
1月前
|
C# Windows
一款基于.NET开发的简易高效的文件转换器
一款基于.NET开发的简易高效的文件转换器
下一篇
无影云桌面