目录

Redis概述

Redis的数据类型

Redis的持久化

Redis的发布订阅

Redis的事务

Redis的性能优化

Python操作字符串(String)

Python操作哈希表(Hash)

Python操作列表(List) 

Python操作集合(Set)

Python操作有序集合(ZSet)

pipeline对象

Redis数据库连接池

附录 C++ hiredis库 (人生苦短)


Redis概述

edis是一款开源的内存数据库,支持键值对存储、发布订阅、持久化等功能。下面是一些关于Redis的基本知识:

Redis的数据类型

Redis支持五种基本的数据类型,分别是字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(ZSet)。这些数据类型可以用于不同的场景,例如字符串可以用于缓存、计数器等,哈希可以用于存储对象,列表可以用于队列等。

Redis的持久化

Redis支持两种持久化方式,分别是RDB和AOF。RDB是一种快照式的持久化方式,会将Redis的数据以快照的方式保存到硬盘上,AOF则是将Redis的操作以追加的方式保存到一个文件中。这两种方式各有优缺点,可以根据实际情况选择使用。

Redis的发布订阅

Redis支持发布订阅模式,可以通过订阅某个频道来接收频道中的消息。这个功能可以用于实现实时消息推送、事件通知等场景。

Redis的事务

Redis支持事务,可以将多个操作打包成一个原子性的操作进行执行,如果其中一个操作失败,所有的操作都会回滚。这个功能可以用于确保多个操作的一致性,避免中间出现意外情况导致数据不一致。

Redis的性能优化

Redis是一款高性能的数据库,可以通过一些方法来进一步提升性能,例如使用管道来批量执行操作、使用连接池减少连接的建立和关闭、设置合适的内存限制等等。

Python操作字符串(String)

以下是一些常用的 Redis 字符串类型的 API:

  • set(name, value, ex=None, px=None, nx=False, xx=False): 设置指定键的值。
  • get(name): 获取指定键的值。
  • mset(mapping): 批量设置多个键值对。
  • mget(keys, *args): 批量获取多个键值对。
  • incr(name, amount=1): 将指定键的值自增指定量。
  • decr(name, amount=1): 将指定键的值自减指定量。
  • append(name, value): 将值追加到指定键的值后面。
  • strlen(name): 获取指定键的值的长度。

下面是一个例子,演示如何使用 Redis 字符串类型的 API 存储、读取、修改字符串:

import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 设置键值对
r.set('mykey', 'Hello World')

# 获取键值对
value = r.get('mykey')
print(value)  # 输出 b'Hello World'

# 批量设置多个键值对
r.mset({'key1': 'value1', 'key2': 'value2', 'key3': 'value3'})

# 批量获取多个键值对
values = r.mget('key1', 'key2', 'key3')
print(values)  # 输出 [b'value1', b'value2', b'value3']

# 自增键的值
r.incr('counter', amount=2)
value = r.get('counter')
print(value)  # 输出 b'2'

# 自减键的值
r.decr('counter', amount=1)
value = r.get('counter')
print(value)  # 输出 b'1'

# 追加字符串到键的值后面
r.append('mykey', ' Redis')
value = r.get('mykey')
print(value)  # 输出 b'Hello World Redis'

# 获取键的值的长度
length = r.strlen('mykey')
print(length)  # 输出 18

Python操作哈希表(Hash)

以下是一些常用的 Redis 哈希类型的 API:

  • hset(name, key, value): 设置哈希表中指定键的值。
  • hget(name, key): 获取哈希表中指定键的值。
  • hmset(name, mapping): 批量设置哈希表中的多个键值对。
  • hmget(name, keys, *args): 批量获取哈希表中的多个键值对。
  • hgetall(name): 获取哈希表中所有的键值对。
  • hincrby(name, key, amount=1): 将哈希表中指定键的值自增指定量。
  • hdel(name, *keys): 删除哈希表中一个或多个指定键。
import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 设置哈希表中的一个键值对
r.hset('myhash', 'field1', 'value1')

# 获取哈希表中的一个键值对
value = r.hget('myhash', 'field1')
print(value)  # 输出 b'value1'

# 批量设置哈希表中的多个键值对
r.hmset('myhash', {'field2': 'value2', 'field3': 'value3'})

# 批量获取哈希表中的多个键值对
values = r.hmget('myhash', 'field1', 'field2', 'field3')
print(values)  # 输出 [b'value1', b'value2', b'value3']

# 获取哈希表中所有的键值对
all_values = r.hgetall('myhash')
print(all_values)  # 输出 {b'field1': b'value1', b'field2': b'value2', b'field3': b'value3'}

# 将哈希表中指定键的值自增指定量
r.hincrby('myhash', 'field4', amount=3)
value = r.hget('myhash', 'field4')
print(value)  # 输出 b'3'

# 删除哈希表中的一个或多个指定键
r.hdel('myhash', 'field1', 'field2')

Python 操作列表(List) 

  • rpush(name, values): 在列表的右侧添加一个或多个元素。
  • lpush(name, values): 在列表的左侧添加一个或多个元素。
  • lrange(name, start, end): 返回列表中指定范围内的元素。
  • lpop(name): 删除并返回列表最左侧的元素。
  • rpop(name): 删除并返回列表最右侧的元素。
  • llen(name): 返回列表的长度。
  • lset(name, index, value): 设置列表中指定索引的元素的值。
  • lrem(name, count, value): 从列表中删除指定值的元素。

下面是一个例子,演示如何使用 Redis 列表类型的 API 存储、读取、修改列表:

import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 在列表的右侧添加一个元素
r.rpush('mylist', 'a')

# 在列表的左侧添加一个元素
r.lpush('mylist', 'b')

# 在列表的右侧添加多个元素
r.rpush('mylist', 'c', 'd', 'e')

# 返回列表中指定范围内的元素
values = r.lrange('mylist', 0, -1)
print(values)  # 输出 [b'b', b'a', b'c', b'd', b'e']

# 删除并返回列表最左侧的元素
value = r.lpop('mylist')
print(value)  # 输出 b'b'

# 删除并返回列表最右侧的元素
value = r.rpop('mylist')
print(value)  # 输出 b'e'

# 返回列表的长度
length = r.llen('mylist')
print(length)  # 输出 3

# 设置列表中指定索引的元素的值
r.lset('mylist', 1, 'new_value')

# 删除列表中所有指定值的元素
r.lrem('mylist', 0, 'c')

Python操作集合(Set)

  • sadd(name, values): 往集合中添加一个或多个元素。
  • srem(name, values): 从集合中删除一个或多个元素。
  • sismember(name, value): 检查指定元素是否存在于集合中。
  • smembers(name): 返回集合中的所有元素。
  • srandmember(name, count=None): 返回集合中一个或多个随机元素。
  • scard(name): 返回集合中的元素个数。
  • sinter(keys, *args): 返回多个集合的交集。
  • sunion(keys, *args): 返回多个集合的并集。
  • sdiff(keys, *args): 返回多个集合的差集。
import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 往集合中添加元素
r.sadd('myset', 'a', 'b', 'c')

# 从集合中删除元素
r.srem('myset', 'c')

# 检查指定元素是否存在于集合中
exists = r.sismember('myset', 'a')
print(exists)  # 输出 True

# 返回集合中的所有元素
values = r.smembers('myset')
print(values)  # 输出 {b'a', b'b'}

# 返回集合中一个或多个随机元素
random_values = r.srandmember('myset', 2)
print(random_values)  # 输出 [b'b', b'a']

# 返回集合的元素个数
count = r.scard('myset')
print(count)  # 输出 2

# 创建另一个集合
r.sadd('otherset', 'a', 'd')

# 返回多个集合的交集
inter = r.sinter(['myset', 'otherset'])
print(inter)  # 输出 {b'a'}

# 返回多个集合的并集
union = r.sunion(['myset', 'otherset'])
print(union)  # 输出 {b'a', b'b', b'd'}

# 返回多个集合的差集
diff = r.sdiff(['myset', 'otherset'])
print(diff)  # 输出 {b'b'}

Python操作有序集合(ZSet)

  • zadd(name, mapping): 往有序集合中添加一个或多个元素。
  • zrem(name, values): 从有序集合中删除一个或多个元素。
  • zscore(name, value): 返回指定元素的分值。
  • zrange(name, start, end, withscores=False): 返回有序集合中排名在 start 和 end 之间的元素。
  • zrevrange(name, start, end, withscores=False): 返回有序集合中分值在 start 和 end 之间的元素,按分值从大到小排序。
  • zcard(name): 返回有序集合中的元素个数。
  • zcount(name, min, max): 返回有序集合中分值在 min 和 max 之间的元素个数。
  • zrank(name, value): 返回指定元素在有序集合中的排名。
  • zrevrank(name, value): 返回指定元素在有序集合中的排名,按分值从大到小排序。
  • zincrby(name, amount, value): 将指定元素的分值增加 amount。
  • zremrangebyrank(name, start, end): 删除有序集合中排名在 start 和 end 之间的元素。
  • zremrangebyscore(name, min, max): 删除有序集合中分值在 min 和 max 之间的元素。
import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 往有序集合中添加元素
r.zadd('myzset', {'a': 1, 'b': 2, 'c': 3})

# 返回有序集合中排名在 0 和 1 之间的元素
range_values = r.zrange('myzset', 0, 1, withscores=True)
print(range_values)  # 输出 [(b'a', 1.0), (b'b', 2.0)]

# 返回有序集合中分值在 1 和 2 之间的元素,按分值从大到小排序
revrange_values = r.zrevrange('myzset', 1, 2, withscores=True)
print(revrange_values)  # 输出 [(b'b', 2.0), (b'c', 3.0)]

# 返回指定元素的分值
score = r.zscore('myzset', 'a')
print(score)

pipeline 对象

在 Redis 中,为了减少网络往返次数,提高性能,我们可以使用 Redis 的 pipeline 来将多个 Redis 操作打包到一个请求中发送给 Redis 服务器,Redis 服务器将一次性返回所有操作的结果。

在 Python 中,可以使用 Redis 的 pipeline 来执行多个 Redis 操作,例如插入、删除、修改等,而不需要将每个操作都发送到 Redis 服务器。这样可以大大减少网络往返次数,提高 Redis 的性能。

pipeline 通常用于执行大量的相似 Redis 操作,例如插入、删除、修改等操作,可以将这些操作打包到一个 pipeline 中,一次性发送到 Redis 服务器执行,而不需要等待每个操作的结果。

在 Python 中,可以使用 pipeline() 方法来创建一个 pipeline 对象,然后使用 pipeline 对象执行多个 Redis 操作。例如:

import redis

# 创建 Redis 客户端
r = redis.Redis(host='localhost', port=6379, db=0)

# 创建 pipeline 对象
pipe = r.pipeline()

# 将多个 Redis 操作添加到 pipeline 中
pipe.set('mykey', 'value1')
pipe.set('mykey2', 'value2')
pipe.get('mykey')
pipe.get('mykey2')

# 执行 pipeline 中的操作
result = pipe.execute()

# 输出操作结果
print(result)  # 输出 [True, True, b'value1', b'value2']

在上面的例子中,我们首先使用 pipeline() 方法创建了一个 pipeline 对象,然后将多个 Redis 操作添加到 pipeline 中。最后,使用 execute() 方法执行 pipeline 中的所有操作,并将操作的结果存储在一个列表中。

Redis数据库连接池

在 Python 中,使用 Redis 的客户端连接 Redis 服务器时,每个连接都需要建立 TCP 连接、认证、选择数据库等步骤,这些步骤会增加 Redis 服务器的负载,同时也会降低客户端的性能。

为了减少每个 Redis 操作的开销,Python 的 Redis 客户端提供了 Connection Pool(连接池)机制,通过连接池,可以实现 Redis 客户端的连接复用,减少连接建立的开销,提高 Redis 客户端的性能。

在 Python 中,可以使用 redis.ConnectionPool() 方法来创建一个连接池,然后使用 redis.Redis(connection_pool=pool) 方法来创建一个 Redis 客户端,并将连接池作为参数传递。

import redis

# 创建一个连接池
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)

# 创建一个 Redis 客户端,并将连接池作为参数传递
r = redis.Redis(connection_pool=pool)

# 使用 Redis 客户端执行操作
r.set('mykey', 'myvalue')
print(r.get('mykey'))

附录 C++ hiredis库 (人生苦短)

在 C++ 中,可以使用 hiredis 库来连接 Redis 服务器,该库提供了和 Redis 命令一一对应的 C 语言 API。

使用 hiredis 库操作 Redis 的步骤大致如下:

  1. 创建 Redis 连接对象
  2. 构造 Redis 命令并发送给 Redis 服务器
  3. 解析 Redis 服务器返回的响应
  4. 释放 Redis 连接对象
#include <iostream>
#include <hiredis/hiredis.h>

int main() {
    // 1. 创建 Redis 连接对象
    redisContext* redis_conn = redisConnect("localhost", 6379);
    if (redis_conn == nullptr || redis_conn->err) {
        if (redis_conn) {
            std::cout << "Error: " << redis_conn->errstr << std::endl;
            redisFree(redis_conn);
        } else {
            std::cout << "Error: Failed to allocate redis context" << std::endl;
        }
        return -1;
    }

    // 2. 构造 Redis 命令并发送给 Redis 服务器
    redisReply* redis_reply = nullptr;

    // 使用 RPUSH 命令向列表中添加元素
    redis_reply = static_cast<redisReply*>(redisCommand(redis_conn, "RPUSH mylist a b c"));
    if (redis_reply == nullptr) {
        std::cout << "Error: Failed to execute Redis command" << std::endl;
        redisFree(redis_conn);
        return -1;
    }

    // 使用 LLEN 命令获取列表长度
    redis_reply = static_cast<redisReply*>(redisCommand(redis_conn, "LLEN mylist"));
    if (redis_reply == nullptr) {
        std::cout << "Error: Failed to execute Redis command" << std::endl;
        redisFree(redis_conn);
        return -1;
    }
    std::cout << "List length: " << redis_reply->integer << std::endl;

    // 3. 解析 Redis 服务器返回的响应
    freeReplyObject(redis_reply);

    // 4. 释放 Redis 连接对象
    redisFree(redis_conn);

    return 0;
}

人生苦短,我用Python!!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐