RedisLua,两个看似风流马不相及的技术框架,为什么能产生“爱”的火花,成为工作中的黄金搭档?面试中更是高频出现:Redis 执行 Lua,到底能不能保证原子性?

一、原子性

在回答问题之前,需要对“原子性”这个概念有一个清新的认识,因此,我们首先要分析的是原子性的概念。

关系型数据库的原子性

通常意义上,我们说的原子性是指关系型数据库RDBMS(比如 MySQL)的原子性,也就是 ACID(Atomicity、Consistency、Isolation、Durability)中 Atomicity这一项特性。

ACID 中的原子性指是:事务中的所有操作要么全部执行成功,要么全部失败回滚。

这里以银行转账这个生活实例来解释原子性:账户A 给 账户B 转账100元,原子性就是指账户A减去100元的同时,账户B必须增加100元,如果账户A减少100元,账户B没有增加100元,该操作就不具备原子性,需要进行回滚,将账户A减少的100元加回去。JAVA 代码实现如下:

photo_2024-03-29 18.44.29.jpeg

继续阅读

当你在使用 Redis 扩展连接到 Redis 服务器时,可能会遇到 Redis::connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known 的警告。这个警告通常表示 PHP 无法解析 Redis 服务器的主机名或无法连接到 Redis 服务器。以下是一篇关于解决这个问题的技术博客的 Markdown 格式示例:

解决 Redis 连接问题:php_network_getaddresses

在使用 Redis 扩展连接到 Redis 服务器时,可能会遇到以下警告信息:

PHP Warning: Redis::connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known

这个警告通常表示 PHP 无法解析 Redis 服务器的主机名或无法连接到 Redis 服务器。下面是一些可能的解决方法:

1. 检查主机名和端口

确保你在连接 Redis 服务器时使用了正确的主机名和端口。检查你的代码,确认主机名和端口与 Redis 服务器的设置匹配。

2. 检查网络连接

确保 PHP 能够访问 Redis 服务器所在的网络。尝试使用 ping 命令或其他网络工具来测试与 Redis 服务器的连接。

3. 检查 DNS 解析

如果你使用的是主机名连接 Redis 服务器,确保主机名能够正确解析为有效的 IP 地址。你可以尝试使用 pingnslookup 命令来确认主机名是否能够解析为正确的 IP 地址。

4. 检查防火墙设置

如果你的服务器上启用了防火墙,确保已经允许 PHP 连接到 Redis 服务器的端口。检查防火墙设置,并确保允许来自 PHP 的网络流量通过 Redis 服务器的端口。

5. 检查 Redis 服务器状态

确保 Redis 服务器正在运行,并且服务正常。你可以尝试连接到 Redis 服务器并执行一些简单的操作,例如 PING 命令,来确认 Redis 服务器是否可用。

如果你仍然无法解决连接问题,建议参考 Redis 和 PHP 文档,查找更多关于连接 Redis 的指导和调试技巧。

希望以上解决方法能够帮助你解决 php_network_getaddresses 的问题,并成功连接到 Redis 服务器。

Redis浮点数运算精度提升技术研究

随着现代技术的发展,数据量越来越大,而精度越来越高。因此,在数据操作方面,精度提升也是一个重要的问题。Redis是一款开源的高性能键值数据库,它支持非常丰富的数据类型,其中包括浮点数。然而,Redis浮点数在运算时会出现精度丢失的问题,对于传统的处理方式来说,这种情况会带来很大的困扰。因此,为了确保计算的精度,提升数据处理的效率,对Redis浮点数运算的精度进行提升成为一个必要的任务。

一、Redis浮点数运算的问题与原因

在进行Redis浮点数运算时,我们可以使用Redis提供的指令,例如INCRBYFLOATHINCRBYFLOAT等等。然而,使用这些指令进行运算时会发现,当浮点数较大时,运算结果会出现精度丢失的问题。

这是由于在传统的浮点数存储方式中,浮点数在计算机内部是以二进制形式表示的,而二进制无法精确地表示小数位数很多的实数。举个例子,当我们使用Redis进行一个简单的加法运算时,如下所示:

127.0.0.1:6379> incrbyfloat foo 0.1
"0.1"
127.0.0.1:6379> incrbyfloat foo 0.2
"0.3"

对于大多数人来说,以上的运算结果是没有问题的。然而,如果我们查看Redis内部所存储的实际数值时,就会发现其实Redis存储的是以下二进制数据:

001111111011011100001010001111010111000010100011110101110000101

这个二进制数据即为0.30000000000000004000000000000000的二进制表示,这是因为在计算机内部,0.1和0.2被转化为二进制时产生了舍入误差,此时的误差通常很小,但在进行多次运算时,误差会逐渐累积,使得结果越来越不准确。

二、Redis浮点数运算精度提升的技术

为了解决这个问题,我们需要对Redis浮点数运算的精度进行提升。以下是一些常见的技术:

1. 精度提升方案

使用一个特殊的算法对浮点数进行处理,可以达到精度提升的效果。例如,可以使用BigDecimal库来进行高精度的运算。

2. 整数存储方案

考虑到整数运算的精度会比浮点数运算高,我们可以使用整数存储方案进行浮点数运算。例如,可以将浮点数乘以一个倍数,使其变成整数,再进行相应的运算。

示例代码(使用整数存储方案):

127.0.0.1:6379> set foo 0
"OK"
127.0.0.1:6379> incrby foo 1
(integer) 1
127.0.0.1:6379> incrby foo 2
(integer) 3
127.0.0.1:6379> incrby foo 0.1
(integer) 400000001
127.0.0.1:6379> incrby foo 0.2
(integer) 700000001

在这个例子中,我们将浮点数乘以了10的9次方,使其变成整数,并以此来进行运算。

三、总结

Redis可以作为一个高效的键值数据库,提供丰富的数据类型支持,其中包括浮点数。但是,由于浮点数在计算机内部以二进制形式表示,会导致精度丢失的问题。为了解决这个问题,我们可以使用精度提升方案或整数存储方案来进行优化。精度提升方案利用特殊算法提升浮点数运算的精度,使得结果更加准确。整数存储方案则是将浮点数乘以一个倍数,取整数来完成运算,虽然结果不如精度提升方案准确,但在普通场合下也能满足要求。希望本文能为您理解Redis浮点数运算精度提升方案提供帮助。

服务器抛错, redis 持久化出了问题. 抛错如下:

Fatal error: Uncaught RedisException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error

翻译:

(错误)MISCONF Redis 已配置为保存 RDB 快照,但目前无法在磁盘上持久化。 可以修改数据集的命令被禁用,因为如果 RDB 快照失败(stop-writes-on-bgsave-error 选项),此实例被配置为在写入期间报告错误。 有关 RDB 错误的详细信息,请检查 Redis 日志。
抛错中 已经提供了解决方案 stop-writes-on-bgsave-error 参数调整为 no;

这个问题19年也是发生过的, 解决方案 Redis抛错:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to.

下面找了个介绍的文章内容比较细.

Redis 可以将数据库快照保存在名为dump.rdb的二进制文件中。
RDB这种持久化方式被称为快照。

工作方式:

Redis调用forks,获得子进程 子进程将数据集写入到一个临时RDB文件中
当子进程完成对新RDB文件的写入时,Redis用新RDB文件替换原来的文件,并删除旧的RDB文件
这种工作方式使得Redis可以从copy-on-write机制中获益。(AOF的重写也利用了写时复制)
写时复制 是一种计算机程序设计领域的优化策略。核心思想是,如果有多个调用者同时要求相同资源,他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的。此作法主要的优点是如果调用者没有修改该资源,就不会有副本被创建,因此多个调用者只是读取操作时可以共享同一份资源。

其实stop-writes-on-bgsave-error 在配置文件里在 快照 板块里。

默认情况下,如果启用了 RDB 快照(至少一个保存点)并且最新的后台保存失败,``将停止接受写入。
这将使用户意识到(以一种艰难的方式)数据没有正确地保存在磁盘上,否则很可能没有人会注意到并且会发生一些灾难。
如果后台保存过程将再次开始工作,Redis 将自动允许再次写入。
但是,如果您设置了对 Redis 服务器和持久性的适当监控,您可能希望禁用此功能,以便 Redis 继续照常工作,即使存在磁盘、权限等问题。

所以说简单将该选项设置为no很可能依然没有从本质上解决问题, 只是说就算发生错误我也依然备份。
其实在持久化出错时停止工作也是一种保护机制和提示。

我之后又将stop-writes-on-bgsave-error 设置为了yes, 但是再次加入KEY的时候, 没有报错。

理论上应该要看日志, 但是我这里大概可以猜测到应该是和内存有关, 因为我的服务器只有4G的内存, 大概是一时之间起了好几个程序, 内存空间不够fork的子进程

即使我有很多空闲 RAM,在 Linux 下后台保存也会因 fork() 错误而失败!
简短的回答:echo 1 > /proc/sys/vm/overcommit_memory:)

现在是长的:

Redis 后台保存模式依赖于现代操作系统中 fork 的写时复制语义:Redis fork(创建子进程)是父进程的精确副本。子进程将数据库转储到磁盘上并最终退出。理论上,子进程应该使用与作为副本的父进程一样多的内存,但实际上由于大多数现代操作系统实现的写时复制语义,父进程和子进程将共享公共内存页面。只有在子页面或父页面发生变化时,页面才会被复制。由于理论上所有页面都可能在子进程保存时发生变化,Linux 无法提前知道子进程将占用多少内存,因此如果overcommit_memory 设置为零 fork 将失败,除非有足够多的可用 RAM 来真正复制所有父内存页面,结果是如果您有 3 GB 的 Redis 数据集和只有 2 GB 的可用内存,它将失败。

设置overcommit_memory为 1 告诉 Linux 放松并以更乐观的分配方式执行 fork,这确实是Redis 想要的。

原文地址 : https://blog.csdn.net/qq_43178138/article/details/119144986

今天看了同时的代码, 发现自己对redis的了解就是渣渣呀.

$redis->set($key, $data, ['nx', 'ex' => $frequency]]

字符串的应用, 一般我们就是用作缓存, 或者自增键加锁使用. 其他业务很少用.

看到上面代码第一眼时我就懵逼了, 三参数可以是数组.
先解释下上面代码意思 : $key 是否存在, 存在则设 $frequencyttl有效期.

说下使用场景: 我们弄了个预警服务, 怕重复报警, 限制频率 $frequency秒内仅报警一次.

nx, ex 的介绍 细节如下面文档:

SET

SET key value [EX seconds] [PX milliseconds] [NX|XX]

将字符串值 value 关联到 key

如果 key 已经持有其他值, SET 就覆写旧值,无视类型。

对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。

可选参数
Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:

EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。
PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value
NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value
XX :只在键已经存在时,才对键进行设置操作。

文档地址 : http://doc.redisfans.com/string/set.html

karp

创建我自己的巨人