2024-09-04

Redis是一个开源的使用C语言编写的、支持网络交互的、可基于内存也可持久化的日志型、Key-Value数据库,并提供多种语言的API。

以下是Redis中一些常用的命令和数据结构:

  1. 常用命令:

    • SET:为一个键设置值。
    • GET:获取一个键的值。
    • DEL:删除一个键。
    • EXPIRE:为一个键设置过期时间。
    • EXISTS:检查一个键是否存在。
    • KEYS:查找符合给定模式的键。
    • PING:测试与服务器的连接是否仍然有效。
  2. 数据结构:

    • 字符串(String):可以存储任何类型的字符串,包括二进制、JSON、序列化对象等。
    • 列表(List):按照插入顺序保存数据,可以在头部或尾部添加或删除元素。
    • 集合(Set):无序的字符串集合,不允许重复。
    • 有序集合(Sorted Set):字符串成员与浮点数分数相关联,成员是唯一的,分数可以重复。
    • 哈希(Hash):包含键值对的无序散列表。
    • 位图(Bitmap):用于处理二进制数据,可以对位进行设置、清除和切换操作。
    • 超级字符串(HyperLogLog):用于计算集合的基数,适合用于数据统计。
  3. 使用示例:

    
    
    
    # 设置键值对
    SET key "value"
     
    # 获取键的值
    GET key
     
    # 删除键
    DEL key
     
    # 设置键的过期时间
    EXPIRE key 60
     
    # 检查键是否存在
    EXISTS key
     
    # 查找所有符合模式的键
    KEYS *
     
    # 测试与服务器的连接
    PING

以上是Redis的基本概念和常用命令,实际应用中可以根据需求选择合适的数据结构和命令。

2024-09-04



import redis
import time
import uuid
 
class RedisLock:
    def __init__(self, client: redis.Redis, lock_name: str, lock_timeout: int = 10):
        self.client = client
        self.lock_name = lock_name
        self.lock_timeout = lock_timeout
 
    def acquire_lock(self):
        identifier = str(uuid.uuid4())
        end = time.time() + self.lock_timeout
        while time.time() < end:
            if self.client.set(self.lock_name, identifier, ex=self.lock_timeout, nx=True):
                return identifier
            time.sleep(0.001)
        return False
 
    def release_lock(self, identifier):
        pipe = self.client.pipeline(True)
        while True:
            try:
                pipe.watch(self.lock_name)
                if pipe.get(self.lock_name) == identifier:
                    pipe.multi()
                    pipe.delete(self.lock_name)
                    pipe.execute()
                    return True
                pipe.unwatch()
                break
            except redis.exceptions.WatchError:
                pass
        return False
 
# 使用示例
client = redis.Redis(host='localhost', port=6379, db=0)
lock = RedisLock(client, "my_lock")
identifier = lock.acquire_lock()
if identifier:
    try:
        # 在这里执行需要互斥访问的代码
        print("Lock acquired and executed code")
    finally:
        lock.release_lock(identifier)
else:
    print("Could not acquire lock")

这段代码实现了一个基于Redis的分布式锁,使用Python语言和redis-py库。它提供了一种方法来避免多个服务实例同时写入数据或执行特定操作。锁通过一个唯一标识符来释放,确保只有获得锁的服务实例能够执行操作。这是构建微服务时常用的一种技术,以确保数据的一致性和系统的可靠性。

2024-09-04



local resty_lock = require "resty.lock"
local cache_ng = require "resty.openresty-cache-ng"
local cache_zone = ngx.shared.cache_zone
local cache_zone_2 = ngx.shared.cache_zone_2
 
-- 创建锁
local lock = resty_lock:new("lock_zone")
 
-- 尝试获取锁
local elapsed, err = lock:lock("some_key")
if not elapsed then
    ngx.log(ngx.ERR, "failed to lock: ", err)
    return
end
 
-- 尝试从第一级缓存获取数据
local data, err = cache_ng.get(cache_zone, "some_key", {
    ttl = 5, -- 缓存时间
    neg_ttl = 3, -- 负缓存时间
    l1_serializer = "json", -- 缓存数据的序列化方式
    l1_neg_load = function(key) -- 负载函数,当缓存失效时调用
        -- 从数据源获取数据
        local data_source_data = fetch_data_from_source(key)
        if data_source_data then
            -- 将数据存入第二级缓存
            cache_ng.set(cache_zone_2, key, data_source_data, { ttl = 300 })
            -- 设置缓存数据
            return cache_ng.set(cache_zone, key, data_source_data, { ttl = 5 })
        end
        return nil, "data not found"
    end
})
 
-- 如果数据未找到,则释放锁并返回错误信息
if not data then
    lock:unlock()
    ngx.say("data not found")
    return
end
 
-- 输出数据
ngx.say(data)
 
-- 释放锁
lock:unlock()

这段代码展示了如何在OpenResty环境中使用Redis作为分布式缓存,并且实现了多级缓存的策略。它使用了resty.lock库来处理分布式锁,以及resty.openresty-cache-ng库来管理缓存。代码中包含了锁的创建、获取以及释放,同时展示了如何使用负载函数来从数据源获取数据并设置缓存。

2024-09-04

在Linux系统中安装和启动Redis的步骤如下:

  1. 更新包管理器索引并安装Redis:



sudo apt-get update
sudo apt-get install redis-server
  1. 启动Redis服务:



sudo systemctl start redis-server
  1. 确认Redis正在运行:



sudo systemctl status redis-server
  1. 如需开机自启动Redis:



sudo systemctl enable redis-server
  1. 测试Redis是否安装成功:



redis-cli ping

如果返回PONG,则表示Redis已成功安装并可以使用。

以上步骤适用于基于Debian或Ubuntu的Linux发行版。其他Linux发行版可能需要修改安装命令。

2024-09-04

要在Python中获取Redis的所有数据,你可以使用redis包。以下是一个简单的例子,展示了如何连接到Redis服务器并获取所有键及其值。

首先,确保你已经安装了redis包,如果没有安装,可以使用pip安装:




pip install redis

然后,你可以使用以下代码来获取所有Redis键及其值:




import redis
 
# 连接到本地Redis实例
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 获取所有的keys
keys = r.keys('*')
 
# 获取每个key的值
data = {key.decode('utf-8'): r.get(key).decode('utf-8') for key in keys}
 
print(data)

请注意,使用keys('*')可能会对生产环境中的大型数据库性能产生负面影响,因为它会检索所有的键。在生产环境中,考虑使用SCAN迭代键以避免性能问题。

2024-09-04

在上一篇文章中,我们已经讲解了Redis主从复制的基本概念和配置方法。在这篇文章中,我们将深入到Redis主从复制的具体实现细节。

Redis主从复制的实现主要依赖于sync命令和psync命令。

  1. sync命令:当从服务器连接到主服务器时,会发送PSYNC ? -1命令,请求全量复制。主服务器接收到命令后,会开始在后台保存快照(RDB持久化),并在保存过程中继续处理命令。当快照完成后,主服务器会将快照文件发送给从服务器,从服务器接收并加载快照。
  2. psync命令:当从服务器连接已经建立,主服务器会把自己执行的写命令发送给从服务器。当从服务器与主服务器网络连接断开后,会尝试重新连接主服务器,此时会发送PSYNC <runid> <offset>命令,其中<runid>是主服务器的运行ID,<offset>是断开时的复制偏移量。如果<runid>和主服务器的运行ID相同,且主服务器仍然保留了此次断开前的回放缓冲区,则可以使用部分复制功能,只将断开后的命令发送给从服务器。

以下是一个Redis主从复制的配置示例:




# 在主服务器的redis.conf中
bind 0.0.0.0
 
# 在从服务器的redis.conf中
slaveof 主服务器IP 主服务器端口

启动Redis服务并配置主从复制后,可以通过Redis命令info replication查看复制的状态和信息。

注意:在生产环境中,为了数据的安全性和一致性,建议使用Sentinel或者Cluster来管理Redis的高可用性和扩展性。

2024-09-04

在Redis中设置密码,你需要修改Redis配置文件(通常名为redis.conf),找到# requirepass foobared这行配置,去掉前面的#并将foobared替换成你想要设置的密码。

例如,你想要设置密码为myStrongPassword123,你应该这样修改配置文件:




requirepass myStrongPassword123

修改完成后,重启Redis服务以使配置生效。

在Linux中,你可以使用以下命令来重启Redis服务:




sudo service redis-server restart

或者如果你使用的是systemd(大多数现代Linux发行版):




sudo systemctl restart redis.service

设置密码后,客户端连接到Redis服务时需要提供密码。使用redis-cli时,可以使用-a参数:




redis-cli -a myStrongPassword123

在编程时,连接Redis时需要提供密码:




import redis
 
# 创建连接对象
r = redis.StrictRedis(host='localhost', port=6379, password='myStrongPassword123')
 
# 测试连接
r.ping()

请确保在设置密码后,你的应用程序和其他管理工具(如Redis Desktop Manager或其他CLI工具)都使用正确的密码进行连接,否则将无法正常访问Redis服务。

2024-09-04



local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('get', key) or "0")
 
if current + 1 > limit then
    return 0 -- 超出限制
else
    if current == 0 then
        redis.call('expire', key, 1) -- 设置键的过期时间,避免永久锁
    end
    redis.call('incr', key) -- 自增键值
    return 1 -- 未超出限制
end

这段Lua脚本用于实现接口访问频率的限制。它通过Redis的键值来记录访问次数,并设置过期时间来防止无限期占用资源。脚本接收两个参数,一个是限制次数,一个是键名。如果当前访问次数加1后超过限制次数,则返回0;否则,如果当前访问次数是0(即键不存在),它会设置键的过期时间,然后递增访问次数,并返回1。这个脚本可以在Redis中通过EVAL命令执行。

2024-09-04

Redis 的 RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshotting。

RDB 的优点是:

  • 一旦采用该方式,整个Redis数据库将只包含一个文件,方便进行备份和恢复。
  • 对于恢复大数据集来说,RDB是一种比AOF更快的方式。
  • 对于性能的影响较小,RDB在指定的时间间隔进行保存,对服务器性能的影响可以控制。

RDB的缺点是:

  • 如果你需要尽量减小数据丢失的风险,RDB可能不适合你。因为RDB是间隔一段时间进行保存,如果Redis意外宕机,那么可能会丢失最后一次快照后的数据。
  • RDB需要经常fork子进程来执行IO操作,如果数据集很大,可能会造成较长时间的阻塞。

配置RDB快照保存的时机,可以在redis.conf中设置:




save 900 1      # 900秒内至少1个键被修改则触发保存
save 300 10     # 300秒内至少10个键被修改则触发保存
save 60 10000   # 60秒内至少10000个键被修改则触发保存

如果你想关闭RDB,可以将所有的save指令注释掉或者设置为空。

RDB的文件默认为dump.rdb,可以通过配置dir选项来指定保存的目录,通过配置dbfilename选项来指定文件名。




dir ./
dbfilename dump.rdb

启动Redis时,如果指定了RDB文件,Redis会尝试加载该文件进内存。

注意:Redis的RDB文件是一个压缩过的二进制文件,不能直接编辑。如果需要修改RDB文件,可以使用Redis提供的工具redis-check-rdb来进行处理。

2024-09-04

在实时监控Redis性能指标的方法中,可以使用Redis自带的INFO命令,或者使用第三方工具和服务,如RedisLive、RedisInsight、Prometheus配合Grafana等。

以下是使用INFO命令的一个简单示例:




import redis
import json
 
# 连接到Redis
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 使用INFO命令获取性能指标
info = r.info()
 
# 打印信息
print(json.dumps(info, indent=4))

为了实时监控和报警,你可以定期运行上述脚本,并将输出结果发送到监控系统。如果你需要更高级的实时监控,可以考虑使用Prometheus配合Grafana,它们都是开源的监控和报警工具。

Prometheus配合Grafana的示例:

  1. 安装并配置Prometheus,添加一个job来抓取Redis的metrics。
  2. 安装Grafana,并添加Prometheus数据源。
  3. 创建监控仪表盘,配置图表,设置报警规则。

这些工具都有详细的官方文档,可以根据需要进行安装和配置。