Redis 学习记录
简介:
Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSql数据库系统。特点是高性能,持久存储,适用高并发的应用场景。redis纯粹为应用而生,它是一个高性能的key-value数据库,并且提供了多种语言的API,性能测试结果表示SET操作每秒可达110000次,GET操作每秒可达81000次(当然不同的服务器配置性能不同)。
Redis目前提供了五种数据类型,string(字符串),list(链表),Hash(哈希),set (集合),zset(sorted set)(有序集合)
Redis与Memcached的比较
1、Memcached是多线程,Redis是单线程。
2、Memcached使用预分配的内存池的方式,Redis使用现场申请内存的方式来存储数据,并且可以配置虚拟缓存
3、Redis可以实现持久化,主从复制,实现故障恢复。
4、Memcached只是简单的Key与value,但是Redis支持的类型比较多
Redis的存储分为内存存储、磁盘存储,从这一点,也说明了Redis与Memcached是有区别的。Redis与Memcached一样,为了保证效率,数据都是缓存在内存中。区别是Redis会周期性的吧更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis是一个支持持久化的内存数据库,也就是说Redis需要经常将内存中的数据同步到硬盘中保证持久化。
Redis支持两种持久化方式
(1)、snapshotting(快照)也是默认方式(把数据做一个备份,将数据存储到文件)
(2)、Append-Only file(缩写AOF)的方式
快照是默认的持久化方式,这种方式是将内存中数据以快照的方式写到二进制文件中,默认的文件名称为dump.rdb可以通过配置设置自动做快照持久化的方式。我们可以配置Redis在n秒内如果m个key键修改就自动做快照。
aof方式:由于快照方式是在一定时间间隔做一次的,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。aof比快照方式有更好的持久化性,是由于在使用aof是,Redis会将每一个收到的写命令都通过write函数追加到文件中,当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
Redis安装
下载Redis:https://github.com/dmajkic/redis/downloads
安装包中:
redis-server.exe :服务程序
redis-chaeck-aof.exe:更新日志检查
redis-benchmark.exe:性能测试,用以模拟同时又N个客户端发送M个SETs/GETs查询
redis-cli.exe:服务端开启后,我们的客户端就可以输入各种命令测试了
将Redis安装到Windows服务中:
安装服务下载地址:https://github.com/MicrosoftArchive/redis/releases
下载之后傻瓜式安装就可以了
在程序中使用Redis还需要下载驱动:驱动下载
Redis代码实例
1 IRedisClientsManager clientManager = new PooledRedisClientManager(new string[] { "127.0.0.1:6379" }); 2 IRedisClient redisClent = clientManager.GetClient(); 3 redisClent.FlushAll(); 4 5 #region String数据类型 6 redisClent.Add<string>("stringkey", "I Love You", DateTime.Now.AddSeconds(5)); 7 while (true) 8 { 9 if (redisClent.ContainsKey("stringkey")) 10 { 11 Console.WriteLine("String数据类型的键stringkey的值{0}{1}", redisClent.Get<string>("stringkey"), DateTime.Now.ToString()); 12 Thread.Sleep(1000); 13 } 14 else 15 { 16 Console.WriteLine("String数据类型的键stringkey的值已过期"); 17 break; 18 } 19 } 20 21 Student stud = new Student() { id = 1001, name = "李四" }; 22 redisClent.Add<Student>("StringEntity", stud); 23 Student Get_stud = redisClent.Get<Student>("StringEntity"); 24 Console.WriteLine("数据类型为:String.键:StringEntity,值:{0} {1}", Get_stud.id, Get_stud.name); 25 26 #endregion 27 28 #region Hash数据类型 29 redisClent.SetEntryInHash("Id-1", "Name", "张三"); 30 redisClent.SetEntryInHash("Id-1", "Age", "28"); 31 redisClent.SetEntryInHash("Id-1", "Sex", "男"); 32 33 List<string> hasKey = redisClent.GetHashKeys("Id-1"); 34 foreach (string key in hasKey) 35 { 36 Console.WriteLine("Id-1--Key:{0},value:{1}", key, redisClent.GetValueFromHash("Id-1", key)); 37 } 38 39 List<string> AllKey = redisClent.GetAllKeys(); //获取所有的key。 40 foreach (string Key in AllKey) 41 { 42 Console.WriteLine("AllKey--Key:{0}", Key); 43 } 44 #endregion 45 46 #region List 链表 47 /* 48 * list是一个链表结构,主要功能是push,pop,获取一个范围的所有的值等,操作中key理解为链表名字。 49 * Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素, 50 * 这样list既可以作为栈,又可以作为队列。Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销, 51 * Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构 52 */ 53 redisClent.EnqueueItemOnList("QueueListId", "1.张三"); //入队 54 redisClent.EnqueueItemOnList("QueueListId", "2.张四"); 55 redisClent.EnqueueItemOnList("QueueListId", "3.王五"); 56 redisClent.EnqueueItemOnList("QueueListId", "4.王麻子"); 57 int q = redisClent.GetListCount("QueueListId"); 58 for (int i = 0; i < q; i++) 59 { 60 Console.WriteLine("QueueListId出队值:{0}", redisClent.DequeueItemFromList("QueueListId")); //出队(队列先进先出) 61 } 62 63 redisClent.PushItemToList("StackListId", "1.张三"); //入栈 64 redisClent.PushItemToList("StackListId", "2.张四"); 65 redisClent.PushItemToList("StackListId", "3.王五"); 66 redisClent.PushItemToList("StackListId", "4.王麻子"); 67 int p = redisClent.GetListCount("StackListId"); 68 for (int i = 0; i < p; i++) 69 { 70 Console.WriteLine("StackListId出栈值:{0}", redisClent.PopItemFromList("StackListId")); //出栈(栈先进后出) 71 } 72 #endregion 73 74 #region Set 无序集合 75 redisClent.AddItemToSet("SetA", "A"); 76 redisClent.AddItemToSet("SetA", "B"); 77 redisClent.AddItemToSet("SetA", "C"); 78 redisClent.AddItemToSet("SetA", "D"); 79 redisClent.AddItemToSet("SetA", "E"); 80 HashSet<string> hasSetA = redisClent.GetAllItemsFromSet("SetA"); 81 foreach (string key in hasSetA) 82 { 83 Console.WriteLine("Set无序集合ValueA:{0}", key); //出来的结果是无须的 84 85 } 86 87 redisClent.AddItemToSet("SetB", "D"); 88 redisClent.AddItemToSet("SetB", "E"); 89 redisClent.AddItemToSet("SetB", "F"); 90 redisClent.AddItemToSet("SetB", "G"); 91 redisClent.AddItemToSet("SetB", "H"); 92 HashSet<string> hasSetB = redisClent.GetAllItemsFromSet("SetB"); 93 foreach (string key in hasSetB) 94 { 95 Console.WriteLine("Set无序集合ValueB:{0}", key); //出来的结果是无须的 96 97 } 98 99 HashSet<string> hashUnion = redisClent.GetUnionFromSets(new string[] { "SetA", "SetB" }); 100 foreach (string item in hashUnion) 101 { 102 Console.WriteLine("求SetA和SetB的并集:{0}", item); //并集 103 } 104 105 HashSet<string> hashG = redisClent.GetIntersectFromSets(new string[] { "SetA", "SetB" }); 106 foreach (string item in hashG) 107 { 108 Console.WriteLine("求SetA和SetB的交集:{0}", item); //交集 109 } 110 111 HashSet<string> hashD = redisClent.GetDifferencesFromSet("SetA", new string[] { "SetB" }); //[返回存在于第一个集合,但是不存在于其他集合的数据。差集] 112 foreach (string item in hashD) 113 { 114 Console.WriteLine("求SetA和SetB的差集:{0}", item); //差集 115 } 116 #endregion 117 118 #region SetSorted 有序集合 119 /* 120 sorted set 是set的一个升级版本,它在set的基础上增加了一个顺序的属性,这一属性在添加修改.元素的时候可以指定, 121 * 每次指定后,zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表,一列存 value,一列存顺序。操作中key理解为zset的名字. 122 */ 123 redisClent.AddItemToSortedSet("SetSorted1001", "1.刘仔"); 124 redisClent.AddItemToSortedSet("SetSorted1001", "2.星仔"); 125 redisClent.AddItemToSortedSet("SetSorted1001", "3.猪仔"); 126 List<string> listSetSorted = redisClent.GetAllItemsFromSortedSet("SetSorted1001"); 127 foreach (string item in listSetSorted) 128 { 129 Console.WriteLine("SetSorted有序集合{0}", item); 130 } 131 #endregion 132 Console.ReadKey();
参考文章:https://www.cnblogs.com/caokai520/p/4409712.html