In this chapter, we will introduce how to operate redis in Python. redis is a Key-Value database. Value supports string, list, set, zset (ordered set), hash (hash type) and other types.

For more about redis, you can refer to ourredis tutorial, note that before you start learning this chapter, you need to make sure your redis service has been installed.

The redis startup interface is as follows:

Start redis

$ ./redis-server
75858:C 25 Oct 11:43:34.329 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf
75858:M 25 Oct 11:43:34.331 * Increased maximum number of open files to 10032 (it was originally set to 256).
                _._                                                  
           _.-``__ ''-._                                            
      _.-``    `.  `_.  ''-._           Redis 3.0.3 (255fcb1a/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'
` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'
   |     PID: 75858
  `-._    `-._  `-./  _.-'    _.-'                                  
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'
_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'
_.-'    _.-'                                  
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'
_.-'    |                                  
  `-._    `-._`-.__.-'
_.-'    _.-'                                  
      `-._    `-.__.-'    _.-'                                      
          `-._        _.-'                                          
              `-.__.-'
                                             

75858:M 25 Oct 11:43:34.337 # Server started, Redis version 3.0.3
75858:M 25 Oct 11:43:34.339 * DB loaded from disk: 0.002 seconds
75858:M 25 Oct 11:43:34.339 * The server is now ready to accept connections on port 6379

You can see the default port number is6379。


Install redis module

To use redis in Python, you need to install the redis module first:

sudo pip3 install redis
或
sudo easy_install redis
或
sudo python setup.py install

Source code address:https://github.com/WoLpH/redis-py

Test whether the installation is successful:

>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'

redis provides two classes: Redis and StrictRedis. StrictRedis is used to implement most official commands, and Redis is a subclass of StrictRedis, used for backward compatibility with old versions.

The result retrieved from redis is bytes by default; we can setdecode_responses=Truechange it to a string.

Example

import redis   # Import redis module

r = redis.Redis(host='localhost', port=6379, decode_responses=True)  
r.set('name', 'example')  # Set the value corresponding to name
print(r['name'])
print(r.get('name'))  # Get the value corresponding to key name
print(type(r.get('name')))  # Check the type

The output result is:

example
example
<class 'str'>

Connection pool

redis-py uses a connection pool to manage all connections to a redis server, avoiding the overhead of establishing and releasing connections each time.

By default, each Redis instance maintains its own connection pool. You can directly create a connection pool and then pass it as a parameter to Redis, so that multiple Redis instances can share one connection pool.

Example

import redis    # Import redis module

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(host='localhost', port=6379, decode_responses=True)  
r.set('name', 'example')  # Set the value corresponding to name
print(r.get('name'))  # Get the value corresponding to key name

redis basic commands String

set(name, value, ex=None, px=None, nx=False, xx=False)

Set a value in Redis. By default, if it does not exist, create it; if it exists, modify it.

Parameters:

  • ex - expiration time (seconds)
  • px - expiration time (milliseconds)
  • nx - If set to True, the current set operation is executed only when name does not exist.
  • xx - If set to True, the current set operation is executed only when name exists.

1. ex - expiration time (seconds). Here the expiration time is 3 seconds. After 3 seconds, the value of key food becomes None.

Example

import redis

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
r.set('food', 'mutton', ex=3)    # The key is "food" and the value is "mutton". Store the key-value pair into redis cache.
print(r.get('food'))  # mutton. Get the value corresponding to key food.

2. px - expiration time (milliseconds). Here the expiration time is 3 milliseconds. After 3 milliseconds, the value of key foo becomes None.

Example

import redis

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
r.set('food', 'beef', px=3)
print(r.get('food'))

3. nx - If set to True, the current set operation is executed only when name does not exist (create).

Example

import redis

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
print(r.set('fruit', 'watermelon', nx=True))    # True--does not exist
# If key fruit does not exist, the output is True; if key fruit already exists, the output is None.

4. xx - If set to True, the current set operation is executed only when name exists (modify).

Example

print((r.set('fruit', 'watermelon', xx=True)))   # True--already exists
# If key fruit already exists, the output is True; if key fruit does not exist, the output is None.

5.setnx(name, value)

Set a value; execute the set operation only when name does not exist (add).

print(r.setnx('fruit1', 'banana'))  # fruit1不存在,输出为True

6.setex(name, time, value)

Set value

Parameters:

time - expiration time (numeric seconds or timedelta object)

Example

import redis
import time

pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
r.setex("fruit2", 5, "orange")
time.sleep(5)
print(r.get('fruit2'))  # After 5 seconds, the value changes from orange to None.

7.psetex(name, time_ms, value)

Set value

Parameters:

time_ms - expiration time (numeric milliseconds or timedelta object)

Example

r.psetex("fruit3", 5000, "apple")
time.sleep(5)
print(r.get('fruit3'))  # After 5000 milliseconds, the value changes from apple to None.

8.mset(*args, **kwargs)

Batch set values

For example:

Example

r.mget({'k1': 'v1', 'k2': 'v2'})
r.mset(k1="v1", k2="v2") # Here k1 and k2 cannot be quoted; set multiple key-value pairs at once.
print(r.mget("k1", "k2"))   # Get the values corresponding to multiple keys at once.
print(r.mget("k1"))

9.mget(keys, *args)

Batch get

For example:

Example

print(r.mget('k1', 'k2'))
print(r.mget(['k1', 'k2']))
print(r.mget("fruit", "fruit1", "fruit2", "k1", "k2"))  # Batch retrieve the values corresponding to the keys in the current redis cache.

10.getset(name, value)

Set a new value and get the original value

print(r.getset("food", "barbecue"))  # 设置的新值是barbecue 设置前的值是beef

11.getrange(key, start, end)

Get subsequence (get by bytes, not characters)

Parameters:

  • name - the name of Redis
  • start - start position (byte)
  • end - end position (byte)

For example: "君惜大大", 0-3 means "君"

Example

r.set("cn_name", "Junxi the Great") # Chinese characters
print(r.getrange("cn_name", 0, 2))   # Get the bytes at index 0-2, the first 3 bytes, "君", slice operation (one Chinese character takes 3 bytes, one letter takes 1 byte, each byte is 8 bits)
print(r.getrange("cn_name", 0, -1))  # Get all bytes, "Junxi Dada", slice operation
r.set("en_name","junxi") # letters
print(r.getrange("en_name", 0, 2))  # Get the bytes at index 0-2, the first 3 bytes, "jun", slice operation (one Chinese character takes 3 bytes, one letter takes 1 byte, each byte is 8 bits)
print(r.getrange("en_name", 0, -1)) # Get all bytes, "junxi", slice operation

12.setrange(name, offset, value)

Modify string content, replace starting from the specified string index (if the new value is too long, append at the end).

Parameters:

  • offset - index of the string, in bytes (one Chinese character is three bytes)
  • value - value to set

Example

r.setrange("en_name", 1, "ccc")
print(r.get("en_name"))    # jccci original value is junxi, replace starting from index 1 with ccc, becomes jccci

13.setbit(name, offset, value)

Operate on the bits of the binary representation of the value corresponding to name

Parameters:

  • name - Redis name
  • offset - index of the bit (convert the value to binary before indexing)
  • value - value can only be 1 or 0

Note: if there is a corresponding entry in Redis: n1 = "foo",

then the binary representation of string foo is: 01100110 01101111 01101111

So, if executing setbit('n1', 7, 1), then the 7th bit is set to 1,

then the final binary becomes 01100111 01101111 01101111, i.e.: "goo"

Extension, convert to binary representation:

Example

source = "Chen Siwei"
source = "foo"
for i in source:
num = ord(i)
print bin(num).replace('b','')

In particular, what if source is the Chinese characters "Chen Siwei"?

Answer: For utf-8, each Chinese character takes 3 bytes, so "Chen Siwei" has 9 bytes. For Chinese characters, when using a for loop, it will iterate by byte. During iteration, convert each byte to a decimal number, then convert the decimal number to binary. 11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 10010000

14.getbit(name, offset)

Get the value of a certain bit (0 or 1) in the binary representation of the value corresponding to name

print(r.getbit("foo1", 0)) # 0 foo1 对应的二进制 4个字节 32位 第0位是0还是1

15.bitcount(key, start=None, end=None)

Get the count of 1s in the binary representation of the value corresponding to name

Parameters:

  • key - Redis name
  • start - byte start position
  • end - byte end position

Example

print(r.get("foo"))  # goo1 01100111
print(r.bitcount("foo",0,1))  # 11 indicates the number of occurrences of 1 in the first 2 bytes

16.bitop(operation, dest, *keys)

Get multiple values, perform bitwise operations on the values, and save the final result to the value corresponding to a new name

Parameters:

  • operation - AND (and), OR (or), NOT (not), XOR (exclusive or)
  • dest - new Redis name
  • *keys - Redis names to look up

e.g.:

bitop("AND", 'new_name', 'n1', 'n2', 'n3')

Get the values corresponding to n1, n2, n3 in Redis, then perform bitwise operation on all values (find union), then save the result to the value corresponding to new_name

Example

r.set("foo","1")  # 0110001
r.set("foo1","2")  # 0110010
print(r.mget("foo","foo1"))  # ['goo1', 'baaanew']
print(r.bitop("AND","new","foo","foo1"))  # "new" 0 0110000
print(r.mget("foo","foo1","new"))

source = "12"
for i in source:
num = ord(i)
print(num)  # Print the ascii code value corresponding to each letter character or Chinese character f-102-0b100111-01100111
print(bin(num))  # Print each decimal ascii code value converted to binary value 0b1100110 (0b indicates binary)
print bin(num).replace('b','')  # Replace binary 0b1100110 with 01100110

17.strlen(name)

Return the byte length of the value corresponding to name (one Chinese character is 3 bytes)

print(r.strlen("foo"))  # 4 'goo1'的长度是4

18.incr(self, name, amount=1)

Increment the value corresponding to name. When name does not exist, create name=amount, otherwise increment.

Parameters:

  • name - Redis name
  • amount - increment value (must be an integer)

Note: same as incrby

Example

r.set("foo", 123)
print(r.mget("foo", "foo1", "foo2", "k1", "k2"))
r.incr("foo", amount=1)
print(r.mget("foo", "foo1", "foo2", "k1", "k2"))

Application scenario - page hit count

Assume we need to record click counts for a series of pages. For example, each post in a forum needs to record click count, and the click count is much larger than the reply count. If a relational database is used to store clicks, there may be a lot of row-level lock contention. Therefore, using redis's INCR command to increase the click count is the best.

When the redis server starts, the initial value of the click count can be read from the relational database (page 12306 was visited 34634 times)

r.set("visit:12306:totals", 34634)
print(r.get("visit:12306:totals"))

Whenever there is a page click, use INCR to increase the click count.

r.incr("visit:12306:totals")
r.incr("visit:12306:totals")

When the page is loaded, this value can be obtained directly

print(r.get("visit:12306:totals"))

19.incrbyfloat(self, name, amount=1.0)

Increment the value corresponding to name. When name does not exist, create name=amount, otherwise increment.

Parameters:

  • name - Redis name
  • amount - increment value (floating point)

Example

r.set("foo1", "123.0")
r.set("foo2", "221.0")
print(r.mget("foo1", "foo2"))
r.incrbyfloat("foo1", amount=2.0)
r.incrbyfloat("foo2", amount=3.0)
print(r.mget("foo1", "foo2"))

20.decr(self, name, amount=1)

Decrement the value corresponding to name. When name does not exist, create name=amount, otherwise decrement.

Parameters:

  • name - Redis name
  • amount - decrement value (integer)

Example

r.decr("foo4", amount=3) # Decrement by 3
r.decr("foo1", amount=1) # Decrement by 1
print(r.mget("foo1", "foo4"))

21.append(key, value)

Append content to the value corresponding to redis name

Parameters:

  • key - redis name
  • value - string to append

Example

r.append("name", "haha")    # Append string haha after the value junxi corresponding to name
print(r.mget("name"))

redis basic commands hash

1. Single add/update (single get) - add if not exists, modify if exists

hset(name, key, value)

Set a key-value pair in the hash corresponding to name (if not exists, create; otherwise, modify)

Parameters:

  • name - Redis name
  • key - key in the hash corresponding to name
  • value - value in the hash corresponding to name

Note: hsetnx(name, key, value) creates when the current key does not exist in the hash corresponding to name (equivalent to adding)

Example

import redis
import time

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

r.hset("hash1", "k1", "v1")
r.hset("hash1", "k2", "v2")
print(r.hkeys("hash1")) # Get all keys in the hash
print(r.hget("hash1", "k1"))    # Get the value corresponding to the key of the hash individually
print(r.hmget("hash1", "k1", "k2")) # Get the values corresponding to multiple keys of the hash
r.hsetnx("hash1", "k2", "v3") # Can only create new ones
print(r.hget("hash1", "k2"))

2. Batch add (get)

hmset(name, mapping)

Batch set key-value pairs in the hash corresponding to name

Parameters:

  • name - Redis name
  • mapping - dictionary, such as: {'k1':'v1', 'k2': 'v2'}

e.g.:

Example

r.hmset("hash2", {"k2": "v2", "k3": "v3"})
hget(name,key)

In the hash corresponding to name, get the value according to the key

hmget(name, keys, *args)

In the hash corresponding to name, get the values of multiple keys

Parameters:

  • name - name corresponding to redis
  • keys - key collection to get, e.g.: ['k1', 'k2', 'k3']
  • *args - keys to get, e.g.: k1,k2,k3

e.g.:

Example

print(r.hget("hash2", "k2"))  # Get the value corresponding to key-k2 of "hash2" individually
print(r.hmget("hash2", "k2", "k3"))  # Batch get the values corresponding to key-k2 k3 of "hash2" -- method 1
print(r.hmget("hash2", ["k2", "k3"]))  # Batch get the values corresponding to key-k2 k3 of "hash2" -- method 2

3. Get all key-value pairs

hgetall(name)

Get all key-values of the hash corresponding to name

print(r.hgetall("hash1"))

4. Get the format of all key-value pairs, hash length

hlen(name)

Get the number of key-value pairs in the hash corresponding to name

print(r.hlen("hash1"))

5. Get all keys (similar to getting all keys of a dictionary)

hkeys(name)

Get the values of all keys in the hash corresponding to name

print(r.hkeys("hash1"))

6. Get all values (similar to getting all values of a dictionary)

hvals(name)

Get all values in the hash corresponding to name

print(r.hvals("hash1"))

7. Check whether a member exists (similar to 'in' of a dictionary)

hexists(name, key)

Check whether the current key passed in exists in the hash corresponding to name

Example

print(r.hexists("hash1", "k4"))  # False: does not exist
print(r.hexists("hash1", "k1"))  # True: exists

8. Delete key-value pair

hdel(name,*keys)

Delete the key-value pair of the specified key in the hash corresponding to name

Example

print(r.hgetall("hash1"))
r.hset("hash1", "k2", "v222")   # Modify existing key k2
r.hset("hash1", "k11", "v1")   # Add new key-value pair k11
r.hdel("hash1", "k1")    # Delete one key-value pair
print(r.hgetall("hash1"))

9. Increment/decrement integer (for the value corresponding to key, integer, increment by 1 or 2, or another integer; negative means decrement)

hincrby(name, key, amount=1)

Increment the value of the specified key in the hash corresponding to name; if it does not exist, create key=amount

Parameters:

  • name - name in redis
  • key - key corresponding to the hash
  • amount - auto-increment number (integer)

Example

r.hset("hash1", "k3", 123)
r.hincrby("hash1", "k3", amount=-1)
print(r.hgetall("hash1"))
r.hincrby("hash1", "k4", amount=1)  # If it doesn't exist, value defaults to 1
print(r.hgetall("hash1"))

10. Increment/decrement float (for the value corresponding to key, float, increment by 1.0 or 2.0, or another float; negative means decrement)

hincrbyfloat(name, key, amount=1.0)

Increment the value of the specified key in the hash corresponding to name; if it doesn't exist, create key=amount

Parameters:

  • name - the name in redis
  • key - the key corresponding to the hash
  • amount, auto-increment number (float)

Increment the value of the specified key in the hash corresponding to name; if it doesn't exist, create key=amount.

Example

r.hset("hash1", "k5", "1.0")
r.hincrbyfloat("hash1", "k5", amount=-1.0)    # Already exists, decrement by -1.0
print(r.hgetall("hash1"))
r.hincrbyfloat("hash1", "k6", amount=-1.0)    # Doesn't exist, value initializes to -1.0, decrement by 1.0 each time
print(r.hgetall("hash1"))

11. Get value - slice read

hscan(name, cursor=0, match=None, count=None)

Incremental iterative fetching is very useful for large data. hscan can fetch data in shards, rather than fetching all data at once, thus preventing memory from being exhausted.

Parameters:

  • name - the name in redis
  • cursor - cursor (fetch data in batches based on cursor)
  • match - match the specified key, default None means all keys
  • count - minimum number fetched per shard, default None means use Redis's default shard count

For example:

第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None)
第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None)
...

Until the returned cursor value is 0, it means all data has been fetched via sharding

print(r.hscan("hash1"))

12、hscan_iter(name, match=None, count=None)

Use yield to wrap hscan to create a generator, enabling batch fetching of data from redis

Parameters:

  • match - match the specified key, default None means all keys
  • count - minimum number fetched per shard, default None means use Redis's default shard count

For example:

Example

for item in r.hscan_iter('hash1'):
    print(item)
print(r.hscan_iter("hash1"))    # Generator memory address

5. redis basic commands list

1. Add (similar to list append, but here it adds from the left) -- creates a new one if it doesn't exist

lpush(name,values)

Add an element to the list corresponding to name; each new element is added to the far left of the list

For example:

Example

import redis
import time

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

r.lpush("list1", 11, 22, 33)
print(r.lrange('list1', 0, -1))

The order saved is: 33, 22, 11

Extension:

r.rpush("list2", 11, 22, 33)  # 表示从右向左操作
print(r.llen("list2"))  # 列表长度
print(r.lrange("list2", 0, 3))  # 切片取出值,范围是索引号0-3

2. Add (add from the right) -- creates a new one if it doesn't exist

Example

r.rpush("list2", 44, 55, 66)    # Add 44, 55, 66 to the right of the list in order
print(r.llen("list2"))  # List length
print(r.lrange("list2", 0, -1)) # Slice to get values, range is index 0 to -1 (the last element)

3. Add an element to the left of the list for an existing name; if it doesn't exist, it cannot be created

lpushx(name,value)

Add an element to the list corresponding to name; only when name already exists is the value added to the far left of the list

More:

Example

r.lpushx("list10", 10)   # Here "list10" does not exist
print(r.llen("list10"))  # 0
print(r.lrange("list10", 0, -1))  # []
r.lpushx("list2", 77)   # Here "list2" already existed before, add an element to the far left of the list, only one at a time
print(r.llen("list2"))  # List length
print(r.lrange("list2", 0, -1)) # Slice to get values, range is index 0 to -1 (the last element

4. Add an element to the right of the list for an existing name; if it doesn't exist, it cannot be created

Example

r.rpushx("list2", 99)   # Here "foo_list1" already existed before, add an element to the far right of the list, only one at a time
print(r.llen("list2"))  # List length
print(r.lrange("list2", 0, -1)) # Slice to get values, range is index 0 to -1 (the last element)

5. Add (insert element at a fixed index position)

linsert(name, where, refvalue, value))

Insert a new value before or after a certain value in the list corresponding to name

Parameters:

  • name - the name in redis
  • where - BEFORE or AFTER
  • refvalue - benchmark value, i.e., insert data before or after it
  • value - data to insert

Example

r.linsert("list2", "before", "11", "00")   # Insert element "00" before the first occurrence of "11" from the left in the list
print(r.lrange("list2", 0, -1))   # Slice to get values, range is index 0 - last element

6. Modify (modify by specifying the index)

r.lset(name, index, value)

Reassign a value at a certain index position in the list corresponding to name

Parameters:

  • name - the name in redis
  • index - index position in the list
  • value - value to set

Example

r.lset("list2", 0, -11)    # Change the element with index 0 to -11
print(r.lrange("list2", 0, -1))

7. Delete (delete by specified value)

r.lrem(name, value, num)

Delete the specified value in the list corresponding to name

Parameters:

  • name - the name in redis
  • value - value to delete
  • num - num=0, delete all specified values in the list;
  • num=2 - delete 2 from front to back; num=1, delete the first from the left from front to back
  • num=-2 - delete 2 from back to front

Example

r.lrem("list2", "11", 1)    # Delete the first occurrence of "11" from the left in the list
print(r.lrange("list2", 0, -1))
r.lrem("list2", "99", -1)    # Delete the first occurrence of "99" from the right in the list
print(r.lrange("list2", 0, -1))
r.lrem("list2", "22", 0)    # Delete all "22" in the list
print(r.lrange("list2", 0, -1))

8. Delete and return

lpop(name)

Get the first element from the left side of the list corresponding to name and remove it from the list; the return value is the first element

More:

rpop(name) means operating from right to left

Example

r.lpop("list2")    # Delete the leftmost element of the list and return the deleted element
print(r.lrange("list2", 0, -1))
r.rpop("list2")    # Delete the rightmost element of the list and return the deleted element
print(r.lrange("list2", 0, -1))

9. Delete values outside the index range

ltrim(name, start, end)

In the list corresponding to name, remove values that are not between the start-end indices

Parameters:

  • name - the name in redis
  • start - starting index position
  • end - ending index position

Example

r.ltrim("list2", 0, 2)    # Delete elements outside index 0-2, keep elements with indices 0-2
print(r.lrange("list2", 0, -1))

10. Get value (get value by index)

lindex(name, index)

Get the list element by index in the list corresponding to name

print(r.lindex("list2", 0))  # 取出索引号是0的值

11. Move an element from one list to another list

rpoplpush(src, dst)

Take the rightmost element from one list and add it to the far left of another list

Parameters:

  • src - the name of the list from which to take data
  • dst - the name of the list to which data is to be added
r.rpoplpush("list1", "list2")
print(r.lrange("list2", 0, -1))

12. Move an element from one list to another list, with timeout support

brpoplpush(src, dst, timeout=0)

Remove an element from the right side of one list and add it to the left side of another list

Parameters:

  • src - the name of the list from which to take and remove the element
  • dst - the name of the list into which to insert the element
  • timeout - when there is no data in the list corresponding to src, the timeout (seconds) for blocking until data is available; 0 means block forever

Example

r.brpoplpush("list1", "list2", timeout=2)
print(r.lrange("list2", 0, -1))

13. Remove from multiple lists at once

blpop(keys, timeout)

Arrange multiple lists and pop elements from the corresponding lists from left to right

Parameters:

  • keys - a collection of redis names
  • timeout - timeout period; after fetching elements from all lists, the time (seconds) to block waiting for data in the list; 0 means block forever

More:

r.brpop(keys, timeout)Same as blpop, arrange multiple lists and remove elements from each list from right to left

Example

r.lpush("list10", 3, 4, 5)
r.lpush("list11", 3, 4, 5)
while True:
    r.blpop(["list10", "list11"], timeout=2)
    print(r.lrange("list10", 0, -1), r.lrange("list11", 0, -1))

14. Custom incremental iteration

Since the redis library does not provide incremental iteration for list elements, if you want to loop over all elements of the list corresponding to name, you need to get the entire list corresponding to name.

Loop through the list

However, if the list is very large, it may exhaust the program's memory in the first step, so it is necessary to define a custom incremental iteration function:

Example

def list_iter(name):
    """
Custom redis list incremental iteration
:param name: the name in redis, i.e., iterate the list corresponding to name
:return: yield returns list elements
    """

    list_count = r.llen(name)
    for index in range(list_count):
        yield r.lindex(name, index)

# Usage
for item in list_iter('list2'): # Traverse this list
    print(item)

6. redis basic commands set

1. Add

sadd(name,values)

name - add elements to the corresponding set

Example

r.sadd("set1", 33, 44, 55, 66)  # Add elements to the set
print(r.scard("set1"))  # The length of the set is 4
print(r.smembers("set1"))   # Get all members in the set

2. Get the number of elements, similar to len

scard(name)

Get the number of elements in the set corresponding to name

print(r.scard("set1"))  # 集合的长度是4

3. Get all members in the set

smembers(name)

Get all members of the set corresponding to name

print(r.smembers("set1"))   # 获取集合中所有的成员

Get all members in the set - in tuple form

sscan(name, cursor=0, match=None, count=None)

Example:

print(r.sscan("set1"))

Get all members in the set - iterator method

sscan_iter(name, match=None, count=None)

Similar to string operations, used for incremental iteration to fetch elements in batches, avoiding excessive memory consumption

for i in r.sscan_iter("set1"):
    print(i)

4. Difference

sdiff(keys, *args)

The set of elements that are in the set corresponding to the first name but not in the sets corresponding to other names

Example

r.sadd("set2", 11, 22, 33)
print(r.smembers("set1"))   # Get all members in the set
print(r.smembers("set2"))
print(r.sdiff("set1", "set2"))   # In set1 but not in set2
print(r.sdiff("set2", "set1"))   # In set2 but not in set1

5. Difference - store the difference in a new set

sdiffstore(dest, keys, *args)

Get elements in the set corresponding to the first name but not in sets corresponding to other names, then add them to the set corresponding to dest

Example

r.sdiffstore("set3", "set1", "set2")    # In set1 but not in set2
print(r.smembers("set3"))   # Get all members in set3

6. Intersection

sinter(keys, *args)

Get the intersection of sets corresponding to multiple names

print(r.sinter("set1", "set2")) # 取2个集合的交集

7. Intersection - store the intersection in a new set

sinterstore(dest, keys, *args)

Get the union of sets corresponding to multiple names, then add it to the set corresponding to dest

print(r.sinterstore("set3", "set1", "set2")) # 取2个集合的交集
print(r.smembers("set3"))

Union

sunion(keys, *args)

Get the union of sets corresponding to multiple names

print(r.sunion("set1", "set2")) # 取2个集合的并集

Union - store the union in a new set

sunionstore(dest,keys, *args)

Get the union of sets corresponding to multiple names, and save the result to the set corresponding to dest

print(r.sunionstore("set3", "set1", "set2")) # 取2个集合的并集
print(r.smembers("set3"))

8. Check whether it is a member of the set, similar to "in"

sismember(name, value)

Check whether value is a member of the set corresponding to name; the result is True or False

print(r.sismember("set1", 33))  # 33是集合的成员
print(r.sismember("set1", 23))  # 23不是集合的成员

9. Move

smove(src, dst, value)

Move a member from one set to another set

r.smove("set1", "set2", 44)
print(r.smembers("set1"))
print(r.smembers("set2"))

10. Delete - randomly delete and return the deleted value

spop(name)

Remove a member from the set and return it. Note: the set is unordered, so it is randomly deleted.

print(r.spop("set2"))   # 这个删除的值是随机删除的,集合是无序的
print(r.smembers("set2"))

11. Delete - delete by specified value

srem(name, values)

Delete certain values from the set corresponding to name

print(r.srem("set2", 11))   # 从集合中删除指定值 11
print(r.smembers("set2"))

7. redis basic commands ordered set

Set operations: A Set is a list that does not allow duplicates, and is inherently unordered.

Ordered set: based on a set, each element is sorted; sorting requires comparison based on another value. Therefore, for an ordered set, each element has two values: value and score. The score is specifically used for sorting.

1. Add

zadd(name, *args, **kwargs)

Add elements to the ordered set corresponding to name

For example:

Example

import redis
import time

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

r.zadd("zset1", n1=11, n2=22)
r.zadd("zset2", 'm1', 22, 'm2', 44)
print(r.zcard("zset1")) # Set length
print(r.zcard("zset2")) # Set length
print(r.zrange("zset1", 0, -1))   # Get all elements in the ordered set
print(r.zrange("zset2", 0, -1, withscores=True))   # Get all elements and scores in the ordered set

2. Get the number of elements in the ordered set, similar to len

zcard(name)

Get the number of elements in the ordered set corresponding to name

print(r.zcard("zset1")) # 集合长度

3. Get all elements of the ordered set

r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)

Get elements of the ordered set corresponding to name by index range

Parameters:

  • name - the name in redis
  • start - starting position of the ordered set index (not score)
  • end - ending position of the ordered set index (not score)
  • desc - sorting rule, default sorted by score from low to high
  • withscores - whether to get the element's score; by default only the element's value is fetched
  • score_cast_func - function for data conversion of the score

3-1 Sort in descending order (same as zrange, the set is sorted in descending order)

zrevrange(name, start, end, withscores=False, score_cast_func=float)

Example

print(r.zrevrange("zset1", 0, -1))    # 只获取元素,不显示分数
print(r.zrevrange("zset1", 0, -1, withscores=True)) # 获取有序集合中所有元素和分数,分数倒序

3-2 Get elements of the ordered set corresponding to name by score range

zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)

Example

Example

for i in range(1, 30):
   element = 'n' + str(i)
   r.zadd("zset3", element, i)
print(r.zrangebyscore("zset3", 15, 25)) # # Fetch elements that meet the condition with scores between 15-25
print(r.zrangebyscore("zset3", 12, 22, withscores=True))    # Fetch elements that meet the condition with scores between 12-22 (with scores)

3-3 Get elements of the ordered set by score range and sort them (default descending)

zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)

Example

print(r.zrevrangebyscore("zset3", 22, 11, withscores=True)) # 在分数是22-11之间,取出符合条件的元素 按照
Scores in reverse order

3-4 Get all elements - sorted by score order by default

zscan(name, cursor=0, match=None, count=None, score_cast_func=float)

Example

print(r.zscan("zset3"))

3-5 Get all elements - iterator

zscan_iter(name, match=None, count=None,score_cast_func=float)

Example

for i in r.zscan_iter("zset3"): # 遍历迭代器
    print(i)

4.zcount(name, min, max)

Get the count of scores in the ordered set corresponding to name that are between [min, max]

print(r.zrange("zset3", 0, -1, withscores=True))
print(r.zcount("zset3", 11, 22))

5. Increment

zincrby(name, value, amount)

Increment the score corresponding to value in the ordered set corresponding to name

r.zincrby("zset3", "n2", amount=2)    # 每次将n2的分数自增2
print(r.zrange("zset3", 0, -1, withscores=True))

6. Get the index of a value

zrank(name, value)

Get the index of a certain value in the ordered set corresponding to name (starting from 0)

More:

zrevrank(name, value), sorted from largest to smallest.

Example

print(r.zrank("zset3", "n1"))   # n1's index is 0, here in score order (from small to large)
print(r.zrank("zset3", "n6"))   # n6's index is 1

print(r.zrevrank("zset3", "n1"))    # n1's index is 29, here in reverse score order (from large to small)

7. Delete - delete by specified value

zrem(name, values)

Delete members whose value is values in the ordered set corresponding to name

r.zrem("zset3", "n3")   # 删除有序集合中的元素n3 删除单个
print(r.zrange("zset3", 0, -1))

8. Delete - delete by rank range, according to index number

zremrangebyrank(name, min, max)

Delete according to rank range

r.zremrangebyrank("zset3", 0, 1)  # 删除有序集合中的索引号是0, 1的元素
print(r.zrange("zset3", 0, -1))

9. Delete - delete by score range

zremrangebyscore(name, min, max)

Delete according to score range

r.zremrangebyscore("zset3", 11, 22)   # 删除有序集合中的分数是11-22的元素
print(r.zrange("zset3", 0, -1))

10. Get the score corresponding to a value

zscore(name, value)

Get the score corresponding to value in the ordered set corresponding to name

print(r.zscore("zset3", "n27"))   # 获取元素n27对应的分数27

8. Other common operations

1. Delete

delete(*names)

Delete any data type in redis according to name (string, hash, list, set, sorted set)

r.delete("gender")  # 删除key为gender的键值对

2. Check whether a name exists

exists(name)

Check whether the name exists in redis; True if it exists, False if it does not

print(r.exists("zset1"))

3. Fuzzy matching

keys(pattern='')

Get redis names according to a pattern

More:

  • KEYS * matches all keys in the database.
  • KEYS h?llo matches hello, hallo, hxllo, etc.
  • KEYS hllo matches hllo and heeeeello, etc.
  • KEYS h[ae]llo matches hello and hallo, but not hillo
print(r.keys("foo*"))

4. Set timeout

expire(name ,time)

Set a timeout for a name in redis

r.lpush("list5", 11, 22)
r.expire("list5", time=3)
print(r.lrange("list5", 0, -1))
time.sleep(3)
print(r.lrange("list5", 0, -1))

5. Rename

rename(src, dst)

Rename a name in redis

r.lpush("list5", 11, 22)
r.rename("list5", "list5-1")

6. Get a random name

randomkey()

Get a random name from redis (without deleting)

print(r.randomkey())

7. Get type

type(name)

Get the type of the value corresponding to name

print(r.type("set1"))
print(r.type("hash2"))

8. View all elements

Example

scan(cursor=0, match=None, count=None)

print(r.hscan("hash2"))
print(r.sscan("set3"))
print(r.zscan("zset2"))
print(r.getrange("foo1", 0, -1))
print(r.lrange("list2", 0, -1))
print(r.smembers("set3"))
print(r.zrange("zset3", 0, -1))
print(r.hgetall("hash1"))

9. View all elements - iterator

Example

scan_iter(match=None, count=None)

for i in r.hscan_iter("hash1"):
    print(i)

for i in r.sscan_iter("set3"):
    print(i)

for i in r.zscan_iter("zset3"):
    print(i)

other methods

Example

print(r.get('name'))    # Query the value with key name
r.delete("gender")  # Delete the key-value pair with key gender
print(r.keys()) # Query all keys
print(r.dbsize())   # How many pieces of data the current redis contains
r.save()    # Execute the "checkpoint" operation to write data back to disk. Blocks while saving.
# r.flushdb() # Clear all data in r

Pipeline (pipeline)

By default, redis creates and disconnects a connection for each request (applying for a connection from the connection pool and returning it to the pool). If you want to specify multiple commands in one request, you can use pipeline to execute multiple commands in one request, and by default a pipeline is an atomic operation.

Pipeline is a subclass of the base class that redis provides for buffering multiple server commands in a single request. It greatly improves the functionality of executing batch commands by reducing repetitive TCP packets between the server and client.

Example

import redis
import time

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

# pipe = r.pipeline(transaction=False) # By default, commands executed in the pipeline ensure atomicity; executing pipe = r.pipeline(transaction=False) disables this feature.
# pipe = r.pipeline(transaction=True)
pipe = r.pipeline() # Create a pipeline

pipe.set('name', 'jack')
pipe.set('role', 'sb')
pipe.sadd('faz', 'baz')
pipe.incr('num')    # If num does not exist, value is 1; if it exists, value increments by 1
pipe.execute()

print(r.get("name"))
print(r.get("role"))
print(r.get("num"))

Pipeline commands can be written together, for example:

Example

pipe.set('hello', 'redis').sadd('faz', 'baz').incr('num').execute()
print(r.get("name"))
print(r.get("role"))
print(r.get("num"))

Author: Junxi丶

Link:https://www.jianshu.com/p/2639549bedc8