设为首页 收藏本站
查看: 1056|回复: 0

[经验分享] 菜鸟爬坑--Redis学习与探索(二):Redis的数据类型

[复制链接]

尚未签到

发表于 2015-7-20 09:32:23 | 显示全部楼层 |阅读模式
.NET使用Redis
  和MongoDB一样,在.NET中使用Redis其实也是使用第三方驱动,官网推荐的是使用ServiceStack.Redis
DSC0000.png
  不过看CapQueen的博客时,有提到ServiceStack.Redis 4.0开始收费了,3.9功能不是特别全,一些地方存在不足。而使用了 StactkExchange.Redis ,具体以后详细研究,这里还是使用了ServiceStack.Redis 。
DSC0001.png
  点击下载压缩包,解压 ServiceStack.Redis-master.zip\ServiceStack.Redis-master\build\release\MonoDevelop  下的ServiceStack.Redis.zip 压缩包 DSC0002.png
  会有4个dll,我们直接在项目中添加引用即可。
Redis数据类型
  Redis目前提供五种数据类型:string(字符串)、list(链表)、Hash(哈希)、set(集合)及zset(sorted set)  (有序集合)。下面我们来一一实践一下。
String类型
  String是最常用的一种数据类型,普通的key/value存储都可以归为此类。一个Key对应一个Value,string类型是二进制安全的。Redis的string可以包含任何数据,比如jpg图片(生成二进制)或者序列化的对象。
  示例:


DSC0003.gif DSC0004.gif


1 using ServiceStack.Redis;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace String
9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             RedisClient client = new RedisClient("127.0.0.1", 6379);
15             Console.WriteLine("请输入用户名:");
16             string username = Console.ReadLine();
17             client.Set("username", username);
18         
19             int exist=client.Exists("username");
20             Console.WriteLine("是否添加到Redis:" + exist.ToString());// 存在返回1,否则返回0
21           
22             username = client.Get("username");
23             Console.WriteLine("获取刚刚输入用户名:" + username);
24
25             int a= client.Del("username");//删除已存在的key 成功返回1
26             int b = client.Del("username2");//删除不存在的key,失败返回0
27             Console.WriteLine("输出删除结果:" +a.ToString()+","+b.ToString());
28             Console.ReadKey();
29         }
30     }
31 }
View Code  
DSC0005.png
Hash类型
  hash是一个string 类型的field和value的映射表。hash特别 适合存储对象。相对于将对象的每个字段存成单个string 类型。一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是新建一个hash对象时开始是用zipmap(又称为small hash)来存储的。这个zipmap其实并不是hash table,但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销。尽管zipmap的添加,删除,查找都是O(n),但是由于一般对象的field数量都不太多。所以使用zipmap也是很快的,也就是说添加删除平均还是O(1)。如果field或者value的大小超出一定限制后,redis会在内部自动将zipmap替换成正常的hash实现. 这个限制可以在配置文件中指定。
DSC0006.png
  如上图。Redis的Hash实际是内部存储的Value为一个HashMap,这个HashMap的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部HashMap的Key(Redis里称内部HashMap的key为field), 也就是通过key(用户ID) + field(属性标签) 就可以操作对应属性数据了。
  示例:





1 using ServiceStack.Redis;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace String
9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             RedisClient client = new RedisClient("127.0.0.1", 6379);
15             Console.WriteLine("请输入用户名:");
16             string username = Console.ReadLine();
17             Console.WriteLine("请输入密码:");
18             string password = Console.ReadLine();
19             client.SetEntryInHash("userinfo", "username", username);
20             client.SetEntryInHash("userinfo", "password", password);
21             List keylist = client.GetHashKeys("userinfo");
22             List valuelist = client.GetHashValues("userinfo");
23             for (int i = 0; i < keylist.Count; i++)
24             {
25                 Console.WriteLine("key为:{0},value为:{1}", keylist, valuelist);
26             }
27             Console.ReadKey();
28         }
29     }
30 }
View Code DSC0007.png
List类型
  list是一个链表结构,主要功能是push,pop,获取一个范围的所有的值等,操作中key理解为链表名字。 Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,又可以作为队列。


Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

示例:






1 using ServiceStack.Redis;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace String
9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             RedisClient client = new RedisClient("127.0.0.1", 6379);
15             Console.WriteLine("请输入第一个数:");
16             string num1 = Console.ReadLine();
17             Console.WriteLine("请输入第二个数:");
18             string num2 = Console.ReadLine();
19             //队列
20             client.EnqueueItemOnList("queue", num1);
21             client.EnqueueItemOnList("queue", num2);
22             int Qcount = client.GetListCount("queue");
23             Console.WriteLine("输出队列:");
24             for (int i = 0; i < Qcount; i++)
25             {
26                 Console.Write(client.DequeueItemFromList("queue")+",");
27             }
28             Console.WriteLine("\n");
29             //栈
30             client.PushItemToList("stack", num1);
31             client.PushItemToList("stack", num2);
32             int Scount = client.GetListCount("stack");
33             Console.WriteLine("输出栈:");
34             for (int i = 0; i < Scount; i++)
35             {
36                 Console.Write(client.PopItemFromList("stack") + ",");
37             }
38             Console.ReadKey();
39         }
40     }
41 }
View Code DSC0008.png
  看以看出队列是FIFO,先入先出,而队列是LIFO,后入先出,具体的等后续有时间来填填数据结构的坑。

  Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。


Set类型
  在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295。
      和List类型不同的是,Set集合中不允许出现重复的元素,这一点和C++标准库中的set容器是完全相同的。换句话说,如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。
  示例:





1 using ServiceStack.Redis;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace String
9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             RedisClient client = new RedisClient("127.0.0.1", 6379);
15             client.AddItemToSet("a", "aaaa1");
16             client.AddItemToSet("a", "aaaa2");
17             client.AddItemToSet("a", "aaaa3");
18             Console.WriteLine("输出Set a:");
19             System.Collections.Generic.HashSet hashset = client.GetAllItemsFromSet("a");
20             foreach (string str in hashset)
21             {
22                 Console.WriteLine(str);
23             }
24
25             Console.ReadKey();
26         }
27     }
28 }
View Code DSC0009.png
  可以看出 Set 是无序的。
  我们也可以对多个Set进行聚合等操作
  例如:



            System.Collections.Generic.HashSet hashset = client.GetUnionFromSets(new string[] { "a", "b" });//求并集
hashset = client.GetIntersectFromSets(new string[] { "a", "b" });//求交集
hashset = client.GetDifferencesFromSet("a", new string[] { "b" });//求差集
  应用场景:   

  1). 可以使用Redis的Set数据类型跟踪一些唯一性数据,比如访问某一博客的唯一IP地址信息。对于此场景,我们仅需在每次访问该博客时将访问者的IP存入Redis中,Set数据类型会自动保证IP地址的唯一性。
      2). 充分利用Set类型的服务端聚合操作方便、高效的特性,可以用于维护数据对象之间的关联关系。比如所有购买某一电子设备的客户ID被存储在一个指定的Set中,而购买另外一种电子产品的客户ID被存储在另外一个Set中,如果此时我们想获取有哪些客户同时购买了这两种商品时,Set的intersections命令就可以充分发挥它的方便和效率的优势了。

  
Sorted Set类型


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





1 using ServiceStack.Redis;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace String
9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             RedisClient client = new RedisClient("127.0.0.1", 6379);
15             client.AddItemToSortedSet("s", "123");
16             client.AddItemToSortedSet("s", "456");
17             client.AddItemToSortedSet("s", "789");
18             client.AddItemToSortedSet("s", "1234");
19             client.AddItemToSortedSet("s", "56789");
20             System.Collections.Generic.List list = client.GetAllItemsFromSortedSet("s");
21             foreach (string str in list)
22             {
23                 Console.WriteLine(str);
24             }
25             Console.ReadKey();
26         }
27     }
28 }
View Code DSC00010.png
  应用场景:   


Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构。
  1). 可以用于一个大型在线游戏的积分排行榜。每当玩家的分数发生变化时,可以执行ZADD命令更新玩家的分数,此后再通过ZRANGE命令获取积分TOP TEN的用户信息。当然我们也可以利用ZRANK命令通过username来获取玩家的排行信息。最后我们将组合使用ZRANGE和ZRANK命令快速的获取和某个玩家积分相近的其他用户的信息。
  2). Sorted-Sets类型还可用于构建索引数据。


参考文献
  1.传智播客-Redis公开课,感谢传智播客
  2.Stephen Liu的Redis学习手册(目录):http://www.iyunv.com/stephen-liu74/archive/2012/04/16/2370212.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-88521-1-1.html 上篇帖子: 利用servicestack连接redis 下篇帖子: Redis 介绍2——常见基本类型
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表