大纲

1.RabbitMQ

2.Redis


1.RabbitMQ消息队列

1.1 RabbitMQ简介

  AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
  AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
  RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
  下面将重点介绍RabbitMQ中的一些基础概念,了解了这些概念,是使用好RabbitMQ的基础。


1.2 安装RabbitMQ和python的pika模块

1.2.1 安装RabbitMQ

(1)安装erlang平台(RabbitMQ的依赖平台)

1.安装依赖文件
yum install ncurses-devel

2.下载源文件
wget http://www.erlang.org/download/otp_src_19.1.tar.gz
若失败,到地址:http://erlang.org/download/去手动下载

3.解压源文件压缩包
tar -xvf otp_src_19.1.tar.gz
(tar 参数含义: bz2格式用j;gz格式用z;c是创建;x是解压缩;v是详细信息;f是指定文件)

4.进入解压后的目录
cd otp_src_19.1

5.依次执行以下命令:
./configure -prefix=/usr/local/erlang 就会开始编译安装 会编译到 /usr/local/erlang 下
make && make install

6.修改/etc/profile文件,增加下面的环境变量:
vim /etc/pofile
#set erlang environment
export PATH=$PATH:/usr/local/erlang/bin
source profile使得文件生效(用export 查看path中是否有刚刚添加的环境变量)

7.安装完成后执行erl看是否能打开eshell,用’halt().’退出,注意:“.”是erlang的结束符

(2)安装RabbitMQ

wget -c http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.0/rabbitmq-server-3.6.0-1.noarch.rpm

rpm -ivh --nodeps rabbitmq-server-3.6.0-1.noarch.rpm

1.2.2 安装pika

pip install pika 或者easy_install pika


1.3 最简单的发送/接收消息队列模型

producer:

 #! /usr/bin/env python3
# -*- coding:utf-8 -*- import pika connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost')) # 相当于建立一个socket连接
channel = connection.channel()
# 声明queue
channel.queue_declare(queue='hello')
# RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='hello',
body='你好!'.encode("utf-8"))
print(" 发送 '你好!'")
connection.close()

consumer:

 #! /usr/bin/env python3
# -*- coding:utf-8 -*-
import pika connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost'))
channel = connection.channel() # You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
channel.queue_declare(queue='hello') def callback(ch, method, properties, body):
print(" 收到: %r" % body.decode("utf-8")) channel.basic_consume(callback,
queue='hello',
no_ack=True)
print(' 等待。。。')
channel.start_consuming()

注意代码中的英文注释,特别是为什么又一次声明queue。。。


1.4 轮询原理

  1.3中如果依次运行两个consumer,分别记consumer1、consumer2,那么producer第一次发消息是consumer1收到,第二次发是consumer2收到,第三次发又是consumer1收到......也就是说,rabbitMQ是依次把消息发给consumer端。


1.5 消息持久化

producer

 #! /usr/bin/env python3
# -*- coding:utf-8 -*-
import pika connection = pika.BlockingConnection(pika.ConnectionParameters("localhost")) # 相当于建立一个socket连接
channel = connection.channel() # 定义一个管道
# 声明Queue
channel.queue_declare(queue="hello2",durable=True) # durable=True 是把这个队列持久化,如果rabbitMQ挂掉,队列还在;如果
# 队列中的消息没有持久化,则消息会丢失
channel.basic_publish(exchange="",
routing_key="hello2",
body="Hi,how are you?",
properties=pika.BasicProperties(
delivery_mode=2,)) # properties=pika.BasicProperties(delivery_mode=2,) 这是队列中的消息持久化
print("发送了一句话。。。")
connection.close()

  上述代码中,第8行只是队列持久化,如果rabbitMQ挂掉,队列还在;但如果队列中的消息没有持久化,则消息会丢失。


1.6 消息公平分发

  如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置perfetch=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。

producer:

 import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.queue_declare(queue='task_queue', durable=True) message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # make message persistent
))
print(" [x] Sent %r" % message)
connection.close()

生产者端其实并没什么变化,只是用了消息持久化。

consumer:

 import pika
import time connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.queue_declare(queue='task_queue', durable=True)
print(' [*] Waiting for messages. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
time.sleep(body.count(b'.'))
print(" [x] Done")
15 ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback,
queue='task_queue') channel.start_consuming()

注意15行,必须要手动回复。


1.7 消息发布/订阅(Publish/Subscribe)

 之前的例子都基本都是1对1的消息发送和接收,即消息只能发送到指定的queue里,但有些时候你想让你的消息被所有的Queue收到,类似广播的效果,这时候就要用到exchange了,

An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.

Exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件,可以接收消息

fanout: 所有bind到此exchange的queue都可以接收消息
direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息
topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息

   表达式符号说明:#代表一个或多个字符,*代表任何字符
      例:#.a会匹配a.a,aa.a,aaa.a等
          *.a会匹配a.a,b.a,c.a等
     注:使用RoutingKey为#,Exchange Type为topic的时候相当于使用fanout 

headers: 通过headers 来决定把消息发给哪些queue

publisher:

 #! /usr/bin/env python3
# -*- coding:utf-8 -*- import pika connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() # 不需要声明队列,这里是交换器
channel.exchange_declare(exchange='logs',
type='fanout') # fanout的意思是广播 message = "Info: How are you???"
channel.basic_publish(exchange='logs',
routing_key='', # 没有队列,这里也必须写为空
body=message)
print(" [x] Sent %r" % message)
connection.close()

subscriber

 #! /usr/bin/env python3
# -*- coding:utf-8 -*- import pika connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='logs',
type='fanout') result = channel.queue_declare(exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除
# exclusive唯一的
queue_name = result.method.queue channel.queue_bind(exchange='logs',
queue=queue_name) # 将随机分配的队列绑定到交换机logs print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] %r" % body) channel.basic_consume(callback,
queue=queue_name,
no_ack=True) channel.start_consuming()

1.8 有选择地接收消息(exchange type = direct)

RabbitMQ还支持根据关键字发送,即:队列绑定关键字,发送者将数据根据关键字发送到消息exchange,exchange根据 关键字 判定应该将数据发送至指定队列。

publisher

 #! /usr/bin/env python3
# -*- coding:utf-8 -*- import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='direct_logs',
type='direct') severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(exchange='direct_logs',
routing_key=severity,
body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()

subscriber

 #! /usr/bin/env python3
# -*- coding:utf-8 -*- import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='direct_logs',type='direct') result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue severities = sys.argv[1:]
if not severities:
sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
sys.exit(1) for severity in severities:
channel.queue_bind(exchange='direct_logs',
queue=queue_name,
routing_key=severity) print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body)) channel.basic_consume(callback,
queue=queue_name,
no_ack=True) channel.start_consuming()

1.9 更细致的消息过滤

import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
type='topic') routing_key = sys.argv[1] if len(sys.argv) > 1 else 'anonymous.info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(exchange='topic_logs',
routing_key=routing_key,
body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.exchange_declare(exchange='topic_logs',
type='topic') result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue binding_keys = sys.argv[1:]
if not binding_keys:
sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
sys.exit(1) for binding_key in binding_keys:
channel.queue_bind(exchange='topic_logs',
queue=queue_name,
routing_key=binding_key) print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body)) channel.basic_consume(callback,
queue=queue_name,
no_ack=True) channel.start_consuming()

1.10 rpc

RPC server

 import pika
import time
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost')) channel = connection.channel() channel.queue_declare(queue='rpc_queue') def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2) def on_request(ch, method, props, body):
n = int(body) print(" [.] fib(%s)" % n)
response = fib(n) ch.basic_publish(exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(correlation_id = \
props.correlation_id),
body=str(response))
ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request, queue='rpc_queue') print(" [x] Awaiting RPC requests")
channel.start_consuming()

RPC client

 import pika
import uuid class FibonacciRpcClient(object):
def __init__(self):
self.connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost')) self.channel = self.connection.channel() result = self.channel.queue_declare(exclusive=True)
self.callback_queue = result.method.queue self.channel.basic_consume(self.on_response, no_ack=True,
queue=self.callback_queue) def on_response(self, ch, method, props, body):
if self.corr_id == props.correlation_id:
self.response = body def call(self, n):
self.response = None
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(exchange='',
routing_key='rpc_queue',
properties=pika.BasicProperties(
reply_to = self.callback_queue,
correlation_id = self.corr_id,
),
body=str(n))
while self.response is None:
self.connection.process_data_events()
return int(self.response) fibonacci_rpc = FibonacciRpcClient() print(" [x] Requesting fib(30)")
response = fibonacci_rpc.call(30)
print(" [.] Got %r" % response)

2 Redis

Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

2.1 python操作redis

2.1.1 操作模式

redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。

 import redis

 r = redis.Redis(host='10.211.55.4', port=6379)
r.set('foo', 'Bar')
print (r.get('foo'))

2.1.2 连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

import redis

pool = redis.ConnectionPool(host='10.211.55.4', port=6379)

r = redis.Redis(connection_pool=pool)
r.set('foo', 'Bar')
print(r.get('foo'))

2.1.3 String 操作

String操作,redis中的String在在内存中按照一个name对应一个value来存储。

name             value

n1 ----------->  v1

n2 ----------->  v2

n3 ----------->  v3

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

在Redis中设置值,默认,不存在则创建,存在则修改

参数:
     ex,过期时间(秒)
     px,过期时间(毫秒)
     nx,如果设置为True,则只有name不存在时,当前set操作才执行
     xx,如果设置为True,则只有name存在时,岗前set操作才执行

setnx(name, value)

设置值,只有name不存在时,执行设置操作(添加)

setex(name, value, time)

# 设置值

# 参数:

    # time,过期时间(数字秒 或 timedelta对象)
 
psetex(name, time_ms, value)
# 设置值

# 参数:
    # time_ms,过期时间(数字毫秒 或 timedelta对象)
 
mset(*args, **kwargs)
批量设置值

如:
    mset(k1='v1', k2='v2')
    
    mget({'k1''v1''k2''v2'})
 
get(name)   获取值
 
mget(keys, *args)
批量获取

如:
    mget('ylr''zingp')
    
    r.mget(['ylr''zigp'])
 
getset(name, value)  设置新值并获取原来的值
 
getrange(key, start, end)
# 获取子序列(根据字节获取,非字符)

# 参数:
    # name,Redis 的 name
    # start,起始位置(字节)
    # end,结束位置(字节)
# 如: "刘亦菲" ,0-3表示 "刘"
 
setrange(name, offset, value)
# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)

# 参数:
    # offset,字符串的索引,字节(一个汉字三个字节)
    # value,要设置的值
 
setbit(name, offset, value)
# 对name对应值的二进制表示的位进行操作

# 参数:
# name,redis的name
# offset,位的索引(将值变换成二进制后再进行索引)
# value,值只能是 1 或 0 # 注:如果在Redis中有一个对应: n1 = "foo",
那么字符串foo的二进制表示为:01100110 01101111 01101111
所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1,
那么最终二进制则变成 01100111 01101111 01101111,即:"goo" # 扩展,转换二进制表示: # source = "勒布朗"
source = "foo" for i in source:
num = ord(i)
print bin(num).replace('b','') 特别的,如果source是汉字 "勒布朗"怎么办?
答:对于utf-8,每一个汉字占 3 个字节,那么 "勒布朗" 则有 9个字节
对于汉字,for循环时候会按照 字节 迭代,那么在迭代时,将每一个字节转换 十进制数,然后再将十进制数转换成二进制
11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 10010000
-------------------------- ----------------------------- -----------------------------
勒 布 朗

getbit(name, offset)  # 获取name对应的值的二进制表示中的某位的值 (0或1)

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

# 获取name对应的值的二进制表示中 1 的个数

# 参数:
    # key,Redis的name
    # start,位起始位置
    # end,位结束位置
 
bitop(operation, dest, *keys)
# 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值

 
# 参数:
    # operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或)
    # dest, 新的Redis的name
    # *keys,要查找的Redis的name
# 如:
    bitop("AND"'new_name''n1''n2''n3')
    # 获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中
 
strlen(name)  # 返回name对应值的字节长度(一个汉字3个字节)
 
incr(self, name, amount=1)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。

 
# 参数:
    # name,Redis的name
    # amount,自增数(必须是整数)
# 注:同incrby
 
incrbyfloat(self, name, amount=1.0)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。

 
# 参数:
    # name,Redis的name
    # amount,自增数(浮点型)
 
decr(self, name, amount=1)
# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。

# 参数:
    # name,Redis的name
    # amount,自减数(整数)
 
append(key, value)
# 在redis name对应的值后面追加内容

 
# 参数:
    key, redis的name
    value, 要追加的字符串
 

2.1.4 Hash操作,redis中Hash在内存中的存储格式:

name                  hash
                       k1-->v1
n1  -----------> k2 -->v2
                       k3-->v3
hset(name, key, value)
# name对应的hash中设置一个键值对(不存在,则创建;否则,修改)

# 参数:
    # name,redis的name
    # key,name对应的hash中的key
    # value,name对应的hash中的value
# 注:
    # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
 
hmset(name, mapping)
# 在name对应的hash中批量设置键值对

# 参数:
    # name,redis的name
    # mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
# 如:
    # r.hmset('xx', {'k1':'v1', 'k2': 'v2'})
 
hget(name,key)    # 在name对应的hash中获取根据key获取value
 
hmget(name, keys, *args)
# 在name对应的hash中获取多个key的值

# 参数:
    # name,reids对应的name
    # keys,要获取key集合,如:['k1', 'k2', 'k3']
    # *args,要获取的key,如:k1,k2,k3 
# 如:
    # r.mget('xx', ['k1', 'k2'])
    # 或
    # print r.hmget('xx', 'k1', 'k2')
 
hgetall(name)  获取name对应hash的所有键值
 
hlen(name)  # 获取name对应的hash中键值对的个数
 
hkeys(name)  # 获取name对应的hash中所有的key的值
 

python【第十一篇】消息队列RabbitMQ、缓存数据库Redis的更多相关文章

  1. docker安装消息队列(rabbitmq)及数据库(mongo、mysql)

    解决ipv6 访问问题 nohup socat TCP6-LISTEN:36001,reuseaddr,fork TCP4:127.0.0.1:36000 > /root/ip6to4.log ...

  2. 消息队列rabbitmq/kafka

    12.1 rabbitMQ 1. 你了解的消息队列 rabbitmq是一个消息代理,它接收和转发消息,可以理解为是生活的邮局.你可以将邮件放在邮箱里,你可以确定有邮递员会发送邮件给收件人.概括:rab ...

  3. 消息队列rabbitmq rabbitMQ安装

    消息队列rabbitmq   12.1 rabbitMQ 1. 你了解的消息队列 生活里的消息队列,如同邮局的邮箱, 如果没邮箱的话, 邮件必须找到邮件那个人,递给他,才玩完成,那这个任务会处理的很麻 ...

  4. (一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景

    原文:(一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景 本篇并没有直接讲到技术,例如没有先写个Helloword.我想在选择了解或者学习一门技术之前先要明白为什么要现在这个技术而不是 ...

  5. 消息队列rabbitmq的五种工作模式(go语言版本)

    前言:如果你对rabbitmq基本概念都不懂,可以移步此篇博文查阅消息队列RabbitMQ 一.单发单收 二.工作队列Work Queue 三.发布/订阅 Publish/Subscribe 四.路由 ...

  6. openstack (共享服务) 消息队列rabbitmq服务

    云计算openstack共享组件——消息队列rabbitmq(3)   一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队 ...

  7. C#中使用消息队列RabbitMQ

    在C#中使用消息队列RabbitMQ 2014-10-27 14:41 by qy1141, 745 阅读, 2 评论, 收藏, 编辑 1.什么是RabbitMQ.详见 http://www.rabb ...

  8. node使用消息队列RabbitMQ一

    基础发布和订阅 消息队列RabbitMQ使用 1 安装RabbitMQ服务器 安装erlang服务 下载地址 http://www.erlang.org/downloads 安装RabbitMQ 下载 ...

  9. 消息队列--RabbitMQ(一)

    1.消息队列概述 可以理解为保存消息的一个媒介/或者是个容器,与之相关有两个概念(即生产者(Publish)与消费者(Consumer)).所谓生产者,就是生产创造消息的一方,那么,消费者便是从队列中 ...

  10. (二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念

    原文:(二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念 没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. Rabbit ...

随机推荐

  1. How to delete a large number of data in SharePoint for List when refreshing data?

    Preface Recently thequestion was asked in the newsgroups about deleting a large number of itemsfrom ...

  2. Android项目Tab类型主界面大总结 Fragment+TabPageIndicator+ViewPager

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24740977 Android如今实现Tab类型的界面方式越来越多,今天就把常见的 ...

  3. [Redux] Using withRouter() to Inject the Params into Connected Components

    We will learn how to use withRouter() to inject params provided by React Router into connected compo ...

  4. LeetCode刷题笔录Add Binary

    Given two binary strings, return their sum (also a binary string). For example, a = "11" b ...

  5. LabVIEW系列——合并错误(VI)的用法

    Merge Errors.vi的功能:1.按顺序搜索错误输入1,2,3,以及错误数组输入中的错误,输出第一个错误.                        2.如果没有错误,也就是错误状态都为F ...

  6. hadoop错误org.apache.hadoop.mapred.MapTask$NewOutputCollector@17bda0f2

    错误: org.apache.hadoop.mapred.MapTask$NewOutputCollector@17bda0f2 java.io.IOException: Spill failed 错 ...

  7. kindle

    http://www.mindmap8.com/Kindle_Paperwhite/20130726266.html http://blog.csdn.net/felomeng/article/det ...

  8. hdu2035java

    人见人爱A^B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  9. SQL语句操作文件

    -----先开启命令exec sp_configure 'show advanced options', 1; reconfigure; exec sp_configure 'xp_cmdshell' ...

  10. linux rman shell

    # make direcory for backset file and scripts file,in my case /backup/db_bak cd   /backup/db_bak mkdi ...