用python 批量操作redis数据库

方法一:使用 pipeline

  使用pipelining 发送命令时,redis server必须部分请求放到队列中(使用内存)执行完毕后一次性发送结果,在 pipeline 使用期间,将“独占”链接,无法进行非“管道”类型的其他操作,直至 pipeline 关闭;如果 pipeline 的指令集很多很庞大,为了不影响其他操作(redis 最大时间lua-time-limit默认是5s),可以使用其他新建新链接操作。批量操作如下:

import redis

r = redis.Redis(host='127.0.0.1', port=6379, password='1234567890')
with r.pipeline() as ctx:
  a = time.time()
  ctx.hset('current', "time2", a)
  ctx.hset('current', "time3", a)
  res = ctx.execute()
  print("result: ", res)

使用 pipe line 以乐观锁的形式执行事务操作

# -*- coding:utf-8 -*-

import redis
from redis import WatchError
from concurrent.futures import ProcessPoolExecutor

r = redis.Redis(host='127.0.0.1', port=6379)

# 减库存函数, 循环直到减库存完成
# 库存充足, 减库存成功, 返回True
# 库存不足, 减库存失败, 返回False
def decr_stock():
  # python中redis事务是通过pipeline的封装实现的
  with r.pipeline() as pipe:
    while True:
      try:
        # watch库存键, multi后如果该key被其他客户端改变, 事务操作会抛出WatchError异常
        pipe.watch('stock:count')
        count = int(pipe.get('stock:count'))
        if count > 0: # 有库存
          # 事务开始
          pipe.multi() # multi 判断 watch 监控的 key 是否被其他客户端改变
          pipe.decr('stock:count')
          # 把命令推送过去
          # execute返回命令执行结果列表, 这里只有一个decr返回当前值
          result = pipe.execute()[0]
          print("result: ", result)
          return True
        else:
          return False
      except WatchError as e:
        # 打印WatchError异常, 观察被watch锁住的情况
        print(e.args)
      finally:
        pipe.unwatch()

def worker():
  while True:
    # 没有库存就退出
    if not decr_stock():
      break

# 实验开始
# 设置库存为100
r.set("stock:count", 100)

# 多进程模拟多个客户端提交
with ProcessPoolExecutor(max_workers=2) as pool:
  for _ in range(10):
    pool.submit(worker)

方法二:使用 register_script

分布执行,发送脚本到redis服务器,获取一个本次连接的一个调用句柄,根据此句柄可以无数次执行不同参数调用

import redis
import time

  r = redis.Redis(host='127.0.0.1', port=31320, password='12345678')

  lua = """
  local key = KEYS[1]
  local field = ARGV[1]
  local timestamp_new = ARGV[2]

  -- get timestamp of the key in redis
  local timestamp_old = redis.call('hget', key, field)
  -- if timestamp_old == nil, it means the key is not exist
  if timestamp_old == nil or timestamp_old == false or timestamp_new > timestamp_old then
    redis.call('hset', key, field .. 1, timestamp_new)
    -- timestamp_new > timestamp_old
    return redis.pcall('hset', key, field, timestamp_new)
  end

  """

  cmd = r.register_script(lua)

  cur_time = time.time()
  cmd(keys=['current'], args=["time", cur_time])

register_script 调用 lua 来实现,需要注意 redis.call(method, key, field) 的返回值(nil,false,1),此处没有键值返回的是false。如果中间有错误,所有的语句不时不生效。

方法三:使用 script_load 和 evalsha

简而言之,通过 script_load 发送给redis服务器,使加载 lua 脚本,并常驻内存,返回标志,通过 evalsha 按标志进行执行,此连接脱离本次redis 客户端。

import redis
import time

  r = redis.Redis(host='127.0.0.1', port=31320, password='12345678')

  lua = """
  local key = KEYS[1]
  local field = ARGV[1]
  local timestamp_new = ARGV[2]

  -- get timestamp of the key in redis
  local timestamp_old = redis.call('hget', key, field)
  -- if timestamp_old == nil, it means the key is not exist
  if timestamp_old == nil or timestamp_old == false or timestamp_new > timestamp_old then
    redis.call('hset', key, field .. 1, timestamp_new)
    -- timestamp_new > timestamp_old
    return redis.pcall('hset', key, field, timestamp_new)
  end

  """
  sha = r.script_load(lua)
  print(r.evalsha(sha, 1, 'current', 'time', time.time()))

Redis 管理Lua脚本:(Python下为 script_... )

  • script load

此命令用于将Lua脚本加载到Redis内存中

  • script exists

scripts exists sha1 [sha1 …]  
此命令用于判断sha1是否已经加载到Redis内存中

  • script flush

此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,所有 sha 不复存在。

  • script kill

此命令用于杀掉正在执行的Lua脚本。

方法四:eval

使用方法与方法三类似,但是eval是一次性请求,每次请求,必须携带 lua 脚本

以上就是用python 批量操作redis数据库的详细内容,更多关于python 批量操作redis数据库的资料请关注我们其它相关文章!

(0)

相关推荐

  • python3实现将json对象存入Redis以及数据的导入导出

    Redis数据类型 String:二进制安全,可以包含任何数据 Hash:一个键值(key=>value)对集合 List:简单的字符串列表 Set:string类型的无序集合 Zset:每个元素都会关联一个double类型的分数,redis通过分数来为集合中的成员进行从小到大的排序 Redis基本命令 Key: set, get, delete Hash: hmset, hget, hdel List: lpush, lindex Set: sadd,smembers Zset: zadd,

  • 基于python实现操作redis及消息队列

    操作 redis import redis redisPool = redis.ConnectionPool(host='192.168.100.50', port=6379, db=8) redis= redis.Redis(connection_pool=redisPool) redis.set('key','values') redis.get('com') redis.append('keys','values') redis.delete('keys') print(redis.get

  • python操作redis数据库的三种方法

    安装依赖 pip3 install redis 使用的三种方式 直接使用 import redis r = redis.Redis(host='127.0.0.1', port=6379, db=1, password=None, decode_responses=True) 连接池使用 import redis pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=1, max_connections=100, password

  • Python调用Redis的示例代码

    #!/usr/bin/env python # -*- coding:utf-8 -*- # ************************************* # @Time : 2019/8/12 # @Author : Zhang Fan # @Desc : Library # @File : MyRedis.py # @Update : 2019/8/23 # ************************************* import redis class MyR

  • Redis分布式锁python-redis-lock使用方法

    python-redis-lock 多个redis客户端访问同一个redis服务端,控制并发. github:https://pypi.org/project/python-redis-lock/ 在使用这个库之前,需要安装如下: pip install python-redis-lock 使用锁的示例: lock = redis_lock.Lock(conn, "name-of-the-lock") if lock.acquire(blocking=False): print(&qu

  • Python定时从Mysql提取数据存入Redis的实现

    设计思路: 1.程序一旦run起来,python会把mysql中最近一段时间的数据全部提取出来 2.然后实例化redis类,将数据简单解析后逐条传入redis队列 3.定时器设计每天凌晨12点开始跑 ps:redis是个内存数据库,做后台消息队列的缓存时有很大的用处,有兴趣的小伙伴可以去查看相关的文档. # -*- coding:utf-8 -*- import MySQLdb import schedule import time import datetime import random i

  • Python安装并操作redis实现流程详解

    Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hash(哈希类型).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性

  • Python3爬虫RedisDump的安装步骤

    在python3爬虫中如何我们想要导入/导出Redis数据,就要安装使用RedisDump.RedisDump是一个用于Redis数据导入/导出的工具,可以将redis数据库中的各个slot中的数据导出到文本中,方便迁移备份数据:是基于Ruby实现的,所以要安装RedisDump,需要先安装Ruby. 1.相关链接 GitHub:https://github.com/delano/redis-dump 官方文档:http://delanotes.com/redis-dump 2.安装Ruby #

  • Python+redis通过限流保护高并发系统

    保护高并发系统的三大利器:缓存.降级和限流.那什么是限流呢?用我没读过太多书的话来讲,限流就是限制流量.我们都知道服务器的处理能力是有上限的,如果超过了上限继续放任请求进来的话,可能会发生不可控的后果.而通过限流,在请求数量超出阈值的时候就排队等待甚至拒绝服务,就可以使系统在扛不住过高并发的情况下做到有损服务而不是不服务. 举个例子,如各地都出现口罩紧缺的情况,广州政府为了缓解市民买不到口罩的状况,上线了预约服务,只有预约到的市民才能到指定的药店购买少量口罩.这就是生活中限流的情况,说这个也是希

  • python如何基于redis实现ip代理池

    这篇文章主要介绍了python如何基于redis实现ip代理池,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用apscheduler库定时爬取ip,定时检测ip删除ip,做了2层检测,第一层爬取后放入redis--db0进行检测,成功的放入redis--db1再次进行检测,确保获取的代理ip的可用性 import requests, redis import pandas import random from apscheduler.sch

随机推荐