共计 4380 个字符,预计需要花费 11 分钟才能阅读完成。
@[toc]
一、Redis 的外围概念
-
概念
Redis 就是分布式缓存,也能够了解成过程外的缓存。
如图:
二、Redis 的利用场景
-
利用场景
次要是利用在集群零碎中。
-
单体我的项目就没必要用分布式缓存,应用本地缓存就能够;如图:
-
当客户端发动申请到零碎,零碎先去到本地缓存查问数据,没有查问到数据则到数据库查问,将查到的数据保留到本地缓存在返回到客户端;当第二次申请到零碎,零碎先去到本地缓存查问数据,则将缓存中的数据返回到客户端【第一次申请曾经将数据保留到本地缓存中】;那他本地缓存的命中率为 50%;
-
应用本地缓存做分布式会有缓存命中率降落缺点;如图:
客户端发动申请到 Nginx,Nginx 将申请代理到零碎 1,零碎 1 查看本地缓存没有符合条件的数据,再到数据库获取数据存到本地缓存再返回到客户端;当客户端在一次发动申请到 Nginx,Nginx 将申请代理到零碎 2,零碎 2 查看本地缓存没有符合条件的数据,再到数据库获取数据存到本地缓存再返回到客户端,那么发动了两次申请都没有到本地缓存中获取到数据,那它缓存命中率为 0/2=0;缓存命中率降落那就表明整体查问性能降落。
-
解决缓存命中率的计划
将缓存数据集中到一起,应用 Redis 分布式缓存,如图:
三、Redis 的我的项目落地
-
条件
- Demo 我的项目
-
Redis【在 linux 中部署】
-
Linux 装置
# 装置 wget 命令 yum -y install wget #下载 wget http://download.redis.io/releases/redis-6.2.6.tar.gz #解压 tar xzf redis-6.2.6.tar.gz #进入解压文件夹 cd redis-6.2.6 #装置 gcc yum install gcc #编译 make #进入解压后的 src 目录,运行服务 src/redis-server
-
-
Demo 我的项目配置
-
步骤
-
装置 Redis Nuget 包
StackExchange.Redis
-
定义一个扩大类
public static IServiceCollection AddRedis(this IServiceCollection serviceCollection) {ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect("IP: 端口"); serviceCollection.AddSingleton(connectionMultiplexer); return serviceCollection; }
-
StateUp 类注册【写了个扩大办法】
services.AddRedis();
-
Redis 存储和获取
// 注入 public readonly ConnectionMultiplexer connectionMultiplexer; public HomeController(ConnectionMultiplexer _connectionMultiplexer) {connectionMultiplexer = _connectionMultiplexer;} // 获取 Redis 值 obj = connectionMultiplexer.GetDatabase(0).StringGet(Key).ToString(); // 存储 Redis 值 Key:Value connectionMultiplexer.GetDatabase(0).StringSet(Key, Value);
-
Redis 存储汇合
// 获取 Redis 是否存在 RedisValue[] redisValues = connectionMultiplexer.GetDatabase(0).SetMembers("list"); //Redis 中不存在此数据 if (redisValues.Length == 0) { // 数据库中获取 list = demoDbContext.Set<User>().ToList(); List<RedisValue> rvList = new List<RedisValue>(); foreach (User user in list) {obj = JsonConvert.SerializeObject(user); rvList.Add(obj); } // 将数据增加到 Redis 中 connectionMultiplexer.GetDatabase(0).SetAdd("list", rvList.ToArray()); }
-
Redis Hash 字典存储
应用场景:对数据库某个字段做批改或者某个 int 字段数据加一
// 获取 HASH 字段中的数据 connectionMultiplexer.GetDatabase(0).HashGet(类型, key).ToString(); if (string.IsNullOrEmpty(obj)) { // 到数据库获取数据 u = demoDbContext.Set<User>().Where(p => p.useid == useid).FirstOrDefault(); // 将数据增加到 Redis Hash 字典中 connectionMultiplexer.GetDatabase(0).HashSet(类型, key,Value); // 设置过期工夫 connectionMultiplexer.GetDatabase(0).KeyExpire(类型,TimeSpan.FromSeconds(10)); } // 字典中的 Value 值加 1 connectionMultiplexer.GetDatabase(0).HashIncrement(类型, key);
-
Redis 事务
// 查问获取值 connectionMultiplexer.GetDatabase(0).HashGet(类型, key).ToString(); // 创立事务 ITransaction transaction = connectionMultiplexer.GetDatabase(0).CreateTransaction(); // 增加值 transaction.HashSetAsync(类型, key, value); // 批改值 // transaction.HashSetAsync(类型, key, 批改后 Value); // 提交事务 bool commit = transaction.Execute();
-
Redis 批量存储数据
// 创立批量对象 var bach = connectionMultiplexer.GetDatabase(0).CreateBatch(); // 获取数据 List<User> list = new List<User>(); list = demoDbContext.user.ToList(); // 批量增加 for (int i = 0; i < list.Count; i++) {bach.HashSetAsync("bach_User_"+i, "state", list[i].usestate); } // 数据提交 bach.Execute();
-
Redis 汇合排序
// 获取数据 RedisValue[] rv = connectionMultiplexer.GetDatabase(0).SetMembers("User"); if (rv.Length == 0) {list = demoDbContext.Set<User>().ToList(); List<RedisValue> rvList = new List<RedisValue>(); // 批量增加数据 foreach (User u in list) {var data = JsonConvert.SerializeObject(u); rvList.Add(data); // 数据排序 connectionMultiplexer.GetDatabase(0).SortedSetAdd("User", data, u.usestate); // User :key data:Value 值 u.usestate:排序字段 升序 }
-
Redis 分页查问
List<User> list = new List<User>(); // 获取分页数据 100 为行数,1 为页数 RedisValue[] rv = connectionMultiplexer.GetDatabase(0).SetScan("User",100,0,1).ToArray(); if (rv.Length == 0) {list = demoDbContext.Set<User>().ToList(); List<RedisValue> rvList = new List<RedisValue>(); foreach (User u in list) {var data = JsonConvert.SerializeObject(u); rvList.Add(data); } // 增加数据到 Redis 中 connectionMultiplexer.GetDatabase(0).SetAdd("User", rvList.ToArray()); }
-
-
四、Redis 的通信原理
Redis 处理事件的简略模型:多路复用机制【一个线程解决多个连贯】【订阅公布机制】;
-
原理
默认通过 Socket 协定建设连贯的,服务端通过 Socket 的通过四层,在通过链路层再通过四层达到 Redis 建设连贯;链路层【硬件层面】收到申请后,操作系统【生产者】通过同步转换成异步将申请发给事件收集器【MQ】而后 Redis【订阅者】用一个线程通过轮询的形式处理事件,这就是多路复用机制。
Redis 做的三件事:
1、建设连贯
2、存储数据到本地缓存
3、长久化数据到文件中(开启新线程)
如图:
五、Redis 的数据结构原理
-
原理
Redis 建设连贯后,通过接口将数据存储到内存中。
如图:
-
数据长久化
-
目标
为了避免数据失落。默认寄存在 AOP 文件中。
-
-
Redis Set 原理图
数组 +HASH 表,如图:
HASH 的作用:避免数据反复,应用 HASH 碰撞。
-
Redis HASH 字典原理
数组 +HASH 表 + 单项列表。
-
原理
字典存储的字段通过 hash 失去一个数组的索引,依据索引将 key \ value 存储到数组中,如果失去的索引曾经存在 key\value 了,不会笼罩掉,会造成一个单项链表的模式持续存储。
如图:
-
![在这里插入图片形容](https://img-blog.csdnimg.cn/3e4a1a23c7a34ef1b8c2c16e34abf72d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
-
缺点
齐全基于内存,会导致内存溢出。不适宜存储海量数据。