python Nosql-redis 连接、管道
非关系型数据库和关系型数据库的差别:
非关系型数据库的优势:
-
性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
-
可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
关系型数据库的优势:
-
复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
-
事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。但是近年来这两种数据库都在向着另外一个方向进化。
例如:NOSQL数据库慢慢开始具备SQL数据库的一些复杂查询功能的雏形,比如Couchbase的index以及MONGO的复杂查询。对于事务的支持也可以用一些系统级的原子操作来实现例如乐观锁之类的方法来曲线救国。
SQL数据库也开始慢慢进化,比如HandlerSocker技术的实现,可以在MYSQL上实现对于SQL层的穿透,用NOSQL的方式访问数据库,性能可以上可以达到甚至超越NOSQL数据库。可扩展性上例如Percona Server,可以实现无中心化的集群。虽然这两极都因为各自的弱势而开始进化出另一极的一些特性,但是这些特性的增加也会消弱其本来具备的优势,比如Couchbase上的index的增加会逐步降低数据库的读写性能。
redis的概念:
redis是一个key-value存储系统。
和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。
redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。
这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
Redis的安装:
redis中文网: http://www.redis.net.cn/
[root@Node1 opt]# wget http://download.redis.io/releases/redis-3.0.6.tar.gz
[root@Node1 opt]# tar zxvf redis-3.0.6.tar.gz -C /usr/local/src/
[root@Node1 opt]# cd !$
cd /usr/local/src/
[root@Node1 src]# ls
pip-1.3.1.tar.gz Python-2.7.14 redis-3.0.6
[root@Node1 src]# cd redis-3.0.6/
[root@Node1 redis-3.0.6]# ls
00-RELEASENOTES CONTRIBUTING deps Makefile README runtest runtest-sentinel src utils
BUGS COPYING INSTALL MANIFESTO redis.conf runtest-cluster sentinel.conf tests
[root@Node1 redis-3.0.6]# make
cd src && make all
...
[root@Node1 redis-3.0.6]# src/redis-server &
[1] 50007
[root@Node1 redis-3.0.6]# 50007:C 28 Nov 08:53:03.999 # Warning: no config file specified, using the default config. In order to specify a config file use src/redis-server /path/to/redis.conf
50007:M 28 Nov 08:53:04.000 * Increased maximum number of open files to 10032 (it was originally set to 1024).
50007:M 28 Nov 08:53:04.001 # Creating Server TCP listening socket *:6379: bind: Address already in use
[1]+ Exit 1 src/redis-server
[root@Node1 redis-3.0.6]# ps aux|grep redis
root 8345 0.1 0.4 143920 8004 ? Sl Nov27 1:43 ./src/redis-server *:6379
root 50009 0.0 0.0 103320 884 pts/1 S+ 08:53 0:00 grep redis
[root@Node1 redis-3.0.6]# netstat -nlp|grep redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 8345/./src/redis-se
tcp 0 0 :::6379 :::* LISTEN 8345/./src/redis-se
[root@Node1 redis-3.0.6]#
python 操作redis
安装redis模块
[root@Node1 redis-3.0.6]# pip install redis
Collecting redis
Using cached redis-2.10.6-py2.py3-none-any.whl
Installing collected packages: redis
Successfully installed redis-2.10.6
redis.Redis 连接数据库
set()方法 :写入一条数据
get(key) 方法: 获取key 对应的值
key() 方法: 获取所有的key
import redis as redis
redis_info = {
'host':'11.11.11.11',
'port':6379
}
r = redis.Redis(**redis_info) # 建立redis 连接
r.set('name','lijunjiang') # r.set() 写入一条数据 redis经key-value形式存储
r.get('name') # r.get(key-name) 获取key-name 对应的值
print(r.key()) # r.key 获取所有的键
########
C:\Python27\python.exe D:/Python/redis/redis_Redis.py
lijunjiang
['name']
Process finished with exit code 0
redis.ConnectionPool() 方法: 管理对一个redis server的所有连接 ,可以避免每次建主、释放连接的开销
默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池
import redis as redis
redis_info = {
'host':'11.11.11.11',
'port':6379
}
pool = redis.ConnectionPool(**redis_info) # 建立一个redis 连接池
r = redis.Redis(connection_pool=pool) # 从连接池里获取连接
r.set('age',15)
print(r.get('age'))
print(r.keys())
#######
C:\Python27\python.exe D:/Python/redis/redis_Redis.py
15
['age', 'name']
Process finished with exit code 0
redis 管道
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作
redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/11/28 22:48
# @Author : lijunjiang
# @File : redis-pipeline.py
import datetime
import redis
redis_info = {
'host': '11.11.11.11',
'port': 6379
}
def conncet_redis():
pool = redis.ConnectionPool(**redis_info)
try:
r = redis.Redis(connection_pool=pool)
except Exception as err:
raise err
return r
def withpipe(r):
# r = conncet_redis()
pipe = r.pipeline(transaction=True)
for i in xrange(1,1000):
key = "test1" + str(i)
value = "value"+str(i)
pipe.set(key, value)
pipe.execute()
def withoutpipe(r):
# r = conncet_redis()
for i in xrange(1,1000):
key = "test1" + str(i)
value = "value"+str(i)
r.set(key, value)
def time(fun):
r = conncet_redis()
start = datetime.datetime.now()
fun(r)
end = datetime.datetime.now()
run_time = (end-start).microseconds
return run_time
if __name__ == '__main__':
# r1 = conncet_redis()
# r2 = conncet_redis()
withpipe_time = time(withpipe)
withoutpipe_time = time(withoutpipe)
print("withpipe run time:{0}".format(withpipe_time))
print("withoutpipe run time: {0}".format(withoutpipe_time))
###################
C:\Python27\python.exe D:/Python/redis/redis-pipeline.py
withpipe run time:19000
withoutpipe run time: 203000
Process finished with exit code 0