node 使用 Redis 缓存

缓存是什么?

高并发下,一个项目最先出问题的,并不是程序本身,而是数据库最先承受不住。

在数据库上我们可以做很多优化,例如优化 SQL 语句,优化索引,如果数据量大了,还可以分库、分表等等。

一个项目中,大多数使用场景都是查询操作,而不是其他新增、修改和删除。那我们思考一下,能不能在第一次查询后,将数据存储在某个地方。下次再查询的时候,就直接读取之前保存的。如果数据发生改变了,就保存的数据删掉,重新保存最新的。这样不就可以大幅度的减少数据库的查询吗?

缓存就是这个原理。

Redis 又是什么?

Redis是一个开源的、基于内存的数据存储系统,可以用作数据库、缓存和消息中间件。Redis的数据都存储在内存中,这样它的读写速度就非常快。而且还会将内存中的数据写入本地硬盘,可以在服务器重启后,自动将数据恢复到内存中。

学习Redis是大家成为高手的必经之路。它的功能非常强大,在我们这节课中,只会用到Redis的缓存能力。

如何安装 Redis 的服务端与客户端?

1、安装 Redis 服务端 Windows Docker Desktop安装及使用 Docker 运行 MySQL

运行Redis,最推荐的方式依然是使用Docker。打开项目根目录的docker-compose.yml文件,添加Redis的相关配置。大家注意下格式,缩进非常重要,一定是和之前的MySQL配置对齐的

services:mysql:# ....redis:image: redis:7.4ports:- "6379:6379"volumes:- ./data/redis:/data

完成后,命令行,再次运行

docker-compose up -d

这样Docker,就会自动下载好Redis,并在6379端口启动它。

在这里插入图片描述

2、安装 Redis 客户端

服务端启动好了,还需要用客户端进行管理。所谓客户端,就是像 Navicat、Sequel Ace 一样用来管理数据库的工具。这里推荐大家使用的客户端,叫做Redis Insight,它是 Redis 官方发布的管理工具。它是完全免费的,非常好用。
Redis Insight官网

在这里插入图片描述
在这里插入图片描述
双击一下,就可以连进去了。
在这里插入图片描述

目前里面还没有存任何东西进去,所以都是空白的。好了,先丢一边,一会儿我们再来继续用它。

如何在 Node 项目中,使用 Redis 缓存数据?

Redis已经安装,并启动好了以后,现在需要在Node项目中来操作它。

1、安装 node-redis

项目根目录

npm i redis

2、Redis 配置文件

接着看官方文档

在这里插入图片描述

  • 这里告诉我们了,使用前,要先用connect方法连接上去。
  • set来写入数据。
  • get来读取数据。
  • key,就是给缓存数据,取了个名字。无论写入,还是读取,都是用这个名字,就能找到它。
  • 不用了以后,可以用disconnect方法来断开连接。
    新建utils/redis.js,内容我已经写好了
const {createClient} = require('redis');// 创建全局的 Redis 客户端实例
let client;/*** 初始化 Redis 客户端*/
const redisClient = async () => {if (client) return; // 如果客户端已经初始化,则不再重复初始化client = await createClient().on('error', err => console.log('Redis 连接失败', err)).connect();
};/*** 存入数组或对象,并可选地设置过期时间* @param key 键名* @param value 要存储的值* @param ttl 可选,以秒为单位的过期时间,默认不设置*/
const setKey = async (key, value, ttl = null) => {if (!client) await redisClient(); // 确保客户端已初始化value = JSON.stringify(value); // 将对象转换为JSON字符串await client.set(key, value);// 如果提供了ttl,则设置过期时间if (ttl !== null) {await client.expire(key, ttl);}
};/*** 读取数组或对象* @param key 键名* @returns {Promise<any>} 解析后的JSON对象或数组*/
const getKey = async (key) => {if (!client) await redisClient(); // 确保客户端已初始化const value = await client.get(key); // 将获取到的JSON字符串转换回对象return value ? JSON.parse(value) : null; // 如果value为空,返回null而不是抛出错误
};/*** 清除缓存数据* @param key* @returns {Promise<void>}*/
const delKey = async (key) => {if (!client) await redisClient(); // 确保客户端已初始化await client.del(key);
};/*** 获取匹配模式的所有键名* @param pattern* @returns {Promise<*>}*/
const getKeysByPattern = async (pattern) => {if (!client) await redisClient();return await client.keys(pattern);
}/*** 清空所有缓存数据* @returns {Promise<void>}*/
const flushAll = async () => {if (!client) await redisClient();await client.flushAll();
}module.exports = {redisClient, setKey, getKey, delKey, getKeysByPattern, flushAll};
  • 先定义了一个client变量,里面会创建全局的Redis客户端实例。
  • 第一个方法,是用来连接到了Redis的。这里有一个判断,如果已经存在了,就直接返回,这样可以避免重复的创建 Redis 实例。
  • 接着我们自定义了写入数据的方法,需要注意的是,在存储之前,先要用JSON.stringify()方法将 JS 对象或数组转换成JSON 字符串
  • 下面还有过期时间的设置,不传就是永久的。如果传了,以秒为单位,如果时间超出后,Redis会自动清理掉存储的数据。
  • 读取方法里,使用JSON.parse()方法将JSON 字符串解析回原来的数据结构。
  • 最下面是删除缓存的方法,调用del方法,即可删掉缓存数据。

这样做好封装好后,用起来就非常简单了,而且就算是数组或对象,也可以顺利的存取了。

PS: 如果您的 Redis 服务端,运行在其他服务器上或者你在宝塔中不想使用docker,可以调整连接格式为:

client = await createClient({url: 'redis://<服务器IP>:<端口号>' ,// password:'',  有无密码
})

在这里插入图片描述

3、通过utils/redis.js使用

// 引入
const { setKey, getKey } = require('../utils/redis');
// 单条数据存储 key:键名  data:数据
setKey(key, data);
// 带有效期存储 key:键名  data:数据 ttl:时间s为单位
setKey( key, data, ttl);
// 带分页的缓存 articles:默认为路由名 后用:链接 当前页和当页数量 (预定俗称以:为连接)
const cacheKey = `articles:${currentPage}:${pageSize}`;
setKey(cacheKey, data);
// 带id 的缓存  articles:默认为路由名 后用:链接 当前id (预定俗称以:为连接)
setKey(`article:${id}`, data)// 单条数据删除 key:键名
await delKey(key);// 复杂缓存删除
/*** 清除缓存* @param id* @returns {Promise<void>}*/
async function clearCache(id = null) {// 清除所有文章列表缓存 let keys = await getKeysByPattern('articles:*');if (keys.length !== 0) {await delKey(keys);}// 如果传递了id,则通过id清除文章详情缓存if (id) {// 如果是数组,则遍历const keys = Array.isArray(id) ? id.map(item => `article:${item}`) : `article:${id}`;await delKey(keys);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21679.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决双系统开机显示gnu grub version 2.06 Minimal BASH Like Line Editing is Supported

找了好多教程都没有用&#xff0c;终于解决了&#xff01;&#xff01;我是因为ubuntu分区的时候出问题了 问题描述&#xff1a; 双系统装好&#xff0c;隔天开机找不到引导项&#xff0c;黑屏显示下列 因为我用的D盘划分出来的部分空闲空间&#xff0c;而不是全部&#xff0c…

NLP-RNN-LSTM浅析

目录 双向 LSTM&#xff08;Bi - LSTM&#xff09; 双向 LSTM&#xff08;Bi - LSTM&#xff09;原理深入讲解 代码示例&#xff08;基于 PyTorch&#xff09; LSTM 应用到双向 RNN 中 代码示例&#xff08;基于 PyTorch&#xff09; 双向 LSTM - CRF&#xff08;Conditio…

自动化之ansible(二)

一、ansible中playbook&#xff08;剧本&#xff09; 官方文档&#xff1a; Ansible playbooks — Ansible Community Documentation 1、playbook的基本结构 一个基本的playbook由以下几个主要部分组成 hosts: 定义要执行任务的主机组或主机。 become: 是否需要使用超级用户…

uni-app小程序开发 基础知识2

目标&#xff1a; 构建一个文章发表平台。 我们先来写一个静态框架。 以下是 首页初代码文章列表页代码&#xff1a; <template><view class"content"><!-- 轮播图 --><swiper class"swiper-container" autoplay"true"…

kafka-集群扩容

一. 前言&#xff1a; 随着业务增加&#xff0c;我们会面临这kafka当性能问题&#xff0c;需要进行集群扩容&#xff0c;增加broker节点。 二. 扩容说明: 增加新服务到kafka集群是很容易的(参考&#xff1a; kafka-部署安装-CSDN博客 )&#xff0c;只要为新服务分配一个独一无…

uni-app开发app时 使用uni.chooseLocation遇到的问题

问题一&#xff1a;不显示 问题二&#xff1a;选择地址列表一直在加载中 因为 uni-app 接口文档 中已经说明&#xff0c;使用腾讯的话需要开启云服务&#xff0c;具体可看官网&#xff0c;这就是为什么使用时直接不显示的原因&#xff0c;所以我使用的高德&#xff0c;但又出现…

RabbitMQ的脑裂(网络分区)问题

问题描述&#xff1a; Mnesia reports that this RabbitMQ cluster has experienced a network partition. There is a risk of losing data 一、什么是MQ脑裂&#xff1f; 网络分区 如果另一个节点在一段时间内&#xff08;默认为 60 秒&#xff09;无法与其联系&#xff0…

SQL知识体系

SQL复习 MySQL SQL介绍 SQL SQL的全拼是什么&#xff1f; SQL全拼&#xff1a;Structured Query Language&#xff0c;也叫结构化查询语言。 SQL92和SQL99有什么区别呢&#xff1f; SQL92和SQL99分别代表了92年和99年颁布的SQL标准。 在 SQL92 中采用&#xff08;&#xff…

企业商业秘密百问百答之五十三【商业秘密转让】

《企业商业秘密百问百答》是由天禾律所陈军律师团队精心编撰的成果&#xff0c;汇集了该团队律师在处理商业秘密相关的刑事和民事案件中的丰富经验。近年来&#xff0c;这份资料已通过线上和线下的方式向全国近千家企业进行了广泛宣讲&#xff0c;并获得了积极的社会反响。 其…

巧用GitHub的CICD功能免费打包部署前端项目

近年来&#xff0c;随着前端技术的发展&#xff0c;前端项目的构建和打包过程变得越来越复杂&#xff0c;占用的资源也越来越多。我有一台云服务器&#xff0c;原本打算使用Docker进行部署&#xff0c;以简化操作流程。然而&#xff0c;只要执行sudo docker-compose -f deploy/…

STM32 CubeMx配置串口收发使用DMA并调用Idle模式(二)

本篇主要结合代码落实&#xff0c;之前串口已经配置好的DMA方式。 一、首先我们把串口看成一个对象&#xff0c;它有属性、私有数据和方法&#xff1b; 每个串口都有名字属性&#xff1b;有初始化、发送、接收方法&#xff1b;还有一个私有数据&#xff08;这个私有数据是每个…

react实例与总结(二)

目录 一、脚手架基础语法(16~17) 1.1、hello react 1.2、组件样式隔离(样式模块化) 1.3、react插件 二、React Router v5 2.1、react-router-dom相关API 2.1.1、内置组件 2.1.1.1、BrowserRouter 2.1.1.2、HashRouter 2.1.1.3、Route 2.1.1.4、Redirect 2.1.1.5、L…

【并发测试】Redis并发性能测试

arthas 测试示例 Redis配置类 Slf4j Configuration public class RedisConfig {BeanJedisConnectionFactory jedisConnectionFactory() {RedisStandaloneConfiguration configuration new RedisStandaloneConfiguration();configuration.setHostName(redisHost);configuratio…

【Linux基础八】计算机体系结构(冯诺依曼和操作系统)

【Linux基础八】计算机体系结构&#xff08;冯诺依曼和操作系统&#xff09; 1.冯诺依曼体系结构2.冯诺依曼的优势3.硬件间的交流4.操作系统对硬件资源的管理 1.冯诺依曼体系结构 计算机大部分遵守冯诺依曼体系 输入设备&#xff1a;键盘、鼠标、摄像头、麦克风、磁盘、网卡…

深入解析Qt事件循环

在Qt开发中&#xff0c;QApplication::exec()这行代码是每个开发者都熟悉的“魔法咒语”。为什么GUI程序必须调用它才能响应操作&#xff1f;为何耗时操作会导致界面冻结&#xff1f;本文将以事件循环为核心&#xff0c;揭示Qt高效运转的底层逻辑&#xff0c;探讨其设计哲学与最…

Hadoop 基础原理

Hadoop 基础原理 基本介绍Hadoop 的必要性Hadoop 核心组件Hadoop 生态系统中的附加组件 HDFSHDFS 集群架构HDFS 读写流程HDFS 写流程HDFS 读流程 NameNode 持久化机制 MapReduce底层原理示例 Hadoop 是一个由 Apache 基金会开发的分布式系统基础架构&#xff0c;主要解决海量数…

视觉分析之边缘检测算法

9.1 Roberts算子 Roberts算子又称为交叉微分算法&#xff0c;是基于交叉差分的梯度算法&#xff0c;通过局部差分计算检测边缘线条。 常用来处理具有陡峭的低噪声图像&#xff0c;当图像边缘接近于正45度或负45度时&#xff0c;该算法处理效果更理想。 其缺点是对边缘的定位…

【从0做项目】Java音缘心动(1)———项目介绍设计

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;项目结果展示 一&#xff1a;音乐播放器Web网页介绍 二&#xff1a;前期准备工作&…

数据链路层分析----交换机基本原理

目录 一、交换机基本原理 1、小型交换网络 2、交换机转发行为 二、交换机转发原理 1、MAC地址表 2、交换机初始状态 3、交换机学习MAC地址 4、ARP协议 5、交换机转发数据帧 6、目标主机回复 常见的以太网设备包括Hub、交换机等。交换机工作在数据链路层&#xff0c;它有…

三、Three.js模型对象、材质

一、三维向量Vector3与模型位置 点模型Points、线模型Line、网格网格模型Mesh等模型对象的父类都是Object3D&#xff0c;如果想对这些模型进行旋转、缩放、平移等操作&#xff0c;如何实现&#xff0c;可以查询Threejs文档Object3D对相关属性和方法的介绍 1、三维向量Vector3 …