标签归档:redis

教你纯原生实现Redis简易客户端(绕过Qmt白名单)

Redis 是我们在开发过程中经常会用到的内存数据库,尤其是在Python的第三方模块Redis-py的支持下,在Python中使用Redis及其方便。

但是在有些情况下,我们无法使用像Redis-py这样的第三方模块(比如QMT),这时候就需要自己实现一个简易版的Redis-py了。

本文将教大家如何用20行代码,制作一个简易版的Redis客户端,不过仅以GET命令为例,其他命令的用法也差不多。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

2.原理剖析

其实通过Redis GET返回的数据就是一些字符串,这些字符串的格式如下:

b'$466\r\n\x80\x04\x95\xc7\x01\x00\x00\x00\x00\x00\x00]\x94(\x8c\x06000957\x94\x8c\x06002031\x94\x8c\x06000899\x94\x8c\x06300339\x94\x8c\x06002090\x94\x8c\x06601016\x94\x8c\x06002547\x94\x8c\x06002863\x94\x8c\x06002591\x94\x8c\x06002514\x94\x8c\x06000629\x94\x8c\x06002204\x94\x8c\x06000544\x94\x8c\x06002374\x94\x8c\x06000821\x94\x8c\x06000625\x94\x8c\x06000158\x94\x8c\x06002703\x94\x8c\x06002866\x94\x8c\x06600686\x94\x8c\x06002796\x94\x8c\x06300598\x94\x8c\x06002101\x94\x8c\x06002454\x94\x8c\x06000970\x94\x8c\x06000631\x94\x8c\x06002121\x94\x8c\x06600348\x94\x8c\x06600996\x94\x8c\x06002080\x94\x8c\x06002194\x94\x8c\x06002466\x94\x8c\x06300663\x94\x8c\x06002616\x94\x8c\x06000665\x94\x8c\x06600992\x94\x8c\x06300750\x94\x8c\x06300059\x94\x8c\x06002047\x94\x8c\x06002997\x94\x8c\x06000521\x94\x8c\x06002594\x94\x8c\x06002261\x94\x8c\x06002125\x94\x8c\x06002085\x94\x8c\x06002168\x94\x8c\x06002665\x94\x8c\x06002523\x94\x8c\x06603067\x94\x8c\x06002432\x94e.\r\n'

可见其是一个bytes字符串,开头$xxx是此数据的长度,\r\n作为分割符,后面紧跟着的就是你的原始数据内容,最后才是\r\n作为结尾。

根据这个返回内容,我们就可以制作一个简易的客户端用于在无法引用第三方模块的环境中接收Redis信息。

3.编写简易Redis客户端

与Redis通信,我们只需要用Python原生的socket模块即可。

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
s.close()

这样就与你的Redis服务器连接上了,接下来只需要向socket发送你的命令并receive即可获取对应的内容:

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某个 KEY 的内容
s.send("GET RQB_keys_20220719 \r\n".encode("utf-8"))
# 接收小于 1M 的数据
msg = s.recv(1024 * 1024) 
s.close()
print(msg)
# b'$466\r\n\x80\x04\x95\xc7\x01\x00\x00\x00\x00\x00\x00]\x94(\x8c\x06000957\x94\x8c\x06002031\x94\x8c\x06000899\x94\x8c\x06300339\x94\x8c\x06002090\x94\x8c\x06601016\x94\x8c\x06002547\x94\x8c\x06002863\x94\x8c\x06002591\x94\x8c\x06002514\x94\x8c\x06000629\x94\x8c\x06002204\x94\x8c\x06000544\x94\x8c\x06002374\x94\x8c\x06000821\x94\x8c\x06000625\x94\x8c\x06000158\x94\x8c\x06002703\x94\x8c\x06002866\x94\x8c\x06600686\x94\x8c\x06002796\x94\x8c\x06300598\x94\x8c\x06002101\x94\x8c\x06002454\x94\x8c\x06000970\x94\x8c\x06000631\x94\x8c\x06002121\x94\x8c\x06600348\x94\x8c\x06600996\x94\x8c\x06002080\x94\x8c\x06002194\x94\x8c\x06002466\x94\x8c\x06300663\x94\x8c\x06002616\x94\x8c\x06000665\x94\x8c\x06600992\x94\x8c\x06300750\x94\x8c\x06300059\x94\x8c\x06002047\x94\x8c\x06002997\x94\x8c\x06000521\x94\x8c\x06002594\x94\x8c\x06002261\x94\x8c\x06002125\x94\x8c\x06002085\x94\x8c\x06002168\x94\x8c\x06002665\x94\x8c\x06002523\x94\x8c\x06603067\x94\x8c\x06002432\x94e.\r\n'

请注意,recv里你设定的大小会直接占用内存,所以请设定一个适宜的数目,或者从返回值中的美元符后的数字判断你需要接收的数据大小。

比如第一次请求,你只接收1024个字节,拿到 $xxx 这个长度后,重新send一次命令,再 s.recv(xxx) 长度。

上述例子中得到的内容是redis的格式,我们需要把\r\n给去除掉,并只取中间的数据便是我们存入redis的原始数据。

import pickle
def get_msg(msg):
    msg_new = msg.split(b"\r\n")[1]
    msg = pickle.loads(msg_new)
    return msg

因为我的原始内容是pickle格式,因此我在取出原始数据后使用pickle.loads便能拿到我想要的内容,完整代码如下:

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某个 KEY 的内容
s.send("GET RQB_keys_20220719 \r\n".encode("utf-8"))
# 接收小于 1M 的数据
msg = s.recv(1024 * 1024) 
s.close()

def get_msg(msg):
    msg_new = msg.split(b"\r\n")[1]
    msg = pickle.loads(msg_new)
    return msg

print(get_msg(msg))

效果如下:

['000957', '002031', '000899', '300339', '002090', '601016', '002547', '002863', '002591', '002514', '000629', '002204', '000544', '002374', '000821', '000625', '000158', '002703', '002866', '600686', '002796', '300598', '002101', '002454', '000970', '000631', '002121', '600348', '600996', '002080', '002194', '002466', '300663', '002616', '000665', '600992', '300750', '300059', '002047', '002997', '000521', '002594', '002261', '002125', '002085', '002168', '002665', '002523', '603067', '002432']

在QMT等会限制第三方模块的软件中,使用这样的方式访问Redis,就不会再遇到白名单的限制了。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

如何在Django中使用redis?

问题:如何在Django中使用redis?

我听说过redis-cache,但是它是如何工作的呢?通过以某种方式缓存rdbms查询,它是否被用作Django和我的rdbms之间的一层?

还是应该将其直接用作数据库?我对此表示怀疑,因为该github页面不包含任何登录详细信息,所以没有设置..只是告诉您设置一些config属性。

I’ve heard of redis-cache but how exactly does it work? Is it used as a layer between django and my rdbms, by caching the rdbms queries somehow?

Or is it supposed to be used directly as the database? Which I doubt, since that github page doesn’t cover any login details, no setup.. just tells you to set some config property.


回答 0

这个Redis的Python模块在自述文件中有一个清晰的用法示例:http : //github.com/andymccurdy/redis-py

Redis被设计为RAM缓存。它支持键的基本GET和SET以及字典等集合的存储。您可以通过将RDBMS查询的输出存储在Redis中来缓存它们。目标是加快Django网站的速度。在需要速度之前,不要开始使用Redis或任何其他缓存-不要过早地进行优化。

This Python module for Redis has a clear usage example in the readme: http://github.com/andymccurdy/redis-py

Redis is designed to be a RAM cache. It supports basic GET and SET of keys plus the storing of collections such as dictionaries. You can cache RDBMS queries by storing their output in Redis. The goal would be to speed up your Django site. Don’t start using Redis or any other cache until you need the speed – don’t prematurely optimize.


回答 1

仅仅因为Redis将事物存储在内存中并不意味着它就是缓存。我见过人们将它用作数据的持久存储。

可以将其用作高速缓存暗示它可以用作高性能存储。如果您的Redis系统出现故障,则可能会丢失尚未再次写回到磁盘的数据。有一些方法可以减轻这种危险,例如,热备份副本。如果您的数据是“关键任务”,例如您经营一家银行或商店,那么Redis可能不是您的最佳选择。但是,如果您使用持久的实时数据或一些社交互动的东西来编写流量高的游戏,并且将数据丢失的可能性控制在可以接受的范围内,那么Redis可能值得一看。

无论如何,重点仍然存在,是的,Redis可以用作数据库。

Just because Redis stores things in-memory does not mean that it is meant to be a cache. I have seen people using it as a persistent store for data.

That it can be used as a cache is a hint that it is useful as a high-performance storage. If your Redis system goes down though you might loose data that was not been written back onto the disk again. There are some ways to mitigate such dangers, e.g. a hot-standby replica. If your data is ‘mission-critical’, like if you run a bank or a shop, Redis might not be the best pick for you. But if you write a high-traffic game with persistent live data or some social-interaction stuff and manage the probability of data-loss to be quite acceptable, then Redis might be worth a look.

Anyway, the point remains, yes, Redis can be used as a database.


回答 2

Redis基本上是一个“记忆中”的KV存储,带有大量的铃声和口哨声。它非常灵活。您可以将其用作临时存储(例如缓存)或永久存储(例如数据库)(带有其他答案中提到的警告)。

当与Django结合使用时,Redis的最佳/最常见用例可能是缓存“响应”和会话。

这里有一个后端https://github.com/sebleier/django-redis-cache/和Django文档中的出色文档,这里是https://docs.djangoproject.com/en/1.3/topics/cache/

我最近开始使用https://github.com/erussell/django-redis-status监视我的缓存-很有魅力。(在redis上配置maxmemory或结果不是很有用)。

Redis is basically an ‘in memory’ KV store with loads of bells and whistles. It is extremely flexible. You can use it as a temporary store, like a cache, or a permanent store, like a database (with caveats as mentioned in other answers).

When combined with Django the best/most common use case for Redis is probably to cache ‘responses’ and sessions.

There’s a backend here https://github.com/sebleier/django-redis-cache/ and excellent documentation in the Django docs here: https://docs.djangoproject.com/en/1.3/topics/cache/ .

I’ve recently started using https://github.com/erussell/django-redis-status to monitor my cache – works a charm. (Configure maxmemory on redis or the results aren’t so very useful).


回答 3

您还可以将Redis用作Django应用程序中分布式任务的队列。您可以将其用作CeleryPython RQ的消息代理。

You can also use Redis as a queue for distributed tasks in your Django app. You can use it as a message broker for Celery or Python RQ.


回答 4

Redis作为主数据库

是的,您可以将Redis键值存储用作主数据库。Redis不仅存储键值对,还支持不同的数据结构,例如

  1. 清单
  2. 排序集
  3. 散列
  4. 位图
  5. 超级日志

Redis数据类型官方文档

Redis在内存键值存储中,因此如果Redis服务器发生故障,您必须知道它,您的数据将丢失。

Redis还可以保留数据检查官方文档。

Redis Persistence官方文档


Redis作为缓存

是的,Redis驻留在Django和RDBMS之间。

这个怎么运作

given a URL, try finding that page in the cache if the page is in the cache: return the cached page else: generate the page save the generated page in the cache (for next time) return the generated page

Django的缓存框架Official Doc


如何在Django中使用Redis

我们可以将redis python客户端redis-py用于Django应用程序。

Redis Python客户端redis-py Github

我们可以将Django-redis用于Django缓存后端。

Django-redis基于redis-py构建,并添加了与Django应用程序相关的额外功能。

Django-redis doc Github

还存在其他库。


Redis用例和数据类型

一些用例

  • 会话缓存
  • 实时分析
  • Web缓存
  • 排行榜

按核心数据结构类型划分的顶级Redis用例


使用Redis的大型科技公司

 Twitter GitHub Weibo Pinterest Snapchat Craigslist Digg StackOverflow Flickr 

Redis as a Primary database

Yes you can use Redis key-value store as a primary database. Redis not only store key-value pairs it also support different data structures like

  1. List
  2. Set
  3. Sorted set
  4. Hashes
  5. Bitmaps
  6. Hyperloglogs

Redis Data types Official doc

Redis is in memory key-value store so you must aware of it if Redis server failure occurred your data will be lost.

Redis can also persist data check official doc.

Redis Persistence Official doc


Redis as a Cache

Yes Redis reside between in Django and RDBMS.

How it works

given a URL, try finding that page in the cache if the page is in the cache: return the cached page else: generate the page save the generated page in the cache (for next time) return the generated page

Django’s cache framework Official Doc


How can use Redis with Django

We can use redis python client redis-py for Django application.

Redis python client redis-py Github

We can use Django-redis for django cache backend.

Django-redis build on redis-py and added extra features related to django application.

Django-redis doc Github

Other libraries also exists.


Redis use cases and data types

Some use cases

  • Session cache
  • Real time analytics
  • Web caching
  • Leaderboards

Top Redis Use Cases by Core Data structure types


Big Tech companies using Redis

 Twitter GitHub Weibo Pinterest Snapchat Craigslist Digg StackOverflow Flickr 


redis-py:StrictRedis()和Redis()有什么区别?

问题:redis-py:StrictRedis()和Redis()有什么区别?

我想使用Redis的-PY缓存一些数据,但我无法找到之间的差异的一个合适的解释redis.StrictRedis()redis.Redis()。它们相等吗?

另外,redis.StrictRedis()Redis Python Docs中找不到关于的参数的任何清晰文档。任何想法?

I want to use redis-py for caching some data, but I can’t find a suitable explanation of the difference between redis.StrictRedis() and redis.Redis(). Are they equivalent?

In addition, I can’t find any clear documentation about redis.StrictRedis()‘s arguments in Redis Python Docs. Any idea?


回答 0

这似乎很清楚

 redis-py exposes two client classes that implement these commands
 The StrictRedis class attempts to adhere to the official command syntax.

In addition to the changes above, the Redis class, a subclass of StrictRedis,
overrides several other commands to provide backwards compatibility with older
versions of redis-py

您需要向后兼容吗?使用Redis。不在乎吗 使用StrictRedis


2017-03-31

以下是从github.com链接引用的向后兼容性的详细信息:

除了上述更改之外,Redis类是StrictRedis的子类,它重写了其他一些命令以提供与较早版本的redis-py的向后兼容性:

LREM:“ num”和“ value”参数的顺序颠倒,因此“ num”可以提供默认值零。

ZADD:Redis在’value’之前指定’score’参数。这些在实施时被意外交换,直到人们使用后才发现。Redis类期望* args的形式为:name1,score1,name2,score2,…

SETEX:“时间”和“值”参数的顺序颠倒了。


This seems pretty clear:

 redis-py exposes two client classes that implement these commands
 The StrictRedis class attempts to adhere to the official command syntax.

and

In addition to the changes above, the Redis class, a subclass of StrictRedis,
overrides several other commands to provide backwards compatibility with older
versions of redis-py

Do you need backwards compatibility? Use Redis. Don’t care? Use StrictRedis.


2017-03-31

Here are the specifics of the backwards compatibility, from the github.com link cited:

In addition to the changes above, the Redis class, a subclass of StrictRedis, overrides several other commands to provide backwards compatibility with older versions of redis-py:

LREM: Order of ‘num’ and ‘value’ arguments reversed such that ‘num’ can provide a default value of zero.

ZADD: Redis specifies the ‘score’ argument before ‘value’. These were swapped accidentally when being implemented and not discovered until after people were already using it. The Redis class expects *args in the form of: name1, score1, name2, score2, …

SETEX: Order of ‘time’ and ‘value’ arguments reversed.



回答 1

这是一个古老的问题,但对于在Google搜索后遇到此问题的任何人:

从redis-py自述文件(链接):

redis-py 3.0放弃了对旧版“ Redis”客户端类的支持。“ StrictRedis”已重命名为“ Redis”,并提供了一个名为“ StrictRedis”的别名,以便以前使用“ StrictRedis”的用户可以继续运行。

这是定义StrictRedislink)的redis-py代码的代码:

StrictRedis = Redis

It’s an old question but for anyone who reaches this question after google search:

from redis-py readme (link):

redis-py 3.0 drops support for the legacy “Redis” client class. “StrictRedis” has been renamed to “Redis” and an alias named “StrictRedis” is provided so that users previously using “StrictRedis” can continue to run unchanged.

Here is the line from redis-py code which defines StrictRedis (link):

StrictRedis = Redis

使用Celery vs. RQ的利弊[关闭]

问题:使用Celery vs. RQ的利弊[关闭]

目前,我正在处理需要实施一些后台作业(主要用于电子邮件发送和大量数据库更新)的python项目。我将Redis用于任务代理。因此,在这一点上,我有两个候选人:CeleryRQ。我对这些工作队列有一定的经验,但我想请大家分享使用此工具的经验。所以。

  1. 使用Celery vs.RQ有什么优缺点。
  2. 适合使用Celery vs. RQ的项目/任务的任何示例。

Celery看起来很复杂,但是它是功能齐全的解决方案。实际上,我认为我不需要所有这些功能。从另一方面讲,RQ非常简单(例如,配置,集成),但是它似乎缺少一些有用的功能(例如,任务吊销,代码自动重载)

Currently I’m working on python project that requires implement some background jobs (mostly for email sending and heavily database updates). I use Redis for task broker. So in this point I have two candidates: Celery and RQ. I had some experience with these job queues, but I want to ask you guys to share you experience of using this tools. So.

  1. What pros and cons to use Celery vs. RQ.
  2. Any examples of projects/task suitable to use Celery vs. RQ.

Celery looks pretty complicated but it’s full featured solution. Actually I don’t think that I need all these features. From other side RQ is very simple (e.g configuration, integration), but it seems that it lacks some useful features (e.g task revoking, code auto-reloading)


回答 0

这是我在尝试回答这个完全相同的问题时发现的。它可能不全面,甚至在某些方面可能不准确。

简而言之,RQ被设计为更简单。Celery被设计为更坚固。他们俩都很棒。

  • 文档。RQ的文档全面而又不复杂,并且反映了项目的整体简单性-您永远不会感到迷茫或困惑。Celery的文档也很全面,但是在您第一次进行设置时,由于有太多可供选择的内部化选项,因此希望能重新访问它
  • 监控。Celery的FlowerRQ仪表板都很容易设置,并且至少为您提供了90%的所有信息

  • 经纪人支持。Celery无疑是赢家,RQ仅支持Redis。这意味着有关“什么是经纪人”的文档更少,但是也意味着,如果Redis不再为您服务,则您将来将无法切换经纪人。例如,Instagram在Celery中同时考虑了Redis和RabbitMQ。这很重要,因为不同的代理有不同的保证,例如,Redis 无法(截至撰写时)保证100%传递您的消息。

  • 优先级队列。RQ的优先级队列模型简单有效,工作人员按顺序从队列中读取。Celery要求纺纱多个工人从不同的队列消费。两种方法都有效

  • 操作系统支持。Celery无疑是赢家,因为RQ仅在支持forkUnix系统的系统上运行

  • 语言支持。RQ仅支持Python,而Celery允许您将任务从一种语言发送到另一种语言

  • API。Celery非常灵活(多个结果后端,漂亮的配置格式,工作流画布支持),但是自然地,这种功能可能会令人困惑。相比之下,RQ API很简单。

  • 子任务支持。Celery支持子任务(例如,从现有任务中创建新任务)。我不知道RQ是否

  • 社区与稳定。Celery可能更成熟,但它们都是活跃的项目。截至撰写本文时,Celery在Github上拥有约3500颗星,而RQ拥有约2000颗星,并且两个项目都显示出积极的发展

我认为,Celery并不像其声誉可能会让您相信的那么复杂,但是您将不得不使用RTFM。

那么,为什么有人愿意将(可能功能更全的)Celery换成RQ?在我看来,这全都归结为简单性。通过限制自己使用Redis + Unix,RQ提供了更简单的文档,更简单的代码库和更简单的API。这意味着您(以及潜在的项目贡献者)可以专注于您关心的代码,而不必在工作内存中保留有关任务队列系统的详细信息。我们每个人一次都有多少个限制,并且不再需要在其中保留任务队列详细信息,因此RQ让您回到您关心的代码。这种简单性是以语言间任务队列,广泛的操作系统支持,100%可靠的消息保证以及轻松切换消息代理的功能为代价的。

Here is what I have found while trying to answer this exact same question. It’s probably not comprehensive, and may even be inaccurate on some points.

In short, RQ is designed to be simpler all around. Celery is designed to be more robust. They are both excellent.

  • Documentation. RQ’s documentation is comprehensive without being complex, and mirrors the project’s overall simplicity – you never feel lost or confused. Celery’s documentation is also comprehensive, but expect to be re-visiting it quite a lot when you’re first setting things up as there are too many options to internalize
  • Monitoring. Celery’s Flower and the RQ dashboard are both very simple to setup and give you at least 90% of all information you would ever want

  • Broker support. Celery is the clear winner, RQ only supports Redis. This means less documentation on “what is a broker”, but also means you cannot switch brokers in the future if Redis no longer works for you. For example, Instagram considered both Redis and RabbitMQ with Celery. This is important because different brokers have different guarantees e.g. Redis cannot (as of writing) guarantee 100% that your messages are delivered.

  • Priority queues. RQs priority queue model is simple and effective – workers read from queues in order. Celery requires spinning up multiple workers to consume from different queues. Both approaches work

  • OS Support. Celery is the clear winner here, as RQ only runs on systems that support fork e.g. Unix systems

  • Language support. RQ only supports Python, whereas Celery lets you send tasks from one language to a different language

  • API. Celery is extremely flexible (multiple result backends, nice config format, workflow canvas support) but naturally this power can be confusing. By contrast, the RQ api is simple.

  • Subtask support. Celery supports subtasks (e.g. creating new tasks from within existing tasks). I don’t know if RQ does

  • Community and Stability. Celery is probably more established, but they are both active projects. As of writing, Celery has ~3500 stars on Github while RQ has ~2000 and both projects show active development

In my opinion, Celery is not as complex as its reputation might lead you to believe, but you will have to RTFM.

So, why would anyone be willing to trade the (arguably more full-featured) Celery for RQ? In my mind, it all comes down to the simplicity. By restricting itself to Redis+Unix, RQ provides simpler documentation, simpler codebase, and a simpler API. This means you (and potential contributors to your project) can focus on the code you care about, instead of having to keep details about the task queue system in your working memory. We all have a limit on how many details can be in our head at once, and by removing the need to keep task queue details in there RQ lets get back to the code you care about. That simplicity comes at the expense of features like inter-language task queues, wide OS support, 100% reliable message guarantees, and ability to switch message brokers easily.


回答 1

Celery并不那么复杂。从本质上讲,您可以从进行逐步配置tutorials,创建一个celery实例,用装饰您的功能,@celery.task然后使用来运行任务my_task.delay(*args, **kwargs)

从您自己的评估来看,似乎您必须在缺少(关键)功能或有些多余的东西之间进行选择。在我的书中,这并不是很难选择的选择。

Celery is not that complicated. At its core, you do the step by step configuration from the tutorials, create a celery instance, decorate your function with @celery.task then run the task with my_task.delay(*args, **kwargs).

Judging from your own assessment, it seems you have to choose between lacking (key) features or having some excess hanging around. That is not too hard of a choice in my book.


Rq Python的简单作业队列

RQ(Redis队列)是一个简单的Python库,用于对作业进行排队并在后台与工作者一起处理它们。它是由Redis支持的,它的设计是为了有一个较低的屏障进入。它应该很容易集成到您的Web堆栈中

RQ需要Redis>=3.0.0



可以找到完整的文档here

支持RQ

如果您发现RQ有用,请考虑通过以下方式支持此项目Tidelift

快速入门

当然,首先要运行Redis服务器:

$ redis-server

要将作业放到队列中,您不必执行任何特殊操作,只需定义通常较长或阻塞的函数:

import requests

def count_words_at_url(url):
    """Just an example function that's called async."""
    resp = requests.get(url)
    return len(resp.text.split())

你确实用了优秀的requests包裹,不是吗?

然后,创建RQ队列:

from redis import Redis
from rq import Queue

queue = Queue(connection=Redis())

并将函数调用排队:

from my_module import count_words_at_url
job = queue.enqueue(count_words_at_url, 'http://nvie.com')

安排作业也同样简单:

# Schedule job to run at 9:15, October 10th
job = queue.enqueue_at(datetime(2019, 10, 8, 9, 15), say_hello)

# Schedule job to run in 10 seconds
job = queue.enqueue_in(timedelta(seconds=10), say_hello)

还支持重试失败的作业:

from rq import Retry

# Retry up to 3 times, failed job will be requeued immediately
queue.enqueue(say_hello, retry=Retry(max=3))

# Retry up to 3 times, with configurable intervals between retries
queue.enqueue(say_hello, retry=Retry(max=3, interval=[10, 30, 60]))

有关更完整的示例,请参阅docs但这才是最本质的

这位工人

要开始在后台执行入队的函数调用,请从项目的目录中启动一个工作器:

$ rq worker --with-scheduler
*** Listening for work on default
Got count_words_at_url('http://nvie.com') from default
Job result = 818
*** Listening for work on default

事情就是这样

安装

只需使用以下命令即可安装最新发布的版本:

pip install rq

如果您想要最先进的版本(很可能已损坏),请使用以下命令:

pip install git+https://github.com/nvie/rq.git@master#egg=rq

相关项目

请查看下面这些可能对您的基于RQ的项目有用的报告

项目历史记录

这个项目的灵感来自于CeleryResquethis snippet,并作为celery或其他基于amqp的排队实现的轻量级替代方案而创建。

Celery-分布式任务队列(开发分支)

版本: 5.1.2(太阳谐波)
网站: https://docs.celeryproject.org/en/stable/index.html
下载: https://pypi.org/project/celery/
来源: https://github.com/celery/celery/
关键词: 任务、队列、作业、异步、rabbitmq、amqp、redis、python、分布式、参与者

捐款

这项工程有赖于你的慷慨捐助。

如果您正在使用celery创建商业产品,请考虑成为我们的backer或者我们的sponsor确保celery的未来

对于企业而言

作为Tidelift订阅的一部分提供

的维护人员celery数以千计的其他软件包正在与Tidelift合作,为您用来构建应用程序的开源依赖项提供商业支持和维护。节省时间、降低风险并提高代码的健全性,同时付钱给您使用的确切依赖项的维护人员。Learn more.

什么是任务队列?

任务队列用作跨线程或计算机分配工作的机制

任务队列的输入是一个工作单元,称为任务,专用的工作进程然后不断地监视队列以查找要执行的新工作

celery通过消息进行通信,通常使用经纪人在客户和工人之间进行调解。为了启动任务,客户端将消息放到队列中,然后代理将消息传递给工作器

celery系统可以由多个工作进程和代理组成,为高可用性和水平扩展让路。

celery是用Python编写的,但是协议可以用任何语言实现。除了Python,还有node-celery对于Node.js,一个PHP clientgocelery对于戈朗,还有rusty-celery对于生锈

语言互操作性也可以通过使用WebHook来实现,其方式是客户端将工作人员请求的URL入队

我需要什么?

celery5.1.2版运行在

  • Python(3.6、3.7、3.8、3.9)
  • Pypy3.6(7.6)

这是下一版本的celery,将支持Python 3.6或更高版本

如果您运行的是较旧版本的Python,则需要运行较旧版本的celery:

  • Python 2.6:celery系列3.1或更早版本
  • Python 2.5:celery系列3.0或更早版本
  • Python 2.4:celery系列2.2或更早版本
  • Python 2.7:celery4.x系列

celery是一个资金最少的项目,所以我们不支持Microsoft Windows。请不要打开任何与该平台相关的问题

celery通常与message broker一起使用来发送和接收消息。RabbitMQ、Redis传输功能齐全,但也有对无数其他解决方案的实验支持,包括使用SQLite进行本地开发

celery可以在单台计算机、多台计算机甚至跨数据中心运行

开始使用

如果这是您第一次尝试使用celery,或者您是以前版本的celery5.0.5或5.1.2的新手,那么您应该阅读我们的入门教程:

您还可以通过使用托管代理传输CloudAMQP开始使用celery。RabbitMQ最大的主机提供商是celery的骄傲赞助商

celery是

  • 简单

    celery很容易使用和维护,而且确实不需要配置文件

    它有一个活跃、友好的社区,您可以与之交谈以寻求支持,例如在我们的mailing-list,或IRC通道

    下面是您可以制作的最简单的应用程序之一:

    from celery import Celery
    
    app = Celery('hello', broker='amqp://guest@localhost//')
    
    @app.task
    def hello():
        return 'hello world'
  • 高可用性

    在连接丢失或故障的情况下,工作人员和客户端将自动重试,一些代理通过以下方式支持HA主要/主要主/复制副本复制

  • 快地

    单个celery进程一分钟可以处理数百万个任务,往返延迟为亚毫秒级(使用RabbitMQ、py-librabbitmq和优化设置)

  • 灵活性

    几乎每一个地方celery可以自己扩展或使用,定制池实现、序列化程序、压缩方案、日志记录、调度程序、使用者、生产者、代理传输等等

它支持

  • 消息传输
  • 并发性
  • 结果商店
    • AMQP,Redis
    • memcached
    • SQL炼金术,Django ORM
    • Apache Cassandra、IronCache、Elasticsearch
  • 序列化
    • 泡菜JSONYAML消息包
    • zlibbzip2压缩
    • 加密消息签名

框架集成

celery很容易与web框架集成,其中一些框架甚至有集成包:

Django 不需要
Pyramid pyramid_celery
Pylons celery-pylons
Flask 不需要
web2py web2py-celery
Tornado tornado-celery

集成包并不是严格必需的,但是它们可以简化开发,有时它们还会添加重要的挂钩,比如在以下位置关闭数据库连接fork

文档

这个latest documentation托管在Read the Docs上,包含用户指南、教程和API参考

最新的中文文档托管在https://www.celerycn.io/中,包含用户指南、教程、接口接口等。

安装

您可以通过Python包索引(PyPI)或从源代码安装celery

要使用安装,请执行以下操作pip

$ pip install -U Celery

捆绑包

celery还定义了一组可用于安装celery的捆绑包以及给定功能的依赖项

您可以在需求中或在pip命令行中使用方括号。可以通过逗号分隔多个捆绑包来指定它们

$ pip install "celery[librabbitmq]"

$ pip install "celery[librabbitmq,redis,auth,msgpack]"

以下捆绑包可用:

序列化程序

celery[auth] 用于使用auth安全序列化程序
celery[msgpack] 用于使用msgpack序列化程序
celery[yaml] 用于使用YAML序列化程序

并发性

celery[eventlet] 用于使用eventlet游泳池
celery[gevent] 用于使用gevent游泳池

传输和后端

celery[librabbitmq] 用于使用librabbitmq C库
celery[redis] 将Redis用作消息传输或作为结果的后端
celery[sqs] 使用Amazon SQS作为消息传输
celery[tblib]: 用于使用task_remote_tracebacks功能
celery[memcache] 用于将memcached用作结果后端(使用pylibmc)
celery[pymemcache] 用于将memcached用作结果后端(纯Python实现)
celery[cassandra] 用于将Apache Cassandra用作DataStAX驱动程序的结果后端
celery[azureblockblob] 使用Azure Storage作为结果后端(使用azure-storage)
celery[s3] 使用S3存储作为结果后端
celery[couchbase] 将Couchbase用作结果后端
celery[arangodb] 使用ArangoDB作为结果后端
celery[elasticsearch] 用于将Elasticsearch用作结果后端
celery[riak] 使用Riak作为结果后端
celery[cosmosdbsql] 使用Azure Cosmos DB作为结果后端(使用pydocumentdb)
celery[zookeeper] 用于将ZooKeeper用作消息传输
celery[sqlalchemy] 使用SQLAlChemy作为结果后端(支持)
celery[pyro] 为了使用Pyro4消息传输(实验性的)
celery[slmq] 为了使用SoftLayer消息队列传输(实验性的)
celery[consul] 用于将Consul.io密钥/值存储用作消息传输或结果后端(实验性的)
celery[django] 指定Django支持的可能最低版本

您可能不应该在您的需求中使用它,它在这里仅供参考

从源下载并安装

从PyPI下载最新版本的celery:

https://pypi.org/project/celery/

您可以通过执行以下操作来安装它:

$ tar xvfz celery-0.0.0.tar.gz
$ cd celery-0.0.0
$ python setup.py build
# python setup.py install

如果您当前未使用虚拟环境,则必须以特权用户身份执行最后一个命令

使用开发版本

带管道

celery开发版本还需要kombuamqpbilliard,以及vine

您可以使用以下pip命令安装这些快照的最新版本:

$ pip install https://github.com/celery/celery/zipball/master#egg=celery
$ pip install https://github.com/celery/billiard/zipball/master#egg=billiard
$ pip install https://github.com/celery/py-amqp/zipball/master#egg=amqp
$ pip install https://github.com/celery/kombu/zipball/master#egg=kombu
$ pip install https://github.com/celery/vine/zipball/master#egg=vine

使用GIT

请参阅投稿部分

获取帮助

邮件列表

有关celery的用途、发展和未来的讨论,请加入celery-users邮件列表

IRC

来和我们在IRC上聊天吧。这个#celery频道位于Freenode网络

漏洞跟踪器

如果您有任何建议、错误报告或烦恼,请将它们报告给我们的问题跟踪器,地址为https://github.com/celery/celery/issues/

维基

https://github.com/celery/celery/wiki

学分

贡献者

这个项目的存在要归功于所有做出贡献的人。celery的开发发生在GitHub:https://github.com/celery/celery

我们非常鼓励您参与celery的开发。如果您不喜欢GitHub(出于某种原因),欢迎您发送常规补丁

请务必同时阅读Contributing to Celery部分,请参阅文档中的

支持者

感谢我们所有的支持者!🙏[Become a backer]

赞助商

通过成为赞助商来支持这个项目。您的徽标将在此处显示,并带有指向您的网站的链接。[Become a sponsor]


许可证

此软件在新的BSD许可证下获得许可。请参阅LICENSE完整许可证文本的顶级分发目录中的文件

教你部署开源的超漂亮电子商城 — Saleor 实战教程

Saleor 是一个快速发展的开源电子商务平台,基于 Python 和 Django开发,且持续更新中,一点不用担心版本过旧的问题。

它的特点如下:

1.GraphQL API:基于GraphQL实现的前后端分离,属于最前沿的技术。
2.仪表板:管理员可以完全控制用户、流程和产品。
3.订单:订单、发货和退款的综合系统。
4.购物车:高级付款和税收选项,支持折扣和促销活动
5.支付:灵活的 API 架构允许集成任何支付方式。
6.地理自适应:自动支持多国家的结账体验。
7.支持云部署:支持Docker部署。
8.支持谷歌分析:集成了谷歌分析,可以很方便地分析流量去留。

Saleor 仓库地址:
https://github.com/mirumee/saleor

1.Saleor 部署指南

Saleor支持多种运行方式,你可以采用手动安装并运行的方式,也可以使用Docker进行运行,下面介绍全平台通用且最简单的Docker部署方案。

在按照以下说明操作之前,你需要安装Docker DesktopDocker Compose

Docker 部署 Saleor 非常方便,你只需要克隆存储库并构建镜像然后运行服务即可:

# Python 实用宝典
# 克隆存储库
git clone https://github.com/mirumee/saleor-platform.git --recursive --jobs 3
cd saleor-platform
# 构建Docker镜像
docker-compose build

如果你无法成功克隆 Salor 源代码仓库,请在Python实用宝典公众号回复:Saleor 下载全部源代码。

Saleor 使用共享文件夹来启用实时代码重新加载。如果你使用的是WindowsMacOS,则需要:

1.将克隆的 saleor-platform 目录放置到 Docker 的共享目录配置 (Settings -> Shared Drives or Preferences -> Resources -> File sharing)。

2.确保在 Docker 首选项中你有至少 5 GB 的专用内存(设置 -> 高级首选项->资源 -> 高级

执行数据库migrations及打包前端资源:

docker-compose run --rm api python3 manage.py migrate
docker-compose run --rm api python3 manage.py collectstatic --noinput

(可选)使用示例数据填充数据库:

docker-compose run --rm api python3 manage.py populatedb

最后,为自己创建一个管理员帐户:

docker-compose run --rm api python3 manage.py createsuperuser

运行服务:

使用以下命令运行Saleor:

docker-compose up

2.Saleor 架构介绍

如果你要基于 Saleor 进行开发,那么你必须了解它的架构。

Saleor 由三个重要组件组成:

1.Saleor Core, 它是GraphQL API的后端服务器。基于Django开发,数据库采用了PostgreSQL并在Redis中储存了一些缓存信息。

2.Saleor Dashboard, 这是一个可以用来经营商店的仪表盘,它是一个静态网站,因此没有任何自己的后端代码,它是一个与Saleor Core核心服务器对话的React程序。

3.Saleor Storefront, 这是基于React实现的示例商店,你可以自定义这部分代码满足你自己的需求,也可以使用 Saleor SDK 构建自定义店面。

所有三个组件都使用 GraphQL 通过 HTTPS 进行通信。

3.Saleor 扩展开发教程

虽然你可以直接基于Saleor源代码进行开发,但是官方建议不这么做,原因是一旦你的代码和Saleor官方源代码产生冲突,你就很难跟上官方的更新,最终会导致代码没人维护的尴尬局面。

因此Saleor提供了两种添加功能的方式:

1.插件功能:插件提供了一种在Saleor Core上运行附加代码的能力,而且有访问数据库的能力。

2.APPS:基于GraphQL API和Saleor Core开发APP,还可以使用WebHooks订阅事件。

下面我们介绍如何基于插件进行扩展开发。

如上图所示,Saleor Core 提供了一种回调通知事件给插件,插件基于此事件进行相关操作,并与数据库进行交互。

开发插件,你必须继承 BasePlugin 基类,然后重写部分方法,比如下面这个例子重写了 postprocess_order_creation 方法,增加了订单创建时的一些操作:

# Python实用宝典
# custom/plugin.py

from django.conf import settings
from urllib.parse import urljoin

from ..base_plugin import BasePlugin
from .tasks import api_post_request_task


class CustomPlugin(BasePlugin):
    def postprocess_order_creation(self, order: "Order", previous_value: Any):
        # 订单创建时的操作
        data = ...

        transaction_url = urljoin(settings.CUSTOM_API_URL, "transactions/createoradjust")
        api_post_request_task.delay(transaction_url, data)

加载插件, 需要在 setup.py 进行配置来自动发现已安装的插件。要使插件可被发现,你需要设置 entry_points 的 saleor_plugins 字段, 并使用这个语法定义插件:package_name = package_name.path.to:PluginClass.

示例如下:

# setup.py
from setuptools import setup

setup(
    ...,
    entry_points={
        "saleor.plugins": [
            "my_plugin = my_plugin.plugin:MyPlugin"
        ]
    }
)

如果你的插件是 Django 应用程序,包名(等号前的部分)将被添加到 Django 的 INSTALLED_APPS 中,以便你可以利用 Django 的功能,例如 ORM 集成和数据库迁移。

注意到我们前面订单创建时的操作使用了 .delay 的语法,这是 Celery 的异步任务。因为有些插件的操作就应该异步完成,Saleor 使用 Celery 并将发现 tasks.py 在插件目录中声明的所有异步任务:

# custom_plugin/tasks.py

import json
from celery import shared_task
from typing import Any, Dict

import requests
from requests.auth import HTTPBasicAuth
from django.conf import settings


@shared_task
def api_post_request(
    url: str,
    data: Dict[str, Any],
):
    try:
        username = "username"
        password = "password"
        auth = HTTPBasicAuth(username, password)
        requests.post(url, auth=auth, data=json.dumps(data), timeout=settings.TIMEOUT)
    except requests.exceptions.RequestException:
        return

上面这个 api_post_request 函数就是前面插件用到的异步任务,在插件调用delay方法后,这个任务将被塞到队列中异步执行。

好了,上面就是一个简单的插件开发例子,个人认为Saleor的开发模式还是很不错的。如果大家有需要,可以采用这个项目构建一个属于自己的商城。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典