2024-09-03



import redis
import time
import uuid
 
# 连接Redis
client = redis.StrictRedis(host='localhost', port=6379, db=0)
 
# 尝试获取分布式锁的函数
def acquire_lock(lock_key, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())  # 生成一个唯一的ID
    end = time.time() + acquire_timeout
 
    while time.time() < end:
        if client.set(lock_key, identifier, ex=lock_timeout, nx=True):
            # 如果设置成功,表示获取锁成功
            return identifier
        time.sleep(0.001)
 
    return False
 
# 释放分布式锁的函数
def release_lock(lock_key, identifier):
    pipe = client.pipeline(True)
    while True:
        try:
            # 检查锁是否是当前的ID
            pipe.get(lock_key)
            current_identifier = pipe.execute()[0]
            if current_identifier == identifier:
                # 释放锁
                pipe.delete(lock_key)
                pipe.execute()
                return True
            else:
                return False
        except redis.exceptions.WatchError:
            # 如果在检查过程中锁已经被其他客户端获取或释放,重试
            continue
 
# 使用示例
lock_key = "my_lock"
lock_identifier = acquire_lock(lock_key)
if lock_identifier:
    try:
        # 在这里执行需要互斥访问的代码
        print("Lock acquired. Exclusive access to the code block.")
    finally:
        # 确保释放锁
        if release_lock(lock_key, lock_identifier):
            print("Lock released.")
        else:
            print("Unable to release lock.")
else:
    print("Unable to acquire lock.")

这段代码展示了如何使用redis-py库来实现一个基本的分布式锁。它首先定义了连接到Redis服务器的客户端,然后定义了获取和释放锁的函数。在使用时,首先尝试获取锁,如果成功,则执行需要互斥访问的代码,并在最后确保释放锁。如果无法获取锁,则代码块将不会执行,并且打印相应的信息。

2024-09-03

Redis是一种开源的内存中数据结构存储系统,可以用作数据库、缓存和消息传递队列。下面是Redis中常见的五种数据类型及其操作命令的示例:

  1. 字符串(String)



# 设置键值
SET key value

# 获取键的值
GET key

# 追加值
APPEND key value

# 数值增减
INCR key
DECR key

# 设置过期时间
EXPIRE key seconds
  1. 列表(List)



# 在列表左侧插入元素
LPUSH key value1 [value2]

# 在列表右侧插入元素
RPUSH key value1 [value2]

# 获取列表指定范围内的元素
LRANGE key start stop

# 移除列表中的元素
LREM key count value
  1. 集合(Set)



# 添加一个或多个成员到集合
SADD key member1 [member2]

# 获取集合中的所有成员
SMEMBERS key

# 移除集合中的一个或多个成员
SREM key member1 [member2]
  1. 有序集合(Sorted Set)



# 添加一个或多个成员,或更新已存在成员的分数
ZADD key [NX|XX] [CH] [INCR] score1 member1 [score2 member2]

# 获取有序集合的成员数
ZCARD key

# 计算在有序集合中指定范围内的成员数
ZCOUNT key min max
  1. 哈希(Hash)



# 设置哈希表字段的值
HSET key field value

# 获取存储在哈希表中指定字段的值
HGET key field

# 获取在哈希表中指定key的所有字段和值
HGETALL key

# 删除一个或多个哈希表字段
HDEL key field1 [field2]

以上命令均为Redis基础命令,可以在Redis客户端或者程序中使用。需要注意的是,具体命令的使用可能会受到Redis版本的影响,建议参考最新的官方文档。

2024-09-03

Redis 是一个键值存储系统,其数据结构可以是字符串、哈希表、列表、集合、有序集合等。

  1. 字符串(String):最基本的数据类型,可以存储任何类型的字符串,包括二进制。



SET key value
GET key
  1. 哈希表(Hash):适用于存储小型结构化数据。



HSET hash_key field value
HGET hash_key field
  1. 列表(List):适用于队列和堆栈。



LPUSH list_key value
LPOP list_key
  1. 集合(Set):元素都是唯一的。



SADD set_key member
SMEMBERS set_key
  1. 有序集合(Sorted Set):元素都是唯一的,每个元素都关联着一个分数,用于排序。



ZADD sorted_set_key score member
ZRANGE sorted_set_key 0 -1 WITHSCORES

以上操作是基本的 Redis 命令,用于操作各种数据结构。在实际应用中,可以根据需要选择合适的数据结构和命令来使用 Redis。

2024-09-03



package main
 
import (
    "fmt"
    "github.com/go-redis/redis"
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"
)
 
func main() {
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
    })
 
    pong, err := client.Ping().Result()
    if err != nil {
        log.Fatalf("Failed to connect to Redis: %v", err)
    }
    fmt.Println(pong)
 
    // 创建一个消息队列的频道
    messages := make(chan string)
 
    // 创建一个信号通知,用于优雅地关闭程序
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
 
    // 开始监听消息队列
    go func() {
        for {
            // 从Redis的列表中取出消息
            val, err := client.BLPop(0, "myqueue").Result()
            if err != nil {
                log.Println("Error receiving message:", err)
                continue
            }
            messages <- val[1]
        }
    }()
 
    // 循环处理消息
    for {
        select {
        case msg := <-messages:
            // 处理消息
            log.Printf("Received: %s\n", msg)
        case sig := <-sigs:
            log.Printf("Received signal: %s. Exiting...\n", sig)
            return
        }
    }
}

这段代码使用Go语言和go-redis库实现了一个简单的Redis消息队列客户端。它连接到Redis服务器,监听名为"myqueue"的列表,并将接收到的消息打印出来。如果接收到系统信号(如SIGINT或SIGTERM),程序会优雅地关闭。这个例子展示了如何使用Go语言处理Redis消息队列,并且是构建实时系统时理解消息队列模式的一个很好的起点。

2024-09-03



// 注意:以下代码是伪代码,仅用于说明如何在CLion中配置和编译Redis 6.2.6源码。
 
// 1. 下载Redis 6.2.6源码并解压。
// 2. 打开CLion并导入Redis源码目录。
 
// 3. 在CLion中配置CMake项目。
// 修改CMakeLists.txt文件,确保包含所有必要的源文件,并添加必要的编译选项。
 
// 4. 配置调试运行配置。
// 在CLion中,点击"Run" -> "Edit Configurations",然后添加一个新的应用程序配置。
// 设置程序的执行路径为编译后的redis-server可执行文件路径。
 
// 5. 编译和调试。
// 点击CLion顶部工具栏中的"Build"按钮开始编译,或者使用快捷键"Shift+F9"开始调试。
 
// 注意:具体的CMakeLists.txt和调试配置需要根据Redis 6.2.6的具体构建要求来设置。

在CLion中进行Redis源码的编译和调试,需要对CMakeLists.txt进行适当的修改,并在CLion中配置正确的调试运行配置。这样可以确保源码能够被正确编译并在CLion中被调试。

2024-09-03

在使用Redisson进行分布式锁时,可以通过以下步骤实现:

  1. 添加Redisson依赖到项目中。
  2. 配置RedissonClient。
  3. 使用Redisson提供的RLock对象进行加锁和解锁操作。

以下是一个使用Redisson进行分布式锁的简单示例:




import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
 
import java.util.concurrent.TimeUnit;
 
public class RedissonLockExample {
 
    public static void main(String[] args) {
        // 1. 配置RedissonClient
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
 
        // 2. 获取锁对象
        RLock lock = redisson.getLock("myLock");
 
        try {
            // 3. 尝试加锁,最多等待100秒,锁定之后最多持有锁10秒
            boolean isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);
            if (isLocked) {
                // 业务逻辑
                System.out.println("Lock acquired");
                // 处理完毕后,释放锁
            } else {
                System.out.println("Lock not acquired");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 4. 确保释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                System.out.println("Lock released");
            }
        }
 
        // 5. 关闭RedissonClient
        redisson.shutdown();
    }
}

在这个例子中,我们创建了一个RedissonClient实例,用于连接Redis服务器。然后我们获取了一个名为"myLock"的锁对象。通过tryLock方法尝试获取锁,并在获取锁后执行业务逻辑。最后,在完成业务逻辑后,我们释放掉获取到的锁。最后关闭RedissonClient以释放资源。

2024-09-03

Redis是一种开源的内存中数据结构存储系统,可以用作数据库、缓存和消息中间件。以下是2024年最常用的Redis命令及其在C和C++中的调用方式。

Redis命令

  • SET key value: 设置字符串值。
  • GET key: 获取字符串值。
  • HSET key field value: 设置哈希表字段的字符串值。
  • HGET key field: 获取哈希表字段的字符串值。
  • DEL key: 删除键。
  • EXISTS key: 检查键是否存在。
  • KEYS pattern: 查找所有符合给定模式的键。
  • PUBLISH channel message: 将信息发送到指定的频道。
  • SUBSCRIBE channel: 订阅给定的一个或多个频道的信息。

C语言调用Redis

使用hiredis库,首先需要安装hiredis:




git clone https://github.com/redis/hiredis.git
cd hiredis
make
sudo make install

示例代码:




#include <stdio.h>
#include <stdlib.h>
#include <hiredis/hiredis.h>
 
int main() {
    // 创建连接对象
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c != NULL && c->err) {
        printf("连接错误: %s\n", c->errstr);
        // 处理错误
        return 1;
    }
 
    // 设置键值
    redisReply *reply = redisCommand(c, "SET key %s", "value");
    freeReplyObject(reply);
 
    // 获取键值
    reply = redisCommand(c, "GET key");
    printf("GET key: %s\n", reply->str);
    freeReplyObject(reply);
 
    // 关闭连接
    redisFree(c);
    return 0;
}

C++语言调用Redis

使用hiredis库,首先需要安装hiredis:




git clone https://github.com/redis/hiredis.git
cd hiredis
make
sudo make install

示例代码:




#include <iostream>
#include <hiredis/hiredis.h>
 
int main() {
    // 创建连接对象
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        if (c) {
            std::cerr << "连接错误: " << c->errstr << std::endl;
        } else {
            std::cerr << "连接失败" << std::endl;
        }
        // 处理错误
        if (c) { redisFree(c); }
        return 1;
    }
 
    // 设置键值
    redisReply *reply = (redisReply*)redisCommand(c, "SET key %s", "value");
    if (reply->type == REDIS_REPLY_ERROR) {
        std::cerr << "命令错误: " << reply->str << std::endl;
        freeReplyObject(reply);
        redisFree(c);
        return 1;
    }
    freeReplyObject(reply);
 
    // 获取键值
    reply = (redisReply*)redisCommand(c, "GET key");
    if (reply->type == REDIS_REPLY_STRING) {
        std::cout << "GET key: " << reply->str << std::endl;
    }
    freeReplyObject(reply);
 
    // 关闭连接
    redisFree(c);
    return 0;
}

以上代码展

2024-09-03

Redis的List数据类型是一个双向链表,可以从两端进行插入和删除操作。

常用命令:

  • LPUSH key value[ value ...]:在列表头部插入一个或多个值。
  • RPUSH key value[ value ...]:在列表尾部插入一个或多个值。
  • LRANGE key start stop:获取列表指定范围内的元素。
  • LPOP key:移出并获取列表的第一个元素。
  • RPOP key:移出并获取列表的最后一个元素。
  • LLEN key:获取列表长度。
  • LREM key count value:移除列表元素。

常见使用场景:

  1. 消息队列:LPUSH/LPOP 或 RPUSH/RPOP 实现先进先出或后进先出。
  2. 排行榜:使用有序集合(sorted set),但当需要频繁更新分数时,使用List更为高效。
  3. 请求限流:使用List记录请求,并设置过期时间,通过LPUSH/LRANGE/LLEN组合来实现。
  4. 分页:使用LRANGE根据页码和每页大小来获取数据。

示例代码(Python使用redis-py库):




import redis
 
# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 使用LPUSH和LRANGE模拟消息队列
r.lpush('myqueue', 'message1')
r.lpush('myqueue', 'message2')
print(r.lrange('myqueue', 0, -1))  # 打印队列内容
 
# 使用RPUSH和LPOP模拟先进先出
r.rpush('mystack', 'item1')
r.rpush('mystack', 'item2')
print(r.lpop('mystack'))  # 移出并打印第一个元素
 
# 使用LLEN获取队列长度
print(r.llen('myqueue'))
 
# 使用LREM移除队列中的特定元素
r.lrem('myqueue', 1, 'message1')  # 移除队列中一个message1
2024-09-03



import redis
 
# 连接到Redis
redis_host = 'localhost'
redis_port = 6379
redis_db = 0
r = redis.StrictRedis(host=redis_host, port=redis_port, db=redis_db)
 
# 更新分数,如果成员存在则更新其分数,不存在则添加该成员
def update_score(leaderboard_key, member, score):
    r.zadd(leaderboard_key, {member: score})
 
# 获取排行榜前N名成员及其分数
def get_top_scores(leaderboard_key, start, stop):
    return r.zrevrange(leaderboard_key, start, stop, withscores=True)
 
# 示例用法
leaderboard_key = 'weekly_leaderboard'
member = 'user123'
score = 1000
 
# 更新成员的分数
update_score(leaderboard_key, member, score)
 
# 获取前10名成员
top_scores = get_top_scores(leaderboard_key, 0, 9)
for member, score in top_scores:
    print(f'Member: {member.decode("utf-8")}, Score: {score}')

这段代码使用了Redis的Sorted Set数据结构来维护一个高性能的排行榜。update_score函数用于更新成员的分数,如果成员不存在则添加。get_top_scores函数用于获取排行榜上指定范围内的成员及其分数。这里使用了Redis的Python客户端库redis-py

2024-09-03

在Spring Boot 3.2.0中,你可以使用Lettuce作为Redis的Java客户端库与Redis进行交互。以下是一个基本的配置示例和使用RedisTemplate的示例代码。

  1. 添加依赖到你的pom.xml



<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>io.lettuce.core</groupId>
    <artifactId>lettuce-core</artifactId>
</dependency>
  1. application.propertiesapplication.yml中配置Redis:



# application.properties
spring.redis.host=localhost
spring.redis.port=6379

或者使用YAML格式:




# application.yml
spring:
  redis:
    host: localhost
    port: 6379
  1. 注入RedisTemplate并使用:



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
 
@Component
public class RedisService {
 
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
 
    public void setKeyValue(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }
 
    public Object getKeyValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

确保你的Spring Boot版本与Redis客户端库版本兼容。上述代码提供了一个简单的RedisService类,它使用RedisTemplate来设置和获取键值对。在实际应用中,你可能需要根据自己的需求进行更复杂的配置和编码。