概念
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。
Redis 与 Memcached 区别
- Memcached是多线程,而Redis使用单线程。(个人认为Memcached在读写处理速度上由于Redis)
- Memcached使用预分配的内存池的方式,Redis使用现场申请内存的方式来存储数据,并且可以配置虚拟内存。
- Redis可以实现持久化(也就是说redis需要经常将内存中的数据同步到硬盘中来保证持久化),主从复制,实现故障恢复。
- Memcached只是简单的key与value,但是Redis支持数据类型比较多。包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
Redis支持两种持久化方式:
(1):snapshotting(快照)也是默认方式.(把数据做一个备份,将数据存储到文件)
(2)Append-only file(缩写aof)的方式
快照是默认的持久化方式,这种方式是将内存中数据以快照的方式写到二进制文件中,默认的文件名称为dump.rdb.可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key键修改就自动做快照.
aof方式:由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
Windows安装Redis
以cmd安装方法:
1.下载安装包:https://github.com/dmajkic/redis/downloads
2.安装包下载后根据操作系统选择对应版本文件,里面会有几个dll分别为:
redis-server.exe:服务程序
redis-check-dump.exe:本地数据库检查
redis-check-aof.exe:更新日志检查
redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询.
redis-cli.exe: 服务端开启后,我们的客户端就可以输入各种命令测试了
首先以管理员身份打开cmd (窗口+R),进入到安装包下载的位置。输入:redis-server.exe redis.conf 开启Redis服务。提示信息没有报错表示启动成功。
此窗口要保持开启状态,如果关闭Redis服务也会相即被关闭。使用客户端测试一下数据。
现在来观察Redis是怎么持久化存储数据到硬盘上。(快照是默认的持久化方式,默认的文件名称为dump.rdb)
可以看到Redis服务端在一段时间后将数据库保存在磁盘上,文件为:dump.rdb。
以weindows服务安装Redis方法:
下载Redis服务安装包:https://github.com/rgl/redis/downloads
下载完成后直接点击.exe下一步下一步OK。安装完后我们会在windows服务中找到Redis Service服务。注意启动服务后在进行相关测试。
代码实例
在调用Redis服务前需要准备三个DLL。下载地址:【Redis调用驱动】在项目中引用即可。
使用Redis中存储常用的5种数据类型:String,Hash,List,SetSorted set编写实例代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using ServiceStack; 8 using ServiceStack.ServiceInterface; 9 using ServiceStack.Redis; 10 using System.Threading; 11 12 namespace RedisDemo 13 { 14 class Student 15 { 16 public string Id { get; set; } 17 public string Name { get; set; } 18 19 public string Address { get; set; } 20 } 21 class Program 22 { 23 static void Main(string[] args) 24 { 25 //在Redis中存储常用的5种数据类型:String,Hash,List,SetSorted set 26 RedisClient client = new RedisClient("192.168.0.103", 6379); 27 client.FlushAll();//clear 28 29 #region string type 30 client.Add<string>("StringKey01", "设置时间30秒消失", DateTime.Now.AddMilliseconds(3000)); 31 32 while (true) 33 { 34 if (client.ContainsKey("StringKey01")) 35 { 36 Console.WriteLine($"string键:stringvalue 值{client.Get<string>("StringKey01")} {DateTime.Now}"); 37 Thread.Sleep(1000); 38 } 39 else 40 { 41 Console.WriteLine("键:StringValue,值:我已过期 {0}", DateTime.Now); 42 break; 43 } 44 45 } 46 client.Add<string>("StringKey02", "String和Memcached操作方法差不多"); 47 Console.WriteLine($"数据类型为“string”,键为:{"StringKey01"},值为:{client.Get<string>("StringKey02")}"); 48 49 Student student = new Student() { Id = "001", Name = "Tom", Address = "大兴区" }; 50 client.Add<Student>("StudentEntity", student); 51 52 Student getStudent = client.Get<Student>("StudentEntity"); 53 Console.WriteLine($"学生ID:{getStudent.Id}"); 54 Console.WriteLine($"名称:{getStudent.Name}"); 55 Console.WriteLine($"地址:{getStudent.Address}"); 56 #endregion 57 58 #region Hash 59 client.SetEntryInHash("HashId01", "Name", "张三"); 60 client.SetEntryInHash("HashId01", "Age", "26"); 61 client.SetEntryInHash("HashId01", "Sex", "女"); 62 client.SetEntryInHash("HashId01", "Address", "北京市大兴区"); 63 64 List<string> hashKey = client.GetHashKeys("HashId01"); 65 66 foreach (string key in hashKey) 67 { 68 Console.WriteLine("HashID--Key:{0}", key); 69 } 70 71 List<string> hashValue = client.GetHashValues("HashId01"); 72 73 foreach (string value in hashValue) 74 { 75 Console.WriteLine("HashID--Value:{0}", value); 76 } 77 78 List<string> allKey = client.GetAllKeys(); 79 80 foreach (string key in allKey) 81 { 82 Console.WriteLine("AllKey--Key:{0}", key); 83 } 84 85 #endregion 86 87 #region List 88 89 /* 90 * list是一个链表结构,主要功能是push,pop,获取一个范围的所有的值等,操作中key理解为链表名字。 91 * Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素, 92 * 这样list既可以作为栈,又可以作为队列。Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销, 93 * Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构 94 */ 95 96 client.EnqueueItemOnList("QueueListId01", "1~zhangsan1"); 97 client.EnqueueItemOnList("QueueListId01", "2~zhangsan2"); 98 client.EnqueueItemOnList("QueueListId01", "3~zhangsan3"); 99 client.EnqueueItemOnList("QueueListId01", "4~zhangsan4"); 100 client.EnqueueItemOnList("QueueListId01", "5~zhangsan5"); 101 client.EnqueueItemOnList("QueueListId01", "6~zhangsan6"); 102 103 int count = client.GetListCount("QueueListId01"); 104 105 for (int i = 0; i < count; i++) 106 { 107 Console.WriteLine("QueueListId01出队值:{0}", client.DequeueItemFromList("QueueListId01")); //出队(队列先进先出) 108 } 109 110 111 client.PushItemToList("StackListId01", "7~666"); 112 client.PushItemToList("StackListId01", "8~666"); 113 client.PushItemToList("StackListId01", "9~666"); 114 client.PushItemToList("StackListId01", "10~666"); 115 client.PushItemToList("StackListId01", "11~666"); 116 client.PushItemToList("StackListId01", "12~666"); 117 client.PushItemToList("StackListId01", "13~666"); 118 119 int count1 = client.GetListCount("StackListId01"); 120 121 for (int i = 0; i < count1; i++) 122 { 123 Console.WriteLine("StackListId01出栈值:{0}", client.PopItemFromList("StackListId01")); //出队(队列先进先出) 124 } 125 #endregion 126 127 #region Set无序集合 128 /* 129 它是string类型的无序集合。set是通过hash table实现的,添加,删除和查找,对集合我们可以取并集,交集,差集 130 */ 131 132 client.AddItemToSet("Set01", "小A"); 133 client.AddItemToSet("Set01", "小B"); 134 client.AddItemToSet("Set01", "小C"); 135 client.AddItemToSet("Set01", "小D"); 136 client.AddItemToSet("Set01", "小E"); 137 138 HashSet<string> hashSetA = client.GetAllItemsFromSet("Set01"); 139 140 foreach(string item in hashSetA) 141 { 142 Console.WriteLine("hashSetA:{0}", item); //出来的结果是无须的 143 } 144 145 client.AddItemToSet("Set02", "小K"); 146 client.AddItemToSet("Set02", "小C"); 147 client.AddItemToSet("Set02", "小A"); 148 client.AddItemToSet("Set02", "小J"); 149 HashSet<string> hastsetB = client.GetAllItemsFromSet("Set02"); 150 foreach (string item in hastsetB) 151 { 152 Console.WriteLine("Set无序集合hastsetB:{0}", item); //出来的结果是无须的 153 } 154 155 HashSet<string> hashUnion = client.GetUnionFromSets(new string[] { "Set01", "Set02" }); 156 157 foreach (string item in hashUnion) 158 { 159 Console.WriteLine("Set无序集合hashUnion:{0}", item); //并集 160 } 161 162 HashSet<string> hashIntersect = client.GetIntersectFromSets(new string[] { "Set01", "Set02" }); 163 164 foreach (string item in hashIntersect) 165 { 166 Console.WriteLine("Set无序集合hashIntersect:{0}", item); //交集 167 } 168 169 HashSet<string> hashDiff = client.GetDifferencesFromSet("Set01", new string[] { "Set02" }); //[返回存在于第一个集合,但是不存在于其他集合的数据。差集] 170 foreach (string item in hashDiff) 171 { 172 Console.WriteLine("求Set01和Set02的差集:{0}", item); //差集 173 } 174 175 #endregion 176 177 #region SetSorted 有序集合 178 /* 179 sorted set 是set的一个升级版本,它在set的基础上增加了一个顺序的属性,这一属性在添加修改.元素的时候可以指定, 180 * 每次指定后,zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表,一列存 value,一列存顺序。操作中key理解为zset的名字. 181 */ 182 client.AddItemToSortedSet("SetSorted1001", "1.刘仔"); 183 client.AddItemToSortedSet("SetSorted1001", "2.星仔"); 184 client.AddItemToSortedSet("SetSorted1001", "3.猪仔"); 185 List<string> listSetSorted = client.GetAllItemsFromSortedSet("SetSorted1001"); 186 ) 187 foreach (string item in listSetSorted) 188 { 189 Console.WriteLine("SetSorted有序集合{0}", item); 190 } 191 #endregion 192 193 Console.ReadLine(); 194 195 } 196 } 197 }
总结
Redis的存储容灾性比较完善,所支持的存储数据类型比较全。比较坑的是版本2.X之下都不支持服务器集群,只能单机。在Redis 3.0中服务器集群功能才亮相。 操作起来总体感觉比较简单容易上手。
转自:http://www.cnblogs.com/caokai520/p/4409712.html (代码自己编写,增加相关图片)