生产者消费者模式:
生产者消费者模式,那么必须要有一个消费者(consumer)和一个生产者(producer),设计时候需要考虑的问题:
-
生产者的速度大于消费者的速度,存储中介中只能容纳一定的数据量
-
消费者的速度大于生产者的速度
解决以上问题:加锁或者sleep或者其他方式来解决。
我们可以让消费者每次取的时候看看存储中介中是否有值,没有值的话就等待一会再取,生产者每次往存储中介中放数据的时候看一下是否快满了,如果快满了也一样睡眠一会再看是否可以放。针对消费者消费过慢的情况,我们可以在代码中开多进程和协程来解决这个问题。
解决方案一、sleep
生产者(producer)
import time import redis pool = redis.ConnectionPool(host='localhost', port=6379, db=1, decode_responses=True) r = redis.Redis(connection_pool=pool) def producer(i): length = r.llen("goods2") print(length) if length > 5000: print("长度过大睡一会") time.sleep(1) product(i) else: #生产者 r.lpush("goods2", "good1"+str(i)) print("加入一个值睡一会") # time.sleep(5) if __name__ == '__main__': # 此处表示循环10000次,往redis里面放10000次数据 for i in range(10000): product(i)
消费者(consumer)
import time import redis pool = redis.ConnectionPool(host='localhost', port=6379, db=1, decode_responses=True) r = redis.Redis(connection_pool=pool) def consumer(): length = r.llen("goods2") print(length) while length > 0: # 消费者 goods = r.lpop("goods2") print(goods) if str(goods) == "None": print("无值多等等") time.sleep(10) else: print("无值等等") time.sleep(10) consumer() if __name__ == '__main__': consumer()
如果消费者的速度跟不上生产者,会浪费大量的时间去等待。可以从多进程程或者协程去解决这个问题。
简单模板
from multiprocessing import Process import time def test(i): while True: print("我是子进程"+str(i)) time.sleep(2) if i == 1: time.sleep(10) print("我是进程" + str(i)) # print[(x,y) for x in range(10) if x%2 if x>3 for y in range(10) if y > 7 if y != 8] if __name__ == '__main__': processes = [] for i in range(3): p = Process(target=test, args=(i,)) p.start() processes.append(p) print(processes) for p in processes: p.join()
进程1和进程0,2是相对独立的, 上面的就是多进程+消费者模式的雏形 。
消费者:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- import time import redis from multiprocessing import Process, Lock # 创建连接池 pool = redis.ConnectionPool(host='localhost', port=6379, db=1, decode_responses=True) r = redis.Redis(connection_pool=pool) def consumer(lock): length = r.llen("goods2") print(length) while True: # 获取锁 1号位置 lock.acquire() if length > 0: # 3号位置 goods = r.lpop("goods2") # 获得资源释放锁 lock.release() try: data = goods print(data) if str(goods) == "None": print("无值多等等") time.sleep(2) except: print("无值等等...") time.sleep(2) consumer(lock) else: # 2号位置 print('无值等等...') time.sleep(10) consumer(lock) if __name__ == "__main__": # 创建全局锁 lock = Lock() # 进程列表 processes = [] for i in range(10): # 创建进程 p = Process(target=consumer, args=(lock,)) p.start() processes.append(p) for p in processes: p.join() print('处理完毕')
PS: 存在一个问题。就是当先启动消费者时,再启动生产者是会出现死锁的情况。修改过后的消费者如下:
def consumer(lock): while True: # 获取锁 lock.acquire() length = r.llen("goods2") print(length) if length > 0: goods = r.lpop("goods2") # 获得资源释放锁 lock.release() try: data = goods print(data) if str(goods) == "None": print("无值多等等") time.sleep(2) except: print("无值等等...") time.sleep(2) consumer(lock) else: print('无值等等...') time.sleep(10) lock.release() consumer(lock)