本文主要分为4个模块介绍Redis:
- Redis概念解释
- Redis 安装
- Redis可视化工具 Redis Desktop Manager使用
- c#代码实现Redis
1.Redis概念解释:
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。你可以就把它当成数据库来看,Redis是把数据保存到内存中的,但是它也会定期的把数据写会到硬盘中。因此Redis的速度很快,但是每次重启Redis服务时,其中的数据也会丢失,因此,Redis也提供了持久化存储机制,将数据以某种形式保存在文件中,每次重启时,可以自动从文件加载数据到内存当中。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API(C#,java。php 等等)。
Redis的架构包括两个部分:Redis Client和Redis Server。Redis客户端负责向服务器端发送请求并接受来自服务器端的响应。服务器端负责处理客户端请求,例如,存储数据,修改数据等。
Redis通常用作数据库,缓存以及消息系统。
Redis保存数据有两种方式:
快照模式(Snapshot)
它支持两种快照模式:
- 定时快照,即按一定时间将内存中的数据保存到磁盘上。
- 定量快照,即数据变化一定次数后将数据保存到磁盘上。
你也可以结合这两种方式,比如变化1000次,距离上次保存时间60秒以上才保存数据。
写模式(Append Only File)
这种模式下Redis会把所以修改数据的命令(如Update,Set)等保存到一个只能追加的ASAP文件中,当Redis重启时,它会把这个文件里的命令重新执行一遍。
数据保存到哪里?
数据是保存到一个数据文件中的,具体文件名要看Redis的配置文件,即Redis.conf
config get dbfilename (返回 dump.rdb)
可以使用 config set dbfilename new (修改你要保存数据的文件)
数据如何到导出?
Redis写数据时先写到一个temp文件中,然后再把temp文件重命名为预定义的文件,所以即使Redis在运行,也可以直接用cp命令拷贝这个文件。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
- String: 字符串
最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。 - Hash: 散列
这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。 - List: 列表
用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。本人还用一个场景,很合适—取行情信息。就也是个生产者和消费者的场景。LIST可以很好的完成排队,先进先出的原则。 - Set: 集合
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 - Sorted Set: 有序集合
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作
5、redis的过期策略以及内存淘汰机制
分析:这个问题其实相当重要,到底redis有没用到家,这个问题就可以看出来。比如你redis只能存5G数据,可是你写了10G,那会删5G的数据。怎么删的,这个问题思考过么?还有,你的数据已经设置了过期时间,但是时间到了,内存占用率还是比较高,有思考过原因么?
回答:
redis采用的是定期删除+惰性删除策略。
为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
定期删除+惰性删除是如何工作的呢?
定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
采用定期删除+惰性删除就没其他问题了么?
不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。
6、redis和数据库双写一致性问题
分析:一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。
首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。
https://blog.csdn.net/hjm4702192/article/details/80518856
2.Redis 安装
Window 下安装
下载地址:https://github.com/MSOpenTech/redis/releases。
Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 C 盘,解压后,将文件夹重新命名为 redis。
打开一个 cmd 窗口 使用cd命令切换目录到 C:\redis 运行 redis-server.exe redis.windows.conf
如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的。输入之后,会显示如下界面:
这时候另启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了。
切换到redis目录下运行 redis-cli.exe -h 127.0.0.1 -p 6379 ,此段操作是为了使用命令形式来使用redis
设置键值对 set myKey abc
取出键值对 get myKey
具体命令操作参考:http://www.runoob.com/redis/redis-keys.html
上面是简单的测试,此外还需要一个redis的调试工具:
3.Redis可视化工具 Redis Desktop Manager
官网下载:https://redisdesktop.com/download
github地址https://github.com/uglide/RedisDesktopManager/releases
下载好一键安装:
二、安装Redis Desktop Manager redis-desktop-manager-0.8.8.384.exe 傻瓜式安装,点击下一步就行。
安装完成桌面会生成如下快捷图标
三、创建连接:可以点击“测试连接”,查看是否连接上,“名字”一定要填写
4.下面开始讲c#代码实现Redis
1.在使用redis之前,需要启动redis
打开一个 cmd 窗口 使用cd命令切换目录到 C:\redis 运行 redis-server.exe redis.windows.conf 。
2.代码调用
2.1 Nuget包管理器添加StackExchange.Redis的引用
2.2 新建一个控制台:测试里面的一个方法:
using StackExchange.Redis;
在main’中新建一个list把list传入到redis中(token之类也是一样使用)
static void Main(string[] args)
{
var q = client.Get<List<UserInfo>>("ListTest");
List<UserInfo> u = new List<UserInfo>() {
new UserInfo(){Name="1",Age=1},
new UserInfo(){Name="2",Age=11},
new UserInfo(){Name="3",Age=12},
new UserInfo(){Name="255555",Age=12},
};
DateTime time = DateTime.Now.AddSeconds(30);
//存储
client.Set<List<UserInfo>>("ListTest", u, time);
//获取
q = client.Get<List<UserInfo>>("ListTest");
foreach (var item in q)
{
Console.WriteLine(item.Name);
}
Console.ReadLine();
}
public class UserInfo
{
public string Name { get; set; }
public int Age { get; set; }
}
运行问以后可以在RedisDesktop,Manager中查看
在刚刚代码中,我们还设计了时间过期时间,20秒;再重新点击 加载数据时候,会发现数据没有了,因为获取了!
。
注解:之前觉得redis很高大上很流弊,接触了以后发现,它很是平易近人呀。后面需要redis的其他数据保存的方法,可以调用方法直接使用,也可以对很多的方法进行封装,因为这是公共类,可以使用单例的方式对该类进行实例。