”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Redis 解释:主要功能、用例和实践项目

Redis 解释:主要功能、用例和实践项目

发布于2024-11-06
浏览:483

Redis Explained: Key Features, Use Cases, and a Hands-on Project

Introduction

Redis is an open-source, in-memory data structure store used as a database, cache, and message broker. It’s known for its performance, simplicity, and support for various data structures such as strings, hashes, lists, sets, and more.

In this article, we’ll dive into:

  • What Redis is and how it works.
  • Key features of Redis.
  • Common use cases of Redis.
  • How to implement Redis in a simple Python-based project.

1. What is Redis?

Redis (Remote Dictionary Server) is a powerful, open-source in-memory key-value data store that can be used as a cache, database, and message broker. Unlike traditional databases, Redis stores data in-memory, making read and write operations extremely fast.

Redis supports various types of data structures including:

  • Strings (binary-safe strings)
  • Lists (collections of strings, sorted by insertion order)
  • Sets (unordered collections of unique strings)
  • Hashes (maps between string fields and values)
  • Sorted Sets (collections of unique strings ordered by score)
  • Bitmaps, HyperLogLogs, and more.

Why Redis?

Redis is preferred for use cases that require high-speed transactions and real-time performance. Its ability to store data in-memory ensures that operations like fetching, updating, and deleting data happen almost instantly.


2. Key Features of Redis

2.1. In-memory Storage

Redis primarily operates in-memory, meaning data is stored in the system's RAM, making access to it incredibly fast. However, Redis can persist data to disk, providing durability in case of system failures.

Example: Storing and Retrieving Data In-Memory

import redis

# Connect to Redis server
r = redis.StrictRedis(host='localhost', port=6379, db=0)

# Store data in Redis
r.set('key1', 'value1')

# Retrieve data from Redis
value = r.get('key1').decode('utf-8')
print(f"Retrieved value: {value}")

In this example, the data (key1, value1) is stored in Redis memory and can be retrieved instantly without needing a database read.


2.2. Persistence

Redis provides two primary persistence mechanisms:

  • RDB (Redis Database Backup): Periodic snapshots of the data.
  • AOF (Append-Only File): Logs every operation to disk in real-time.

You can configure Redis for persistence in the redis.conf file.

Example: Enabling RDB Persistence

In redis.conf, you can specify how often Redis should save the data to disk. Here's an example:

save 900 1   # Save the dataset if at least 1 key changes within 900 seconds
save 300 10  # Save the dataset if at least 10 keys change within 300 seconds

Example: Enabling AOF Persistence

In redis.conf, enable AOF:

appendonly yes

This will log every operation that modifies the data to an append-only file.


2.3. Advanced Data Structures

Redis supports a variety of data structures beyond simple key-value pairs.

2.3.1. Lists

Lists are ordered collections of strings. You can push and pop elements from either end.

# Add items to a Redis list
r.rpush('mylist', 'item1', 'item2', 'item3')

# Get the entire list
mylist = r.lrange('mylist', 0, -1)
print(mylist)

# Pop an item from the left
item = r.lpop('mylist')
print(f"Popped: {item}")

2.3.2. Sets

Sets are unordered collections of unique strings. Redis ensures that no duplicates exist in a set.

# Add items to a Redis set
r.sadd('myset', 'item1', 'item2', 'item3')

# Check if an item exists in the set
exists = r.sismember('myset', 'item2')
print(f"Is item2 in the set? {exists}")

# Get all items from the set
all_items = r.smembers('myset')
print(all_items)

2.3.3. Hashes

Hashes are maps of fields to values, like Python dictionaries.

# Create a hash in Redis
r.hset('user:1', mapping={'name': 'John', 'age': '30', 'country': 'USA'})

# Retrieve a single field from the hash
name = r.hget('user:1', 'name').decode('utf-8')
print(f"Name: {name}")

# Get all fields and values
user_data = r.hgetall('user:1')
print(user_data)

2.3.4. Sorted Sets

Sorted Sets are like sets but with a score that determines the order of the elements.

# Add items with a score to a sorted set
r.zadd('mysortedset', {'item1': 1, 'item2': 2, 'item3': 3})

# Get items from the sorted set
items = r.zrange('mysortedset', 0, -1, withscores=True)
print(items)

# Increment the score of an item
r.zincrby('mysortedset', 2, 'item1')  # Increment 'item1' score by 2

2.4. Pub/Sub Messaging System

Redis supports publish/subscribe (pub/sub) messaging, making it great for real-time applications such as chat apps or notifications.

Example: Publisher

# Publish a message to a channel
r.publish('chatroom', 'Hello, Redis!')

Example: Subscriber

# Subscribe to a channel
pubsub = r.pubsub()
pubsub.subscribe('chatroom')

# Listen for new messages
for message in pubsub.listen():
    if message['type'] == 'message':
        print(f"Received: {message['data'].decode('utf-8')}")

In this example, the publisher sends messages to a "chatroom" channel, and any subscribed clients will receive those messages.


2.5. Atomic Operations

All Redis operations are atomic, meaning they will either complete fully or not at all, which is crucial for maintaining consistency in data modification.

Example: Increment Counter Atomically

# Set an initial counter
r.set('counter', 0)

# Increment the counter
r.incr('counter')
current_value = r.get('counter').decode('utf-8')
print(f"Counter Value: {current_value}")

# Decrement the counter
r.decr('counter')
current_value = r.get('counter').decode('utf-8')
print(f"Counter Value after decrement: {current_value}")

In this example, incr and decr are atomic operations that increment and decrement the value, ensuring data consistency even in concurrent environments.


2.6. Scalability

Redis supports clustering for horizontal scalability, allowing data to be distributed across multiple Redis nodes. With clustering, Redis can handle large datasets and high throughput by spreading the load across multiple servers.

Example: Redis Cluster Setup (Brief Overview)

To set up a Redis cluster, you'll need multiple Redis nodes. Here’s an overview of commands used to create a Redis cluster:

  1. Start multiple Redis instances.
  2. Use the redis-cli to create a cluster:
   redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 --cluster-replicas 1

In production, you would have several Redis instances on different servers and use Redis’s internal partitioning mechanism to scale horizontally.


3. Common Use Cases of Redis

3.1. Caching

Redis is widely used as a cache to store frequently accessed data temporarily. This reduces the need to query the primary database for every request, thus improving performance.

Example: Caching API responses

import redis
import requests

r = redis.StrictRedis(host='localhost', port=6379, db=0)

def get_weather_data(city):
    key = f"weather:{city}"
    # Check if the data is in cache
    if r.exists(key):
        return r.get(key).decode('utf-8')
    else:
        response = requests.get(f"https://api.weather.com/{city}")
        data = response.json()
        # Cache the response for 10 minutes
        r.setex(key, 600, str(data))
        return data

3.2. Session Management

Redis is commonly used to manage sessions in web applications due to its ability to quickly store and retrieve user session data.

3.3. Real-Time Analytics

Redis is used to manage counters, leaderboard scores, and real-time metrics because of its atomic increment operations.

3.4. Pub/Sub System

Redis's pub/sub model is used for real-time messaging, such as chat systems and notification services.


4. Example Project: Building a Real-time Chat Application Using Redis

To demonstrate Redis in action, let’s build a simple real-time chat application using Python and Redis. We'll use Redis' pub/sub mechanism to send and receive messages between users.

4.1. Prerequisites

  • Install Redis on your local machine or use a Redis cloud service.
  • Install Python packages:

    pip install redis flask
    

4.2. Setting Up Redis Pub/Sub

Publisher:

The publisher will send messages to a channel.

import redis

def publish_message(channel, message):
    r = redis.StrictRedis(host='localhost', port=6379, db=0)
    r.publish(channel, message)

if __name__ == "__main__":
    channel = 'chatroom'
    while True:
        message = input("Enter a message: ")
        publish_message(channel, message)

Subscriber:

The subscriber listens to messages from the channel.

import redis

def subscribe_to_channel(channel):
    r = redis.StrictRedis(host='localhost', port=6379, db=0)
    pubsub = r.pubsub()
    pubsub.subscribe(channel)

    for message in pubsub.listen():
        if message['type'] == 'message':
            print(f"Received: {message['data'].decode('utf-8')}")

if __name__ == "__main__":
    channel = 'chatroom'
    subscribe_to_channel(channel)

4.3. Setting Up Flask Web Interface

Now, let's create a simple Flask app that allows users to chat in real time using Redis.

Flask App (app.py):

from flask import Flask, render_template, request
import redis

app = Flask(__name__)
r = redis.StrictRedis(host='localhost', port=6379, db=0)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/send', methods=['POST'])
def send_message():
    message = request.form['message']
    r.publish('chatroom', message)
    return 'Message sent!'

if __name__ == "__main__":
    app.run(debug=True)

HTML Template (index.html):



    
    
    Chat Room


    

Real-Time Chat

4.4. Running the Application

  1. Run the Redis server.
  2. Start the Flask app by running:
   python app.py
  1. Open multiple browser tabs pointing to localhost:5000 and try chatting. Messages will be broadcast to all open tabs using Redis' pub/sub system.

5. Conclusion

Redis is an incredibly powerful tool for high-performance applications that require fast access to data, real-time communication, or temporary storage. With its diverse data structures and features like persistence, pub/sub, and atomic operations, Redis can fit into many different use cases, from caching to message brokering.

By implementing this simple chat application, you’ve seen how Redis can handle real-time messaging in a highly performant and scalable way.


Join me to gain deeper insights into the following topics:

  • Python
  • Data Streaming
  • Apache Kafka
  • Big Data
  • Real-Time Data Processing
  • Stream Processing
  • Data Engineering
  • Machine Learning
  • Artificial Intelligence
  • Cloud Computing
  • Internet of Things (IoT)
  • Data Science
  • Complex Event Processing
  • Kafka Streams
  • APIs
  • Cybersecurity
  • DevOps
  • Docker
  • Apache Avro
  • Microservices
  • Technical Tutorials
  • Developer Community
  • Data Visualization
  • Programming

Stay tuned for more articles and updates as we explore these areas and beyond.

版本声明 本文转载于:https://dev.to/amitchandra/redis-explained-key-features-use-cases-and-a-hands-on-project-1hdf?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 反射动态实现Go接口用于RPC方法探索
    反射动态实现Go接口用于RPC方法探索
    在GO 使用反射来实现定义RPC式方法的界面。例如,考虑一个接口,例如:键入myService接口{ 登录(用户名,密码字符串)(sessionId int,错误错误) helloworld(sessionid int)(hi String,错误错误) } 替代方案而不是依靠反射...
    编程 发布于2025-06-08
  • Spark DataFrame添加常量列的妙招
    Spark DataFrame添加常量列的妙招
    在Spark Dataframe ,将常数列添加到Spark DataFrame,该列具有适用于所有行的任意值的Spark DataFrame,可以通过多种方式实现。使用文字值(SPARK 1.3)在尝试提供直接值时,用于此问题时,旨在为此目的的column方法可能会导致错误。 df.withCo...
    编程 发布于2025-06-08
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-06-08
  • 对象拟合:IE和Edge中的封面失败,如何修复?
    对象拟合:IE和Edge中的封面失败,如何修复?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    编程 发布于2025-06-08
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中3个Party Package将另一个PAXPANCE带有导入式套件之间的另一个软件包,并在导入式套件之间导入另一个软件包。如回声消息所证明的那样: go.etcd.io/bbolt [&&&&&&&&&&&&&&&&...
    编程 发布于2025-06-08
  • CSS可以根据任何属性值来定位HTML元素吗?
    CSS可以根据任何属性值来定位HTML元素吗?
    靶向html元素,在CSS 中使用任何属性值,在CSS中,可以基于特定属性(如下所示)基于特定属性的基于特定属性的emants目标元素: 字体家庭:康斯拉斯(Consolas); } 但是,出现一个常见的问题:元素可以根据任何属性值而定位吗?本文探讨了此主题。的目标元素有任何任何属性值,属...
    编程 发布于2025-06-08
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-06-08
  • 哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    在Python Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a path object to represent the polygon.它...
    编程 发布于2025-06-08
  • Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    在ASP.NET async void void async void void void void void的设计无需返回asynchroncon而无需返回任务对象。他们在执行过程中增加未偿还操作的计数,并在完成后减少。在某些情况下,这种行为可能是有益的,例如未期望或明确预期操作结果的火灾和...
    编程 发布于2025-06-08
  • 如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    使用http request 上传文件上传到http server,同时也提交其他参数,java.net.net.urlconnection and Multipart/form-data Encoding是普遍的。 Here's a breakdown of the process:Mu...
    编程 发布于2025-06-08
  • Python中嵌套函数与闭包的区别是什么
    Python中嵌套函数与闭包的区别是什么
    嵌套函数与python 在python中的嵌套函数不被考虑闭合,因为它们不符合以下要求:不访问局部范围scliables to incling scliables在封装范围外执行范围的局部范围。 make_printer(msg): DEF打印机(): 打印(味精) ...
    编程 发布于2025-06-08
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    在Java 中,以全屏幕独立模式运行Java应用程序时,通常无法按期望的工作可能无法使用JAVA应用程序时,将用户输入在Java ProblemPassive rendering mode allows the use of KeyListener and ActionListener inter...
    编程 发布于2025-06-08
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,以便更快地搜索这些前缀。理解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-06-08
  • 找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    如何在mySQL中使用mySql 检索最大计数,您可能会遇到一个问题,您可能会在尝试使用以下命令:理解错误正确找到由名称列分组的值的最大计数,请使用以下修改后的查询: 计数(*)为c 来自EMP1 按名称组 c desc订购 限制1 查询说明 select语句提取名称列和每个名称...
    编程 发布于2025-06-08
  • 如何在Chrome中居中选择框文本?
    如何在Chrome中居中选择框文本?
    选择框的文本对齐:局部chrome-inly-ly-ly-lyly solument 您可能希望将文本中心集中在选择框中,以获取优化的原因或提高可访问性。但是,在CSS中的选择元素中手动添加一个文本 - 对属性可能无法正常工作。初始尝试 state)</option> < op...
    编程 发布于2025-06-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3