一、NoSQL的操作

  NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。

  虽然NoSQL的流行与火起来才短短几年的时间,但是不可否认,现在已经开始了第二代运动。尽管早期的堆栈代码只能算是一种实验,然而现在的系统已经更加的成熟、稳定。不过现在也面临着一个严酷的事实:技术越来越成熟——以至于原来很好的NoSQL数据存储不得不进行重写,也有少数人认为这就是所谓的2.0版本。该工具可以为大数据建立快速、可扩展的存储库。

非关系型数据库和关系型数据库的差别:

  非关系型数据库的优势:1. 性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。2. 可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。

  关系型数据库的优势:1. 复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。2. 事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。但是近年来这两种数据库都在向着另外一个方向进化。例如:NOSQL数据库慢慢开始具备SQL数据库的一些复杂查询功能的雏形,比如Couchbase的index以及MONGO的复杂查询。对于事务的支持也可以用一些系统级的原子操作来实现例如乐观锁之类的方法来曲线救国。SQL数据库也开始慢慢进化,比如HandlerSocker技术的实现,可以在MYSQL上实现对于SQL层的穿透,用NOSQL的方式访问数据库,性能可以上可以达到甚至超越NOSQL数据库。可扩展性上例如Percona Server,可以实现无中心化的集群。虽然这两极都因为各自的弱势而开始进化出另一极的一些特性,但是这些特性的增加也会消弱其本来具备的优势,比如Couchbase上的index的增加会逐步降低数据库的读写性能。所以怎样构建系统的短期和长期存储策略,用好他们各自的强项是架构师需要好好考虑的重要问题。

二、redis服务搭建

  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一般都是安装在linux系统中,具体安装步骤如下:

#cd /usr/local/src
#wget http://download.redis.io/releases/redis-3.0.1.tar.gz
#tar xzf redis-3.0.1.tar.gz
#cd redis-3.0.1
#make
#src/redis-server &
检查redis是否正常启动
Ps –ef |grep redis
Netstat –lnp |grep 6379

 安装redis客户端,在pycharm的terminal中进行安装

pip install redis

三、redis的简单操作

  redis是以key-value的形式存储的,所以我们在操作的时候。首先我们将redis所在主机的ip和发布端口作为参数实例化了一个对象r,然后执行set('name','I love you!'),这样我们就在内存中存储了一个key为shang,值为‘I love you!’的项。我们可以理解为{'shang':'I love you!'},当我们要读取的之后,keys()就是获得多有key值。

  1.对redis简单的操作,代码如下:

import redis

redis_config = {
"host":"192.168.203.12",
"port":6379
} r = redis.Redis(**redis_config)
r.set("abc","something")
#set操作,第一个参数是key,第二个参数是value
print (r.get("abc"))

结果:something

  2.redis的连接池,代码如下:

# redis连接池
def get_redis_connect():
redis_config = {
"host":"192.168.203.12",
"port":6379
}
pool = redis.ConnectionPool(**redis_config)
r = redis.Redis(connection_pool=pool)
return r if __name__ == "__main__":
r = get_redis_connect()
r.set("name","huangdongju")
print (r.get("name"))

结果:huangdongju

四、redis管道

  redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。减少功耗

  redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。基本的通信过程如下:

Client: INCR X

Server: 1

Client: INCR X

Server: 2

Client: INCR X

Server: 3

Client: INCR X

Server: 4

  基本上四个命令需要8个tcp报文才能完成。由于通信会有网络延迟,假如从client和server之间的包传输时间需要0.125秒。那么上面的四个命令8个报文至少会需要1秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了可以利用mget,mset 之类的单条命令处理多个key的命令外我们还可以利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。通信过程如下:

Client: INCR X

Client: INCR X

Client: INCR X

Client: INCR X

Server: 1

Server: 2

Server: 3

Server: 4

  假设不会因为tcp报文过长而被拆分。可能两个tcp报文就能完成四条命令,client可以将四个命令放到一个tcp报文一起发送,server则可以将四条命令的处理结果放到一个tcp报文返回。通过pipeline方式当有大批量的操作时候。我们可以节省很多原来浪费在网络延迟的时间。需要注意到是用 pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并是不是打包的命令越多越好。具体多少合适需要根据具体情况测试

  代码如下:

import datetime
import redis def withpipe(r):
pipe = r.pipeline(transaction=True)
for i in xrange(1, 1000):
key = "test1" +str(i)
value = "test1" + str(i)
pipe.set(key, value)
pipe.execute() def withoutpipe(r):
# pipe = r.pipeline(transaction=True)
for i in xrange(1, 1000):
key = "test1" + str(i)
value = "test1" + str(i)
r.set(key, value) if __name__ == "__main__":
pool = redis.ConnectionPool(host="192.168.203.12", port=6379, db=0)
r1 = redis.Redis(connection_pool=pool)
r2 = redis.Redis(connection_pool=pool)
start = datetime.datetime.now()
# print(start)
withpipe(r1)
end = datetime.datetime.now()
# print((end-start).microseconds)
# print(end-start)
t_time = (end - start).microseconds
print("withpipe time is : {0}".format(t_time)) start = datetime.datetime.now()
withoutpipe(r2)
end = datetime.datetime.now()
t_time = (end - start).microseconds
print("withoutpipe time is : {0}".format(t_time))

结果:

withpipe time is : 27000
withoutpipe time is : 372000

五、string操作

  redis中的string在内存中都是按照一个key对应一个value来存储的。如:

r.set(“name”, “huangdongju”)

  1.set的使用方法:

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

  ex,过期时间(秒)

px,过期时间(毫秒)

nx,如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value)

xx,如果设置为True,则只有name存在时,当前set操作才执行'''

  2.get(name)     获取值

print(r.get("name"))

  3.mset()          批量设置值

r.mset(name1="shang", name2="ling")
r.mset({"name3": "kong", "name4": "gu"})

  4.mget(keys, *args)                    批量获取值

print(r.mget("name1", "name2", "name3", "name4"))

  程序代码如下:

import redis
pool = redis.ConnectionPool(host="192.168.203.12",port = 6379,db =0)
r = redis.Redis(connection_pool = pool) r.set("name","huangdongju")
print (r.keys())
print (r.get("name"))
r.mset(name1="huang",name2="momo")
print (r.mget("name1","name2"))
r.mset({"hello":"world","hi":"nice"})
print (r.keys())
print (r.mget("hello","hi"))

  结果:

六、list操作

  redis中的List在在内存中按照一个name对应一个List来存储。常用的方法:

  1.lpush(name,values):在name对应的list中添加元素,每个新的元素都添加到列表的最左边

  2.rpush(name,values):同lpush,但每个新的元素都添加到列表的最右边

  3.lpushx(name,value):在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边

  4.rpushx(name,value):在name对应的list中添加元素,只有name已经存在时,值添加到列表的最右边

  5.llen(name):name对应的list元素的个数

  6.linsert(name,where,refvalue,value):在name对应的列表的某一个值前后插入一个新值

     参数:

     name,redis的name

where,BEFORE或AFTER

     refvalue,标杆值,即:在它前后插入数据

      value,要插入的数据

  

  7.r.lset(name,index,value):对name对应的list中的某一个索引位置重新赋值。

   参数:

name,redis的name

     index,list的索引位置

     value,要设置的值

  8.r.lrem(name,value,num):在name对应的list中删除指定的值

  参数:

    name,redis的name

         value,要删除的值

         num,  num=0,删除列表中所有的指定值;

        num=2,从前到后,删除2个;

        num=-2,从后向前,删除2个

  9.lpop(name):在name对应的列表的左侧获取第一个元素并在列表中移除,返回值删除那个元素的值

    10.rpop(name) 表示从右向左操作

  11.lindex(name,index):在name对应的列表中根据索引取列表元素

  12.lrange(name,start,end):在name对应的列表分片获取数据

  程序代码如下:

import redis
pool = redis.ConnectionPool(host="192.168.203.12",port=6379,db=0)
r = redis.Redis(connection_pool=pool) #lpush 在list的左边增加一个元素
#rpush 在list的右边增加一个元素
r.lpush("list1","test1")
r.rpush("list1","huang")
r.lpush("list1", "test2")
r.lpush("list1", "test3")
r.lpush("list1", "test2")
r.lpush("list1", 2, 3, 4)
r.lpush("list1", "test2")
print(r.lrange("list1", 0, -1)) #在中间位置增加一个元素
#linsert(name,where,refvalue,value)
#naem 代表的是list对应的key值
#where After Before
#refvalue list中的某个元素
#value 要增加的值
r.linsert("list1","AFTER","test2","hello")
print(r.lrange("list1", 0, -1))
r.lset("list1",2,"world")
#lset 更改某个元素的值
# r.lset(name,index,value) print (r.lrange("list1",0,-1))
print (r.lindex("list1",2))
# lindex 查看list某个下标的值

  结果:

七、set操作

  set集合就是不重复的列表。常用的方法:

  1.sadd(name,values):给name对应的集合中添加元素

  2.smembers(name):获取name对应的集合的所有成员

  3.scard(name):获取name对应的集合中的元素个数

  4.sinter(keys, *args):获取多个name对应集合的并集

  5.sismember(name, value):检查value是否是name对应的集合内的元素

  6.spop(name):从集合的右侧移除一个元素,并将其返回

  7.sunion(keys, *args):获取多个name对应的集合的并集

  8.srem(name, value)  删除集合中的某个元素

程序代码如下:

import redis
pool = redis.ConnectionPool(host="192.168.203.12",port=6379,db=0)
r = redis.Redis(connection_pool=pool)
#r.sadd(name,*args) 增加一个name对应的一个集合
r.sadd("set_name","aa","bb","cc") #smember 查看集合的所有元素
print(r.smembers("set_name")) #scard 等同于 list 的len 查看元素的个数
print (r.scard("set_name")) #srem(name,value) 删除值为value的指定集合中的某个元素
r.srem("set_name","aa") print (r.smembers("set_name")) r.sadd("set_name1","cc","dd","ee") #sinter 两个集合的交集
print(r.sinter("set_name","set_name1")) #sunion 两个集合的并集
print (r.sunion("set_name","set_name1"))

结果:

八、hash类型操作

  Redis在内存中存储hash类型是以name对应一个字典形式存储的,简单来说就是一个name对应一个字典

  1.hset(name,key,value):name对应的hash中设置一个键值对(不存在,则创建;否则,修改)

  参数:

  name:redis的name

  key:key对应的hash中的key

  value:value对应的hash中的value

  注:hsetx(name,key,value),当name对应的hash中不存在当前key则创建(相当于添加)

  2.hget(name,key):在name对应的hash中获取根据key获取value

  3.hmset(name,mapping):在name对应的hash中批量设置键值对

  参数:

  name:redis的name

  mapping:字典,如{'k1':'v1','k2','v2'}

  4.hmget(name,keys,*args):在name对应的hash中获取多个key的值

  参数:

  name:redis对应的name

  keys:要获取key的集合,如:['k1','k2','k3']

  *args:要获取的key,如:k1,k2,k3

  5.hgetall(name):获取name对应hash的所有键值

  6.hlen(name):获得name对应的hash中的键值的个数

  7.hkeys(name):获取name对应的hash中所有的key的值

  8.hvals(name):获取name对应的hash中所有的value的值

  9.hexists(name,key):检查name对应的hash是否存在当前传入的key

  10.hdel(name,*key):将name对应的hash中指定key的键值对删除

  程序例子如下:

import redis
pool = redis.ConnectionPool(host="192.168.203.12",port=6379,db=0)
r = redis.Redis(connection_pool=pool) #hash的类型操作就是一个name对应一个字典
#hset hget hmset hmget
r.hset("dict1","hello","world")
print (r.hget("dict1","hello"))
r.hmset("dict1",{"k1":"v1","k2":"v2","k3":"v3"})
print (r.hmget("dict1","k1","k2","hello"))
print (r.hgetall("dict1")) print (r.hlen("dict1"))
print (r.hkeys("dict1"))
print (r.hvals("dict1"))
print (r.hexists("dict1","hello"))
print (r.hexists("dict1","momo"))
r.hdel("dict1","hello")
print (r.hgetall("dict1"))

  结果:

九、其他操作

  1.delete(*name):根据name删除redis中任意数据类型

  2.exists(name):检测redis中的name是否存在

  3.keys(pattern='*'):根据* ?等通配符匹配获取redis的name

  4.expire(name,time):为某个name设置超时时间

  5.rename(src,dst):重命名

  6.move(name,db):将redis的某个值移动到指定的db下

  7.type(name):获取name对应值的类型

Python操作nosql数据库之redis的更多相关文章

  1. python操作nosql数据库之memcache

    一.memcache的安装 1.memcache简介 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象减少读取数据库的次数,从而 ...

  2. NOSQL数据库之 REDIS

    NOSQL数据库之 REDIS 一.NOSQL 1.简介 NoSQL ,(Not Only SQL),泛指非关系型数据库. 特点: NoSQL 通常是以key-value形式存储, 不支持SQL语句, ...

  3. python操作mysql数据库的相关操作实例

    python操作mysql数据库的相关操作实例 # -*- coding: utf-8 -*- #python operate mysql database import MySQLdb #数据库名称 ...

  4. Python操作Access数据库

    我们在这篇文章中公分了五个步骤详细分析了Python操作Access数据库的相关方法,希望可以给又需要的朋友们带来一些帮助. AD: Python编 程语言的出现,带给开发人员非常大的好处.我们可以利 ...

  5. Windows下安装MySQLdb, Python操作MySQL数据库的增删改查

    这里的前提是windows上已经安装了MySQL数据库,且配置完成,能正常建表能操作. 在此基础上仅仅需安装MySQL-python-1.2.4b4.win32-py2.7.exe就ok了.仅仅有1M ...

  6. 使用python操作mysql数据库

    这是我之前使用mysql时用到的一些库及开发的工具,这里记录下,也方便我查阅. python版本: 2.7.13 mysql版本: 5.5.36 几个python库 1.mysql-connector ...

  7. python 内存NoSQL数据库

    python 内存NoSQL数据库 来自于网络,经过修改,秉承Open Source精神,回馈网络! #!/usr/bin/python #-*- coding: UTF-8 -*- # # memd ...

  8. python操作三大主流数据库(10)python操作mongodb数据库④mongodb新闻项目实战

    python操作mongodb数据库④mongodb新闻项目实战 参考文档:http://flask-mongoengine.readthedocs.io/en/latest/ 目录: [root@n ...

  9. python操作三大主流数据库(9)python操作mongodb数据库③mongodb odm模型mongoengine的使用

    python操作mongodb数据库③mongodb odm模型mongoengine的使用 文档:http://mongoengine-odm.readthedocs.io/guide/ 安装pip ...

随机推荐

  1. Asp.net网站优化【转】

    阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一些方法用于优化ASP.NET网站性能,这些方法都是不 ...

  2. POJ-1080 Human Gene Functions---类似LCS

    题目链接: https://cn.vjudge.net/problem/POJ-1080 题目大意: 给定两组序列,要你求出它们的最大相似度,每个字母与其他字母或自身和空格对应都有一个打分,求在这两个 ...

  3. Ajax系列之三:UpdatePanel

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhanghongjie0302/article/details/35609691           ...

  4. 【安卓】imageView.scaleType取centerCrop后,再用padding时显示异常?

    imgView.setCropToPadding(true);就可以         

  5. BZOJ1718:[USACO]Redundant Paths 分离的路径(双连通分量)

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

  6. 高通Vuforia

    这里使用高通的Vuroria来做一个AR歌姬. 工具: Vuforia,MMD4Mecanim 模型: 初音未来pmd模型文件,极乐净土vmd动作文件. 逻辑: 当发现识别卡时:开启音乐,模型速度为1 ...

  7. luogu P4168 [Violet]蒲公英

    嘟嘟嘟 分块经典题竟然是一道黑题…… 分块求区间众数的大体思想是对于询问区间[L, R],预处理出这中间的整块的众数,然后统计两边零散的数在[L, R]中出现的次数,最后取出现次数最多且最小的数. 因 ...

  8. maven 项目运行找不到类

    其实maven 仓库有jar包,可能未编译或破损, 在本地仓删除它,然后maven install

  9. HDU 1426 Sudoku Killer(dfs 解数独)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1426 Sudoku Killer Time Limit: 2000/1000 MS (Java/Oth ...

  10. 课时90.div和span(掌握)

    为什么在这里讲解div和span呢,而不在html中讲解呢? 因为在我们的开发中div和span一般是配合css来使用的,来完成一定的效果,来设置一些属性,在前面我们没有学习css,所以体会不到它的效 ...