在 Node.js 中操作 Redis

news/2024/4/18 14:38:23/文章来源:https://blog.csdn.net/qq_42308316/article/details/128112821

在 Node.js 中操作 Redis

Node.js 中可以操作 Redis 的软件包推荐列表:https://redis.io/clients#nodejs。

推荐下面两个:

  • node-redis
  • ioredis

这里主要以 ioredis 为例。

ioredis 是功能强大的 Redis 客户端,已被世界上最大的在线商务公司阿里巴巴和许多其他了不起的公司所使用。

ioredis 特点:

  • 功能齐全。它支持集群,前哨,流,流水线,当然还支持Lua脚本和发布/订阅(具有二进制消息的支持)。
  • 高性能
  • 令人愉快的 API。它的异步 API 支持回调函数与 Promise
  • 命令参数和返回值的转换
  • 透明键前缀
  • Lua脚本的抽象,允许您定义自定义命令。
  • 支持二进制数据
  • 支持 TLS
  • 支持脱机队列和就绪检查
  • 支持ES6类型,例如 Map 和 Set
  • 支持GEO命令(Redis 3.2不稳定)
  • 复杂的错误处理策略
  • 支持NAT映射
  • 支持自动流水线

相关链接:

  • API 参考文档
  • 更新日志
  • 从 node_redis 迁移

基本使用

npm install ioredis
const Redis = require("ioredis");
const redis = new Redis(); // uses defaults unless given configuration object// ioredis supports all Redis commands:
redis.set("foo", "bar"); // returns promise which resolves to string, "OK"// the format is: redis[SOME_REDIS_COMMAND_IN_LOWERCASE](ARGUMENTS_ARE_JOINED_INTO_COMMAND_STRING)
// the js: ` redis.set("mykey", "Hello") ` is equivalent to the cli: ` redis> SET mykey "Hello" `// ioredis supports the node.js callback style
redis.get("foo", function (err, result) {if (err) {console.error(err);} else {console.log(result); // Promise resolves to "bar"}
});// Or ioredis returns a promise if the last argument isn't a function
redis.get("foo").then(function (result) {console.log(result); // Prints "bar"
});// Most responses are strings, or arrays of strings
redis.zadd("sortedSet", 1, "one", 2, "dos", 4, "quatro", 3, "three");
redis.zrange("sortedSet", 0, 2, "WITHSCORES").then((res) => console.log(res)); // Promise resolves to ["one", "1", "dos", "2", "three", "3"] as if the command was ` redis> ZRANGE sortedSet 0 2 WITHSCORES `// All arguments are passed directly to the redis server:
redis.set("key", 100, "EX", 10);

有关更多实例,可以参考这里:https://github.com/luin/ioredis/tree/master/examples。

Pipelining

如果要发送一批命令(例如> 5),则可以使用流水线将命令在内存中排队,然后将它们一次全部发送到 Redis。这样,性能提高了50%〜300%(请参阅基准测试部分)。

redis.pipeline() 创建一个 Pipeline 实例。您可以像 Redis 实例一样在其上调用任何 Redis 命令。这些命令在内存中排队,并通过调用 exec 方法刷新到 Redis:

const pipeline = redis.pipeline();
pipeline.set("foo", "bar");
pipeline.del("cc");
pipeline.exec((err, results) => {// `err` is always null, and `results` is an array of responses// corresponding to the sequence of queued commands.// Each response follows the format `[err, result]`.
});// You can even chain the commands:
redis.pipeline().set("foo", "bar").del("cc").exec((err, results) => {});// `exec` also returns a Promise:
const promise = redis.pipeline().set("foo", "bar").get("foo").exec();
promise.then((result) => {// result === [[null, 'OK'], [null, 'bar']]
});

每个链接的命令还可以具有一个回调,该回调将在命令得到答复时被调用:

redis.pipeline().set("foo", "bar").get("foo", (err, result) => {// result === 'bar'}).exec((err, result) => {// result[1][1] === 'bar'});

除了将命令分别添加到管道队列之外,您还可以将命令和参数数组传递给构造函数:

redis.pipeline([["set", "foo", "bar"],["get", "foo"],]).exec(() => {/* ... */});

#length 属性显示管道中有多少个命令:

const length = redis.pipeline().set("foo", "bar").get("foo").length;
// length === 2

事务

大多数时候,事务命令 multi&exec 与管道一起使用。因此,在调用 multi 时,默认情况下会自动创建 Pipeline 实例,因此您可以像使用管道一样使用 multi:

redis.multi().set("foo", "bar").get("foo").exec((err, results) => {// results === [[null, 'OK'], [null, 'bar']]});

如果事务的命令链中存在语法错误(例如,错误的参数数量,错误的命令名称等),则不会执行任何命令,并返回错误:

redis.multi().set("foo").set("foo", "new value").exec((err, results) => {// err://  { [ReplyError: EXECABORT Transaction discarded because of previous errors.]//    name: 'ReplyError',//    message: 'EXECABORT Transaction discarded because of previous errors.',//    command: { name: 'exec', args: [] },//    previousErrors://     [ { [ReplyError: ERR wrong number of arguments for 'set' command]//         name: 'ReplyError',//         message: 'ERR wrong number of arguments for \'set\' command',//         command: [Object] } ] }});

就接口而言,multi 与管道的区别在于,当为每个链接的命令指定回调时,排队状态将传递给回调,而不是命令的结果:

redis.multi().set("foo", "bar", (err, result) => {// result === 'QUEUED'}).exec(/* ... */);

如果要使用不带管道的事务,请将 { pipeline: false } 传递给 multi,每个命令将立即发送到 Redis,而无需等待 exec 调用:

redis.multi({ pipeline: false });
redis.set("foo", "bar");
redis.get("foo");
redis.exec((err, result) => {// result === [[null, 'OK'], [null, 'bar']]
});

multi 的构造函数还接受一批命令:

redis.multi([["set", "foo", "bar"],["get", "foo"],]).exec(() => {/* ... */});

管道支持内联事务,这意味着您可以将管道中的命令子集分组为一个事务:

redis.pipeline().get("foo").multi().set("foo", "bar").get("foo").exec().get("foo").exec();

错误处理

Redis服务器返回的所有错误都是 ReplyError 的实例,可以通过 Redis 进行访问:

const Redis = require("ioredis");
const redis = new Redis();
// This command causes a reply error since the SET command requires two arguments.
redis.set("foo", (err) => {err instanceof Redis.ReplyError;
});

默认情况下,错误堆栈没有任何意义,因为整个堆栈都发生在 ioredis 模块本身而不是代码中。因此,要找出错误在代码中的位置并不容易。 ioredis 提供了一个选项 showFriendlyErrorStack 来解决该问题。启用 showFriendlyErrorStack 时,ioredis 将为您优化错误堆栈:

const Redis = require("ioredis");
const redis = new Redis({ showFriendlyErrorStack: true });
redis.set("foo");

Redis 集群

对于一个小型项目来说,使用一台 Redis 服务器已经非常足够了,然后现实中的项目通常需要若干台 Redis 服务器的支持:

  • 从结构上,单个 Redis 服务器会发生单点故障,同时一台服务器需要承受所有的请求负载。这就需要为数据生成多个副本并分配在不同的服务器上;
  • 从容量上,单个 Redis 服务器的内存非常容易成为存储瓶颈,所有需要进行数据分片

同时拥有多个 Redis 服务器后就会面临如何管理集群的问题,包括如何增加节点、故障恢复等。

为此,我们将依次介绍 Redis 中的复制、哨兵(sentinel)和集群的使用和原理。

复制

通过持久化功能,Redis 保证了即使在服务器重启的情况下也不会损失(或少量损失)数据。但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其它服务器依然可以继续提供服务。为此,Redis 提供了复制功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其它数据库上。

配置

在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。

  • 主数据库可以进行读写操作
  • 当写操作导致数据变化时会自动将数据同步给从数据库
  • 而从数据库一般是只读的,并接受主数据库同步过来的数据
  • 一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库
    在这里插入图片描述

在 Redis 中使用复制功能非常容易,只需要在从数据库的配置文件中加入下面的配置即可,主数据库无需进行任何配置。

slaveof 主数据库地址 主数据库端口

(1)开启两个 Redis 服务进程

为了能够更直观的展示复制的流程,下面将实现一个最简化的复制系统。我们要在一台服务器上启动两个 Redis 实例,监听不同端口,其中一个作为主数据库,另一个作为从数据库。首先我们不加任何参数来启动一个 Redis 实例作为主数据库:

redis-server

该实例默认监听 6379 端口。然后加上 slaveof 参数启动另一个 Redis 实例作为从数据库,并让其监听 6380 端口;

redis-server --port 6380 --slaveof 127.0.0.1 6379

此时在主数据库中的任何数据变化都会自动地同步到从数据库中。

(2)查看复制信息

INFO replication

(3)测试数据同步效果

在实例 A 中写入数据,会被自动同步到实例 B 中。

(4)从数据库中的数据是只读的

默认情况下,从数据库是只读的,如果直接修改从数据库的数据会出现错误:

INFO replication

可以通过设置从数据库的配置文件中的 slave-read-only 为 no 以使从数据库可写,但是因为对从数据库的任何更改都不会同步给任何其它数据库,并且一旦主数据库中更新了对应的数据就会覆盖从数据库中的改动,所有通常的场景下不应该设置从数据库可写,以免导致被忽略的潜在应用逻辑错误。

配置多台从数据库的方法也一样,在所有的从数据库的配置文件中都加上 slaveof 参数指向同一个主数据库即可。

除了通过配置文件或命令行参数设置 slaveof 参数,还可以在运行时使用 SLAVEOF 命令修改。

Redis 设置远程连接

注意:为了保护数据安全,开放远程连接需谨慎操作。
Redis 默认是不允许远程连接的,通过下面的配置可以开启远程连接。
将 redis.conf 配置文件的 bind 和 protected-mode 修改如下:

# 绑定的端口号
bind 0.0.0.0# 关闭保护模式
protected-mode no# RDB 持久化
save 900 1 # 每 900 秒至少有 1 个 key 变化了,则写入快照
save 300 10 # 每 300 秒至少有 10 个 key 变化了,则写入快照
save 60 10000 # 每 60 秒至少有 10000 个 key 变化了,则写入快照
dbfilename dump.rdb # 快照保存的文件名称
dir ./ # 快照文件保存路径# 开启 AOF 方式的持久化
appendonly yes
# 同步的文件名称
appendfilename "appendonly.aof"

除此之外还需要检查服务器防火墙是否开放了 Redis 服务占用的端口号。
修改之后重启 Redis 服务即可生效。

执行

redis-server 配置文件路径

在docker上使用到的相关命令行

# Liunx命令
cd /etc
rm -rf 6379.conf 
cp /app/redis-6.0.9/redis.conf ./6379.conf
cd redis
mv ../6379.conf ./
vim 6379.conf
#bash: vi: command not found
apt-get install vim
apt-get update
apt-get install vim
vim 6379.conf
#/6397 回车查找  按n下一个 把port改为1234
#/daemonize 回车查找 把no 改为 yes (在后台运行)
#按esc :wq回车 保存退出
#redis-server 6379.conf
#redis-cli
#select 1 切换到1号数据库

项目地址

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

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

相关文章

MySQL日志管理、备份与恢复

文章目录一、mysql常用日志1、概述①、错误日志②、二进制日志③、中继日志④、慢查询日志⑤、通用查询日志,用来记录MySQL的所有连接和语句,默认是关闭的2、数据库中查询日志状态①、查看二进制日志开启状态②、查看慢查询日志功能是否开启③、查看慢查…

GAN生成漫画脸

最近对对抗生成网络GAN比较感兴趣,相关知识点文章还在编辑中,以下这个是一个练手的小项目~ (在原模型上做了,为了减少计算量让其好训练一些。) 一、导入工具包 import tensorflow as tf from tensorflow.keras import layersimport numpy a…

业务:财务会计业务知识

一、引言 会计是以货币为主要计量单位,对企业、事业、机关、团体及其他经济组织的经济活动进行记录、计算、控制、分析、报告,以提供财务和管理信息的工作。会计的职能主要是反映和控制经济活动过程,保证会计信息的合法、真实、准确和完整&a…

校园论坛网站设计设计与实现

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

网页JS自动化脚本(四)修改元素的尺寸颜色显隐状态

修改元素尺寸 在定位到了元素之后, 我们就可以对元素进行一些修改了,我们先来修改元素泊宽度以及高度 window.onloadfunction(){var theElementdocument.querySelector("img.undertips-link-lefticon");theElement.style.width"100px";theElement.style.…

命令模式

文章目录思考命令模式1.命令模式的本质2.何时选用命令模式3.优缺点4.实现耦合写法命令模式优化耦合写法命令模式实现撤销命令模式实现厨师做菜命令模式实现排队命令模式实现日志持久化思考命令模式 命令模式就是解耦强耦合代码,用户只关心功能的实现,开发…

win11该文件没有与之关联的应用怎么办

win11用户在使用电脑的时候遇到了“该文件没有与之关联的应用”的提示,这是怎么回事呢?应该怎么办呢?出现这个情况应该是注册表被误删了,大家需要新建一个文本文档,然后输入下文提供的指令,之后将其重命名为…

linux不显示当前路径的解决方法

1.输入vim ~/.bashrc进入用户的shell环境变量的配置文件(可以设置环境变量以及通过alias设置别名) 2.按下“i”键进入编辑模式(底部显示INSERT) 3.修改\w为$PWD: 修改为: 4.按“esc”键后输入":wq"保存并退出&#xff…

Databend 开源周报 #69

Databend 是一款强大的云数仓。专为弹性和高效设计,自由且开源。 即刻体验云服务:https://app.databend.com。 New Features multiple catalog 实现删除用户定义目录 (#8820) meta 新增用于删除 key 和使 key 过期的 cli 命令 (#8858) planner 支…

手把手教你做智能合约开源|多文件合约开源|引用文件开源

本文手把手教你使用 区块链浏览器 验证智能合约的三种方式。 验证单一 Solidity 文件 在开始验证之前,我们需要首先部署智能合约。进入 Remix IDE,创建一个合约新文件。复制粘贴下面的代码: // SPDX-License-Identifier: MITpragma solidit…

JAVA学习-java基础讲义02

java基础讲义02一 进制1.1 进制介绍1.2 二进制1.3 任意进制到十进制转换1.4 十进制到任意进制之间的转换1.5 快速转换法1.6 有符号数据表示法二 Java变量和数据类型1.1 变量概述1.2 数据类型1.3 变量定义三 Java数据类型转换3.1 数据类型转换概述3.2 数据类型转换之自动类型转换…

[附源码]Python计算机毕业设计SSM老年公寓管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

爬虫工作流程、请求与响应原理、requests库讲解

爬虫工作流程、请求与响应原理、requests库讲解 爬虫分类主要分为两大板块 web爬虫(浏览器爬虫) APP爬虫(手机端爬虫) 在这两大板块中又可以把爬虫归类为聚焦爬虫和通用爬虫 聚焦爬虫:针对某一个接口(ur…

使用Conda

0. Anaconda Prompt 命令提示符 0.1 验证conda是否被安装 conda --version0.2 conda管理环境 可以用命令复制和删除环境 参考. 1. Conda管理包 1.1 常用包管理功能 查找包查看包安装包 查找分为精确查找和模糊查找,如下图所示 卸载包更新包 1.2 conda管理环…

三肽Gly-Cys-Gly、88440-55-5

三肽Gly-Cys-Gly 编号:111774 CAS号:88440-55-5 三字母:H2N-Gly-Cys-Gly-COOH 描 述:羧肽酶 U 抑制剂(凝血酶可激活的纤维蛋白溶解抑制剂,TAFI),Ki 0.14 μM。编号: 111774 中文名称…

安装 laravel 遇到的错误和解决方案

安装 laravel 遇到的错误和解决方案 纯粹是为了运行下 laravel,遇到了错误记录下,分享给需要的人。 下载 PHP Windows 版 ,我选择的版本是 PHP 7.4 (7.4.33)。下载文件以后找个文件夹解压就可以了。Composer 安装,官网 。 勾选以…

C/C++家族族谱管理系统

C/C家族族谱管理系统 课题名称: 家族族谱管理 主要目标: 通过训练,强化学生对树结构、二叉树结构的表示及操作算法的掌握和灵活运用 3.具体要求: 要求设计实现具有下列功能的家谱管理系统: (1) 输入文件以存放最初家谱中各成员的信息,成员的信息中…

WSL Ubuntu20.04安装pycairo指南

环境说明 wsl Ubuntu20.04 走过的一些可能有用的弯路 由于pycairo要求python3.7,但是之前Ubuntu上有个3.6的python环境,所以就安装了python3.8: sudo apt install python3.8然后python3命令还是链接到python3.6,结果就yongln …

iOS15适配 UINavigationBar和UITabBar设置无效,变成黑色

今天更新了xcode13,运行项目发现iOS15以上的手机导航栏和状态栏之前设置的颜色等属性都不起作用了,都变成了黑色,滚动的时候才能变成正常的颜色,经确认得用UINavigationBarAppearance和UITabBarAppearance这两个属性对导航栏和状态…

系统封装制作

工具网址: 镜像下载: Windows 10 22H2 - MSDN - 山己几子木 (sjjzm.com)pe工具:【新提醒】优启通 v3.7.2022.0910(2022.10.14 发布)_IT天空原创软件_IT天空 (itsk.com)万能驱动:万能驱动 v7.22.0912.2&…