Herramientas de usuario

Herramientas del sitio


db:redis

¡Esta es una revisión vieja del documento!


Redis

First steps

Install

$ wget <desired redis version>
$ tar xzf <file>
$ cd <created folder>
$ make

Execute

Server

$ redis-server

Client

$ redis-cli

A good explanation of what Redis is

Redis is not a database. If you need an analogy, think of it as a dict that runs on another computer.

Where in regular python dict you take things out and then modify them, in Redis you modify things inside and then you take them out. This helps if more than two Python applications talk to the same Redis.

In web development, you can use Redis as cache (key=url or post_id, value=html), as rate limiting backend (expiring entries, key=ip, value=count). In any Python project, you can use Redis as queue backend (Celery can use Redis), or to synchronize your non-essential state between Python instances.

Data structures & commands

Other commands

  • ping, if everything is good, the server will respond pong.
  • select, to select one of the 16 databases that Redis manage.

Design (and use) patterns

Redis for Python

First steps

Install

$ pip install redis

Examples

import redis
r = redis.StrictRedis(host='192.168.0.100', db=0, socket_timeout=2)
r.set('foo', 'bar')
print r.get('foo')

Highlights

  • You can connect to several isolated interfaces changing db argument.
  • Redis instances are thread safe.
  • You can't create nested structures in Redis, meaning you can't (for example) store a native redis list inside a native redis hash-map. If you need nested structures, you might want to just store a JSON instead. Another option is to store an “id”/key to a different redis object as the value of the map key, but that requires multiple calls to the server to get the full object.
  • flushdb() will flush the database you are connected to (cleaning all the keys), while flushall() will clear all the keys in every database.
  • You can obtain the keys calling the keys() function of an StricRedis object. It also accept a pattern…
r = redis.StrictRedis(host=YOUR_HOST, port=YOUR_PORT, db=YOUR_DB)
r.keys()
keys(pattern='*')
  • A Redis object has the info() to obtain information about Redis server like used memmory.
  • Other Redis methods…
    • delete to delete an instance.

DataTypes

Strings

>>> r.set('nombre', 'Jhon')
True 
>>> r.set('apellido', 'Doe')
True 
>>> r.set('nombre:codigo', '123ASDF')
True
>>> r.get('nombre')
'Jhon'
>>> r.get('nombre')
'Doe'
>>> r.get('nombre:codigo')
123ASDF

Lists

>>> r.rpush('list', '1')
1L
>>> r.rpush('list', '2')
2L
>>> r.lrange('list', '0', '2')
['1', '2']

Sets

>>> r.sadd('conjunto', '1')
1 
>>> r.sadd('conjunto', '2')
1 
>>> r.smembers('conjunto')
set(['1', '2', '23'])

Hashes

>>> r.hset('mihash', 'field1', 'hola')
1L
>>> r.hset('mihash', 'field2', 'mundo')
1L 
>>> r.hget('mihash', 'field1')
'hola'
>>> r.hgetall('mihash')
{'field2': 'mundo', 'field1': 'hola'}

Connections

Connecting/disconnecting for each operation is too expensive, so it is much better to maintain the connection opened. With redis-py it can be done by declaring a pool of connections (ConnectionPool class). redis-py uses a connection pool to manage connections to a Redis server. By default, each Redis instance you create will in turn create its own connection pool. You can choose a concrete connection pool in the next way:

pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)

Pipelines

Pipelines provide support for buffering multiple commands to the server in a single request. They can be used to dramatically increase the performance.

>>> r = redis.Redis(...)
>>> r.set('bing', 'baz')
>>> # Use the pipeline() method to create a pipeline instance
>>> pipe = r.pipeline()
>>> # The following SET commands are buffered
>>> pipe.set('foo', 'bar')
>>> pipe.get('bing')
>>> # the EXECUTE call sends all buffered commands to the server, returning
>>> # a list of responses, one for each command.
>>> pipe.execute()
[True, 'baz']

For ease of use, all commands being buffered into the pipeline return the pipeline object itself. Therefore calls can be chained like:

>>> pipe.set('foo', 'bar').sadd('faz', 'baz').incr('auto_number').execute()
[True, True, 6]

With pipelines commands are executed atomically as a group by default. To disable the atomicity but still buffer commands, it's possible to turn off transactions.

>>> pipe = r.pipeline(transaction=False)

Publish\Subscribe

PubSub object subscribes to channels and listens for new messages. Once a PubSub instance is created, channels and patterns can be subscribed to.

>>> r = redis.StrictRedis(...)
>>> p = r.pubsub()
>>> p.subscribe('my-first-channel', 'my-second-channel', ...)
>>> p.psubscribe('my-*', ...)

To send and receive message…

>>> r.publish('my-first-channel', 'some data')
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 'some data', 'pattern': None, 'type': 'message'}
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 'some data', 'pattern': 'my-*', 'type': 'pmessage'}

Every message read from a PubSub instance will be a dictionary with the following keys.

  • type: One of the following: 'subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe', 'message', 'pmessage'
  • channel: The channel [un]subscribed to or the channel a message was published to

pattern: The pattern that matched a published message's channel. Will be None in all cases except for 'pmessage' types.

  • data: The message data. With [un]subscribe messages, this value will be the number of channels and patterns the connection is currently subscribed to. With [p]message messages, this value will be the actual published message.

Unsubscribing works just like subscribing. If no arguments are passed to [p]unsubscribe, all channels or patterns will be unsubscribed from.

>>> p.unsubscribe()
>>> p.punsubscribe('my-*')

redis-py also allows you to register callback functions to handle published messages. Message handlers take a single argument, the message, which is a dictionary just like the examples above. To subscribe to a channel or pattern with a message handler, pass the channel or pattern name as a keyword argument with its value being the callback function.

>>> def my_handler(message):
...     print 'MY HANDLER: ', message['data']
>>> p.subscribe(**{'my-channel': my_handler})

If your application is not interested in the (sometimes noisy) subscribe/unsubscribe confirmation messages, you can ignore them by passing ignore_subscribe_messages=True to r.pubsub().

Notes

  • redis-py can be used together with Redis Sentinel to discover Redis nodes.

Notes

db/redis.1406833003.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)