写点什么

Redis(一)原理与基本使用

作者:神秘码农
  • 2022 年 3 月 31 日
  • 本文字数:4296 字

    阅读完需:约 14 分钟

@[toc]

## 一、Redis 的核心概念

1. 概念

Redis 就是分布式缓存,也可以理解成进程外的缓存。

如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/0c7b7fb26a514142ba664a40e62bbe2b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

## 二、Redis 的应用场景

- 应用场景

主要是应用在集群系统中。

- 单体项目就没必要用分布式缓存,使用本地缓存就可以;如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/84a757cc02a34d8b9d42795ae56b1ce7.png#pic_center)

当客户端发起请求到系统,系统先去到本地缓存查询数据,没有查询到数据则到数据库查询,将查到的数据保存到本地缓存在返回到客户端;当第二次请求到系统,系统先去到本地缓存查询数据,则将缓存中的数据返回到客户端【第一次请求已经将数据保存到本地缓存中】;那他本地缓存的命中率为 50%;

- 使用本地缓存做分布式会有缓存命中率下降缺陷;如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/0ec82697b60c42afada9a4816b574baa.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

客户端发起请求到 Nginx,Nginx 将请求代理到系统 1,系统 1 查看本地缓存没有符合条件的数据,再到数据库获取数据存到本地缓存再返回到客户端;当客户端在一次发起请求到 Nginx,Nginx 将请求代理到系统 2,系统 2 查看本地缓存没有符合条件的数据,再到数据库获取数据存到本地缓存再返回到客户端,那么发起了两次请求都没有到本地缓存中获取到数据,那它缓存命中率为 0/2=0;缓存命中率下降那就表明整体查询性能下降。

- 解决缓存命中率的方案

将缓存数据集中到一起,使用 Redis 分布式缓存,如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/7e60270c4b4c41d6b8042612c2450f14.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

## 三、Redis 的项目落地

- 条件

- Demo 项目

- Redis 【在 linux 中部署】

- Linux 安装

```bash

#安装 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 项目配置

- 步骤

1. 安装 Redis Nuget 包

```

StackExchange.Redis

```

2. 定义一个扩展类

```

public static IServiceCollection AddRedis(this IServiceCollection serviceCollection)

{

ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect("IP:端口");

serviceCollection.AddSingleton(connectionMultiplexer);

return serviceCollection;

}

```

3. StateUp 类注册【写了个扩展方法】

```

services.AddRedis();

```

4. Redis 存储和获取

```C#

//注入

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);

```

5. 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());

}

```

6. 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);

```

7. 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();

```

8. 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();

```

9. 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:排序字段 升序

}

```

10. 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、持久化数据到文件中(开启新线程)

如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/2b67cfb098954a379e8eb8d9af41e4ce.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

## 五、Redis 的数据结构原理

- 原理

Redis 建立连接后,通过接口将数据存储到内存中。

如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/e40240124287449a885872d6a3441e3e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQEDnpZ7lhpzlhpnku6PnoIE=,size_16,color_FFFFFF,t_70,g_se,x_16#pic_center)

- 数据持久化

- 目的

为了防止数据丢失。默认存放在 AOP 文件中。

- Redis Set 原理图

数组+HASH 表,如图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/7d401b8f5ce84f0a83e6113d9bfb41b8.png#pic_center)

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)

- 缺陷

完全基于内存,会导致内存溢出。不适合存储海量数据。

发布于: 刚刚阅读数: 3
用户头像

神秘码农

关注

还未添加个人签名 2022.03.14 加入

好好学习,天天向上!

评论

发布
暂无评论
Redis(一)原理与基本使用_神秘码农_InfoQ写作平台