Memcached

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。

它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。

Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,

并通过memcached协议与守护进程通信。

一、Memcached安装和基本使用 

1、 Memcached安装

  1. wget http://memcached.org/latest
  2. tar -zxvf memcached-1.x.x.tar.gz
  3. cd memcached-1.x.x
  4. ./configure && make && make test && sudo make install
  5.  
  6. PS:依赖libevent
  7. yum install libevent-devel
  8. apt-get install libevent-dev

2、 启动Memcached

  1. memcached -d -m 10 -u root -l 192.168.100.90 -p 12000 -c 256 -P /tmp/memcached.pid
  2.  
  3. 参数说明:
  4. -d 是启动一个守护进程
  5. -m 是分配给Memcache使用的内存数量,单位是MB
  6. -u 是运行Memcache的用户
  7. -l 是监听的服务器IP地址
  8. -p 是设置Memcache监听的端口,最好是1024以上的端口
  9. -c 选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定
  10. -P 是设置保存Memcachepid文件

3、 Memcached命令

  1. 存储命令: set/add/replace/append/prepend/cas
  2. 获取命令: get/gets
  3. 其他命令: delete/stats..

二、Python操作Memcached

安装API

  1. python操作Memcached使用Python-memcached模块
  2. 下载安装:https://pypi.python.org/pypi/python-memcached

1、第一次操作

  1. import memcache
  2.  
  3. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  4. mc.set("foo", "bar")
  5. ret = mc.get('foo')
  6. print ret

PS:debug = True 表示运行出现错误时,现实错误信息,上线后移除该参数

2、天生支持集群

python-memcached模块原生支持集群操作,其原理是在内存维护一个主机列表,且集群中主机的权重值和主机在列表中重复出现的次数成正比

  1. 主机 权重
  2. 1.1.1.1 1
  3. 1.1.1.2 2
  4. 1.1.1.3 1
  5.  
  6. 那么在内存中主机列表为:
  7. host_list = ["1.1.1.1", "1.1.1.2", "1.1.1.2", "1.1.1.3", ]

如果用户根据如果要在内存中创建一个键值对(如:k1 = "v1"),那么要执行一下步骤:

  • 根据算法将 k1 转换成一个数字
  • 将数字和主机列表长度求余数,得到一个值 N( 0 <= N < 列表长度 )
  • 在主机列表中根据 第2步得到的值为索引获取主机,例如:host_list[N]
  • 连接 将第3步中获取的主机,将 k1 = "v1" 放置在该服务器的内存中

代码实现如下:

  1. mc = memcache.Client([('1.1.1.1:12000', 1), ('1.1.1.2:12000', 2), ('1.1.1.3:12000', 1)], debug=True)
  2.  
  3. mc.set('k1', 'v1')

3、add
添加一条键值对,如果已经存在的 key,重复执行add操作异常

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6. mc.add('k1', 'v1')
  7. # mc.add('k1', 'v2') # 报错,对已经存在的key重复添加,失败!!!

4、replace
replace 修改某个key的值,如果key不存在,则异常

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6. # 如果memcache中存在kkkk,则替换成功,否则一场
  7. mc.replace('kkkk','999')

5、set 和 set_multi

set            设置一个键值对,如果key不存在,则创建,如果key存在,则修改

set_multi   设置多个键值对,如果key不存在,则创建,如果key存在,则修改

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6.  
  7. mc.set('key0', 'linda')
  8.  
  9. mc.set_multi({'key1': 'val1', 'key2': 'val2'})

6、delete 和 delete_multi

delete             在Memcached中删除指定的一个键值对

delete_multi    在Memcached中删除指定的多个键值对

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6.  
  7. mc.delete('key0')
  8. mc.delete_multi(['key1', 'key2'])

7、get 和 get_multi

get            获取一个键值对

get_multi   获取多一个键值对

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6.  
  7. val = mc.get('key0')
  8. item_dict = mc.get_multi(["key1", "key2", "key3"]) 

8、append 和 prepend

append    修改指定key的值,在该值 后面 追加内容

prepend   修改指定key的值,在该值 前面 插入内容

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6. # k1 = "v1"
  7.  
  8. mc.append('k1', 'after')
  9. # k1 = "v1after"
  10.  
  11. mc.prepend('k1', 'before')
  12. # k1 = "beforev1after" 

9、decr 和 incr  

incr  自增,将Memcached中的某一个值增加 N ( N默认为1 )

decr 自减,将Memcached中的某一个值减少 N ( N默认为1 )

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4.  
  5. mc = memcache.Client(['192.168.100.90:12000'], debug=True)
  6. mc.set('k1', '777')
  7.  
  8. mc.incr('k1')
  9. # k1 = 778
  10.  
  11. mc.incr('k1', 10)
  12. # k1 = 788
  13.  
  14. mc.decr('k1')
  15. # k1 = 787
  16.  
  17. mc.decr('k1', 10)
  18. # k1 = 777

10、gets 和 cas

如商城商品剩余个数,假设改值保存在memcache中,product_count = 900

A用户刷新页面从memcache中读取到product_count = 900

B用户刷新页面从memcache中读取到product_count = 900

如果A、B用户均购买商品

A用户修改商品剩余个数 product_count=899

B用户修改商品剩余个数 product_count=899

如此一来缓存内的数据便不在正确,两个用户购买商品后,商品剩余还是 899

如果使用python的set和get来操作以上过程,那么程序就会如上述所示情况!

如果想要避免此情况的发生,只要使用 gets 和 cas 即可,如:

  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. import memcache
  4. mc = memcache.Client(['192.168.100.90:12000'], debug=True, cache_cas=True)
  5.  
  6. v = mc.gets('product_count')
  7. # ...
  8. # 如果有人在gets之后和cas之前修改了product_count,那么,下面的设置将会执行失败,剖出异常,从而避免非正常数据的产生
  9. mc.cas('product_count', "899")

PS:本质上每次执行gets时,会从memcache中获取一个自增的数字,通过cas去修改gets的值时,

会携带之前获取的自增值和memcache中的自增值进行比较,如果相等,则可以提交,如果不想等,那表示在gets和cas执行之间,

又有其他人执行了gets(获取了缓冲的指定值), 如此一来有可能出现非正常数据,则不允许修改。

 Redis

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、

zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,

而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。

区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

一、Redis 安装和基本使用

  1. wget http://download.redis.io/releases/redis-3.2.8.tar.gz
  2. tar -zxvf redis-3.2.8.tar.gz
  3. cd redis-3.2.8.tar.gz
  4. make

启动服务端

  1. src/redis-server

服务端远程配置

启动客户端

  1. src/redis-cli
  2. redis> set foo bar
  3. OK
  4. redis> get foo
  5. "bar"

 二、Python操作Redis

  1. sudo pip install redis
  2. or
  3. sudo easy_install redis
  4. or
  5. 源码安装 详见 https://github.com/WoLpH/redis-py

API使用

redis-py 的API的使用可以分类为:

  • 连接方式
  • 连接池
  • 操作管道
    • String 操作
    • Hash 操作
    • List 操作
    • Set 操作
    • Sort Set 操作
  • 管道
  • 发布订阅
RabbitMQ

RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。

应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。

消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,

直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

一、RabbitMQ安装

  1. 安装配置epel
  2. $ rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
  3.  
  4. 安装erlang
  5. $ yum -y install erlang
  6.  
  7. 错误信息: Cannot retrieve metalink for repository: epel. Please verify its path and try again 需要更新 更新CA证书
  8. $ yum --disablerepo=epel -y update ca-certificates
  9.  
  10. 安装RabbitMQ
  11. $ yum -y install rabbitmq-server

注意:

1. service rabbitmq-server start/stop

2. rabbitmq会在启动前会解析主机名的地址是否可通,注意修改hostname保持一致

二、安装API

  1. pip install pika
  2. or
  3. easy_install pika
  4. or
  5. 源码https://pypi.python.org/pypi/pika

使用API操作RabbitMQ 

基于Queue实现生产者消费者模型

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import Queue
  4. import threading
  5.  
  6. message = Queue.Queue(10)
  7.  
  8. def producer(i):
  9. while True:
  10. message.put(i)
  11.  
  12. def consumer(i):
  13. while True:
  14. msg = message.get()
  15.  
  16. for i in range(12):
  17. t = threading.Thread(target=producer, args=(i,))
  18. t.start()
  19.  
  20. for i in range(10):
  21. t = threading.Thread(target=consumer, args=(i,))
  22. t.start()

代码预览

对于RabbitMQ来说,生产和消费不再针对内存里的一个Queue对象,而是某台服务器上的RabbitMQ Server实现的消息队列。

  1. #!/usr/bin/env python
  2. import pika
  3.  
  4. # ######################### 生产者 #########################
  5.  
  6. connection = pika.BlockingConnection(pika.ConnectionParameters(
  7. host='localhost'))
  8. channel = connection.channel()
  9.  
  10. channel.queue_declare(queue='hello')
  11.  
  12. channel.basic_publish(exchange='',
  13. routing_key='hello',
  14. body='Hello World!')
  15. print(" [x] Sent 'Hello World!'")
  16. connection.close()

  

  1. #!/usr/bin/env python
  2. import pika
  3.  
  4. # ########################## 消费者 ##########################
  5.  
  6. connection = pika.BlockingConnection(pika.ConnectionParameters(
  7. host='localhost'))
  8. channel = connection.channel()
  9.  
  10. channel.queue_declare(queue='hello')
  11.  
  12. def callback(ch, method, properties, body):
  13. print(" [x] Received %r" % body)
  14.  
  15. channel.basic_consume(callback,
  16. queue='hello',
  17. no_ack=True)
  18.  
  19. print(' [*] Waiting for messages. To exit press CTRL+C')

  

Python自动化开发 - Python操作Memcached、Redis、RabbitMQ的更多相关文章

  1. Python自动化开发 - Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy 一.pymysql pymsql是Python中操作MySQL的模块,其使用方法和mysq ...

  2. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  3. python自动化开发学习 I/O多路复用

    python自动化开发学习 I/O多路复用   一. 简介 socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信.IO多路复用的系统消耗很小. IO多路复用底层就是监听so ...

  4. Python下操作Memcache/Redis/RabbitMQ说明

    一.MemcacheMemcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要频繁访 ...

  5. Python自动化开发 - 装饰器

    本节内容 一.装饰器导引 1.函数对象特性 2.扩展业务功能需求 3.各种解决方案 二.装饰器解析 1.装饰器基本概念 2.无参装饰器解析 一.装饰器导引 1.函数对象特性 #### 第一波 #### ...

  6. Appium+python自动化8-Appium Python API

    Appium+python自动化8-AppiumPython API   前言: Appium Python API全集,不知道哪个大神整理的,这里贴出来分享给大家. 1.contexts conte ...

  7. Python自动化开发(三):循环次数控制、常用数据类型、字符串格式化、列表常用操作、列表的后续操作

    计数器的作用可以在死循环中,符合条件的情况下做自动退出中断 #!/usr/bin/env python # _*_ coding: utf-8 _*_ # @Time : 2017/3/14 11:2 ...

  8. python自动化开发-[第三天]-编码,函数,文件操作

    今日概要 - 编码详解 - 文件操作 - 初识函数 一.字符编码 1.代码执行过程 代码-->解释器翻译-->机器码-->执行 2.ASCII ASCII:一个Bytes代表一个字符 ...

  9. Python自动化开发 - 字符串, 列表, 元组, 字典和和文件操作

    一.字符串 特性:字符串本身不可修改,除非字符串变量重新赋值.Python3中所有字符串都是Unicode字符串,支持中文. >>> name  = "Jonathan&q ...

随机推荐

  1. leetcode406

    public class Solution { public int[,] ReconstructQueue(int[,] people) { ) { return new int[,] { }; } ...

  2. python_09 文件处理流程,文件操作方法

    文件处理流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 f=open('test.txt',encoding='gbk') data = f.read() ...

  3. Eclipse 中Git的使用及如何解决冲突

    1. 如何导入已有Git项目 1.1 File——>import… 出现以下界面 1.2 找到Git,然后双击‘Project from Git.或者点击next 1.3 双击Clone URI ...

  4. 笔记:MYSQL四种事务隔离级。

    1·未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 脏读: 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库 ...

  5. cdnbest自定义错误显示节点名教程

    在自定义错误里选择js选项,输入: document.write("error!" + hostname); 这是最简单的写法,只显示节点名,如果要显示其他效果,可自已修改js

  6. Java学习笔记(二十一):类型转换和instanceof关键字

    基本数据类型转换: 自动类型转换:把大类型的数据赋值给大类型的变量(此时的大小指的是容量的范围) byte b = 12; //byte是一个字节 int i = b; //int是四个字节 强制类型 ...

  7. 2. Go变量(Variables)

    变量是什么,变量的命名规则,以及一些关于变量的基础没有必要再说了,我想学习Go语言的有很多都是从其他语言转过来的,那我们直接进入正题. 声明一个变量: var age int 给变量赋值: age = ...

  8. POJ-3268.SilverCowParty.(最短路 + 图的转置)

    本题思路:对原图和原图的逆图分别用一次最短路,找出最大值即可. 一开始是我是对每个顶点spfa搜了一波,结果判题时间巨长,还好这个题的数据量不是很大,所以就用了另一种思路. 参考代码:spfa单结点爆 ...

  9. 华为NB-IOT报告

    转 https://blog.csdn.net/np4rHI455vg29y2/article/details/78958137 [NB-IoT]华为NB-IoT网络报告(完整版) 2018年01月0 ...

  10. python --数据可视化(一)

    python --数据可视化 一.python -- pyecharts库的使用 pyecharts--> 生成Echarts图标的类库 1.安装: pip install pyecharts ...