NoSQLPython开发【第十首】:Redis

缓存数据库介绍

NoSQL(Not Only
SQL),即”不仅仅是SQL”,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在答应本着web2.0网站,特别是超大规模和高起的SNS类型的web2.0纯粹动态网站曾亮心有余而力不足,暴露了无数难以克服的题目,而休关系型的数据库则是因为该自的风味得到了很便捷的开拓进取。NoSQL数据库的起就是为缓解大数据集合多再次数量列带来的挑战,尤其是特别数额采取难题。

NoSQL数据库的季不胜分类

生四要命NoSQL类型:键值存储(key-value store)、文件存储(document
store)、列导向的数据库(Column-Oriented Database)和图纸数据库(graph
database)。每种型且解决了传统关系数据库无法缓解的问题。实际的兑现多次是这些组合的重组。例如结合NoSQL类型,Orientdb是一个几近模式之数据库。Orientdb是图表数据库,每个节点都是一个文档。

键值(key-value)存储数据库

旋即无异于好像数据库重点会动用及一个哈希表,这个发明中发生一个一定的键和一个指南针指为特定的数量。Key/Value模型对于IT系统来说的优势在简单、易部署。但是要DBA只针对片值进行询问或更新的时候,Key/Value就显示效率低下了。代表数据库Tokyo
Cabinet/Tyrant、Redis、Voldemort、Oracle BDB。

排存储数据库

当下片数据库一般是故来应本着分布式存储的海量数据。键任然存在,但是其的性状是凭借于了差不多单列。这些列是出于列家族来布局的。代表数据库Cassandra、HBase、Riak。

文档型数据库

文档型数据库的灵感来自于Lotus
Notes办公软件,而且它们跟第一种键值存储类似。该档的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可用作是键值数据库的升官版本,允许之间嵌套键值。而且文档型数据库比键值数据库的询问效率还胜。代表数据库CouchDB、MongoDB,国内SequoiaDB。

图形(Graph)数据库

图片结构的数据库暨另队以及刚性结构的SQL数据库不同,它是运用灵活的图片模型,并且会壮大及大半宝服务器上。NoSQL数据库没有正规的询问语言(SQL),因此开展数据库查询需要制订数据模型。许多NoSQL数据库都生REST式的多少接口或者查询API。代表数据库Neo4J、InfoGrid、Infinite
Graph。

所以NoSQL数据库在偏下几栽状态较适用:1、数据模型比较简单;2、需要灵活性更胜似之IT系统;3、对数据库性能要求比高;4、不需高度的多少一致性;5、对于被一定key比较好映射复杂值的条件。

NoSQL数据库的季好分类对比

分类

代表数据库

典型应用场景

数据模型

优点

缺点

键值(key-value)

Tokyo Cabinet/Tyrant、Redis、Voldemort、Oracle BDB

内容缓存,主要用于处理大量数据的高访问负载,也用于一些日子系统。

key指向value的键值对,通常用hash table来实现。

查找速度快

数据无结构化,通常只被当作字符串或者二级制数据。

列存储数据库

Cassandra、HBase、Riak

分布式的文件系统

以列簇式存储,将同一列数据存在一起

查找速度快,可扩展性强,更容易进行分布式扩展

功能相对局限性

文档型数据库

CouchDB、MongoDB

web应用(与key-value类似,value是结构化的,不同的是数据库能够了解value的内容)

key-value对应的键值对,value为结构化数据

数据结构要求不严格,表结构可变,不需要像关系数据库一样需要预先定义表结构

查询性能不高,而且缺乏统一的查询语法

图形(Graph)数据库

Neo4J、InfoGrid、Infinite Graph

社交网络、推荐系统等。专注于构建关系图谱

图结构

利用图结构相关算法。比如最短路径寻址,N度关系查找等。

很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。

Redis

介绍

redis是业界主流的key-value
nosql数据库有。与Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted
set有序聚集)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及获得交集和差集及重新增长的操作,而且这些操作都是原子性的。在斯基础及,redis支持各种不同方式的排序。与memcached一样,为了保险效率,数据还是缓存在内存中。区别是redis会周期性的管创新的数目形容副磁盘或者将修改操作写副追加的记录文件,并且于这个基础及落实了master-slave(主从)同步。

Redis优点

那个敏捷:Redis是殊急匆匆的,每秒可以执行大约110000装操作,81000只/秒的读取操作。

支持添加的数据类型:Redis支持不过要命多数开发人员已经清楚数据类,如列表、集合、可排序集合、哈希等。这使在使用被非常容易解决各种问题,因为咱们解怎么问题处理利用什么数据类型更好解决。

操作都是原子的:所有Redis的操作都是原子,从而保证当半个客户以做客Redis服务器得到的凡翻新后的价(最新值)。

MultiUtility工具:Redis是一个基本上力量实用工具,可以在缓存、消息传递队列中采取(Redis原生支持发布/订阅),在应用程序中web应用程序会话,网站网页点击数等其它短暂之数据。

Redis缺点

持久化:Redis直接将数据存储到内存中,要用数据保存至磁盘上,Redis可以利用有限栽艺术实现持久化过程。定时快照(snapshot),每隔一段时间将满数据库写到磁盘上,每次均是写满数码,代价十分强。基于语词多(aof),只追踪变化之数额,但是多的log可能了好,同时具备的操作都重履行同样全勤,回复速度放缓。

占用内存过强。

改配置文件,进行再次开,将硬盘中之数码加载进内存,时间比遥远。这个进程中redis不克提供劳务。

Redis不具机动容错和死灰复燃功能,主机从机的宕机都见面招致前者部分读写请求失败,需要等机器还开或者手动切换前端的IP才会东山再起。

主机宕机,宕机前发出有数据不能就同到从机,切换IP后还见面引入数未均等的题目,降低了系的可用性。

Redis较难以支撑在线扩容,在集群容量达到上限时在线扩容会转换得异常复杂。为了避免这无异题目,运维人员于系上线时必管有足的空间,这对准资源造成了杀特别之荒废。

安装Redis环境

redis官网:https://redis.io/

下载源码,解压后编译源码

  1. wget http://download.redis.io/releases/redis-3.0.6.tar.gz
  1. tar xzf redis-3.0.6.tar.gz

  2. cd redis-3.0.6

  3. make

编译完成后,进入redis-3.0.6目录。将redis.conf中的daemonize配置也yes(以守护进程方式运行)。

登src目录启动redis,指定安排文件位置,并后台运行。

  1. redis-server
    /root/redis-3.0.6/redis.conf &

查是否启动

  1. lsof -i:6379

  2. COMMAND PID USER FD TYPE DEVICE
    SIZE/OFF NODE NAME

  3. COMMAND PID USER FD TYPE DEVICE
    SIZE/OFF NODE NAME

  4. redis-ser 1612 root 4u IPv6 13114 0t0
    TCP *:6379 (LISTEN)

  5. redis-ser 1612 root 5u IPv4 13116 0t0
    TCP *:6379 (LISTEN)

运行redis客户端redis-cli。

  1. redis-cli

  2. 127.0.0.1:6379> ping

  3. PONG

  4. 127.0.0.1:6379>

暨当下说明已经打响安装了redis。

Redis API使用

接连方式

操作模式

Redis-py提供零星只类Redis和StrictRedis用于落实Redis的吩咐,StrictRedis用于落实多数官方的一声令下,并动用官方的语法和下令,Redis是StrictRedis的子类,用于为后相当旧本子的redis-py。

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import redis

  6.  

  7. # 连接池

  8. pool =
    redis.ConnectionPool(host=’192.168.31.128′,port=6379)

  9.  

  10. r = redis.Redis(connection_pool=pool)

  1. r.set(‘foo’,’golden’)

  2. print(r.get(‘foo’))

连接池

redis-py使用connection pool来保管针对性一个redis
server的富有连接,避免每次建立、释放连接的开。默认每个Redis实例都见面保护一个融洽的连接池。可以一直建立一个连接池,然后作为参数Redis,这样就算好实现多个Redis实例共享一个连接池。

基本操作

String操作

Redis中之String在内存中按照一个name对应一个value来存储。

NoSQL 1

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不设有时时,执行设置操作(添加)。

psetex(name,time_ms,value)

time_ms过期时(毫秒)

mset(*args,**kwargs)

批量设置值mset(k1=’v1′,k2=’v2′)或mget({‘k1′:’v1′,’k2′:’v2’})。

get(name)

获取值。

mget(keys,*args)

批量取得值,mget(‘name1′,’name2’)或r.mget([‘name1′,’name2’]。

getset(name,value)

安新增并拿走原来的价值。

getrange(key,start,end)

获取取子序列(根据字节获取,非字符)。一个字3只字节。

setrange(name,offset,value)

修改字符串内容,从指定字符串索引开始为后替换(新值太丰富时,则于后加加)。

setbit(name,offset,value)

针对name对应值的二进制表示的各类展开操作。offset号的目录将值变换成二前行制后复拓展索引,value值只能是1或0。例如setbit(‘name’,6,1)表示将字符串name用二进制表示后,将第六个设置为1。

getbit(name,offset)

取name对应的值的二进制表示受到之某位的价值。

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

博name对应的价的二进制表示着1底个数。

strlen(name)

取得name对应值的字节长度(一个中国字3只字节)。

incr(self,name,amount=1)

自从增name对应之价值,当name不有时时,则开创name=amount,否则就自增,自增数必须是整数。

incrbyfloat(self,name,amount=1.0)

从增name对应之价,当name不在时时,则开创name=amount,否则即自增,自增数浮点型。

decr(self,name,amount=1)

起减name对应的价,当name不存在时时,则创造name=amount,否则就是自减,自减数整数。

append(key,value)

当key对应之价后多内容value。

Hash操作

Hash表现形式上稍加像python中的dict,可以储存一组关联性较强之数,redis中的Hash在内存中的囤格式如下图。

NoSQL 2

hset(name,key,value)

name对应的hash中装置一个键值对,不存在则创造,否则修改。

hmset(name,mapping)

于name对应之hash中批量设置键值对。

hgetall(name)

取得name对应hash的有所键值。

hlen(name)

得到name对应之hash中键值对的个数。

hkeys(name)

赢得name对应之hash中负有的key值。

hvals(name)

获取name对应的hash中持有的value值。

hexists(name,key)

检查name对应的hash是否留存即传来的key。

hdel(name,*keys)

以name对应的hash中指定key的键值对勾。

hincrby(name,key,amount=1)

自增name对应之hash中之指定key的值,不存在则开创key=amount。amount自增数(整数)。

hincrbyfloat(name,key,amount=1.0)

于增name对应的hash中之指定key的价值,不存则开创key=amount。amount自增数(浮点数)。

hscan_iter(name,match=None,count=None)

采取yield封装hscan创建生成器,实现分批去redis中获取数据。

List

Redis中之List在内存中安装一个name对应一个List来囤。如下图所示。

NoSQL 3

lpush(name,values)

于name对应之list中补充加元素,每个新的因素还增长到列表的顶左边。如r.lpush(‘test’,11,22,33),保持顺序也33,22,11。rpush(name,values)表示于右边为左操作。

lpushx(name,value)

当name对应的list中补充加元素,只有name已经是时时,值添加到列表的极端左边。rpushx(name,value)表示从今右边为左操作。

llen(name)

name对应的list元素的个数。

linsert(name,where,refvalue,value)

每当name对应的列表的某一个值前或者后插入一个新值。where:BEFORE或AFTER;refvalue:标杆值,即以它们左右插入数据;value:要插入的数量。

r.lset(name,index,value)

本着name对应的list中的某个一个目录位置又赋值。index:list的目位置。

r.lrem(name,num,value)

每当name对应之list中删去指定的值。value:要抹的价值;num>0:从表头开始为表尾搜索,移除与value相等的元素,删除数量为num个;num<0:从表尾开始通往表头搜索,移除与value相等的因素,删除数量为num个;num=0:移除表中所有与value相等的价值。

lpop(name)

以name对应之列表的左侧获取第一单元素并在列表中移除,返回第一只因素。

lindex(name,index)

于name对应的列表中冲目录获取列表元素。

lrange(name,start,end)

以name对应的列表分片获取数据。

ltrim(name,start,end)

每当name对应的列表中移除没有当start-end索引之间的价值。

rpoplpush(src,dst)

由一个列表取出最右边边的元素,同时以该加加至其它一个列表的无限左边。src:要拿走多少的列表的name;dst:要补充加多少的列表的name。

blpop(keys,timeout)

以大半只列表排列,按照从左到右去pop对承诺列表的元素。timeout:超时时间,当元素所有列表的因素得到了以后,阻塞等待列表内发数据的光阴(秒),0表示永远阻塞。

brpoplpush(src,dst,timeout=0)

自打一个列表的下手移除一个因素并将那补偿加至任何一个列表的左手。

set

Redis的set是string类型的无序集聚。集合成员是唯一的,这就是象征集合中未可知起重复的多寡。

sadd(name,values)

name对应之聚集中上加元素。

scard(name)

获取name对应之集中元素个数。

sdiff(keys,*args)

以首先独name对应的联谊中且不以另外name对应之集合元素的聚众。

sdiffstore(dest,keys,*args)

抱第一只name对应的集纳中且不在旁name对应之集合元素,再将该新参加到dest对应的聚合中。

sinter(keys,*args)

得到多只name对应集合的混。

sinterstore(dest,keys,*args)

赢得多个name对应集合的并集,再用那个在到dest对应之集结中。

sismember(name,value)

检查value是否是name对应的集的分子。

smembers(name)

取name对应的联谊的保有成员。

smove(src,dst,value)

用有成员由一个集聚中走至任何一个汇聚。

spop(name)

从集合的右边(尾部)移除一个分子,并拿那归来。

srandmember(name,numbers)

由name对应的集聚中随机获取numbers个因素。

srem(name,values)

在name对应的汇聚中删去某些价值。

sunion(keys,*args)

收获多独name对应的集结的并集。

sunionstore(dest,keys,*args)

取多单name对应的汇的并集,并以结果保存到dest对应的聚众中。

有序聚集,在集聚的基本功及呢每个元素排序,元素的排序需要基于外一个价值来进展比,所以,对于有序聚集各一个因素来少数只价,即值和分,分数用来举行排序。

zadd(name,*args,**kwargs)

每当name对应之静止聚集中上加元素。

zcard(name)

获name对应的雷打不动集合元素的数。

zcount(name,min,max)

博name对应的稳步聚集中分在min和max之间的个数。

zincrby(name,value,amount)

针对点名成员的分加上增量value。

r.zrange(name,start,end,desc=False,score_cast_func=float)

依索引范围获得name对应的有序聚集的素。

start:有序集合索引起起位置(非分数)。

end:有序集合索引了位置(非分数)。

desc:排序规则,默认按照分从小到深排序。

withscores:是否拿走元素的分数,默认只抱元素的值。

score_cast_func:对分数进行数量易的函数。

zrevrange(name,start,end,withscores=False,score_cast_func=float)

自那个至多少排序。

zrangebyscore(name,min,max,start=None,num=None,withscores=False,score_cast_func=float)

遵照分范围取得name对应之有序聚集的因素。

zrevrangebyscore(name,max,min,start=None,num=None,withscores=False,score_cast_func=float)

起生至有些排序。

zrank(name,value)

收获有值在name对应的不变聚集中之行

zrevrank(name,value)

自打十分及稍微排序。

zrem(name,values)

去除name对应之有序聚集中值是values的分子。

zremrangebyrank(name,min,max)

冲排名范围去。

zremrangebyscore(name,min,max)

据悉分数范围去。

zscore(name,value)

取得name对应有序集合中value对应之分。

zinterstore(dest,keys,aggregate=None)

获得两个静止聚集的夹,如果遇上相同值不同分数则随aggregate进行操作,aggregate的值为SUM、MIN、MAX。

其他操作

delete(*names)

依据name删除redis中之即兴数据类型。

exists(name)

检测redis的nameNoSQL是否是。

keys(pattern=’*’)

因key匹配获取redis的name。

expire(name,time)

也某某redis的之一name设置过时间。

rename(src,dst)

对redis的name重命名。

move(name,db)

以redis的某个值移动至指定的db下。

randomkey()

擅自获得一个redis的name(不去)。

type(name)

赢得name对应值的种类。

管道

redis-py默认在推行每次要都见面创(连接池申请连接)和断开(归还连接池)一潮连续操作。如果想只要在同等不好呼吁被指定多只命,则足以应用pipline实现均等不行呼吁指定多独令,并且默认情况下同样不善pipline是原子性操作。(原子性操作是借助非会见叫线程调度机制打断的操作,这种操作而开始便直运行至了,中间不见面时有发生另外context
switch(切换到其它一个线程))

宣布订阅

Redis发布订阅(pub/sub)是一致种信息通信模式,发送者(pub)发送信息,订阅者(sub)接收信息。Redis客户端可订阅任意数量之频段。下图显示了频道channel1,以及订阅者频道的老三只客户端client1、client2和client5之间的涉及。

NoSQL 4

当起新消息经publish命令发送给频道channel1时常,这个信息就是会见让发送给订阅它的老三个客户端。

NoSQL 5

RedisHelper_basic

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import redis

  6.  

  7. class
    RedisHelper(object):

  8.     “””

  9.     RedisHelper

  10.     “””

  11.     def __init__(self):

  12.         self.__conn =
    redis.Redis(host=’192.168.31.128′)

  13.         self.chan_sub = ‘channel1’

  1.         self.chan_pub = ‘channel1’
  1.  

  2.     def public(self,msg):

  3.         self.__conn.publish(self.chan_pub,msg)

  1.         return True

  2.  

  3.     def subscribe(self):

  4.         pub = self.__conn.pubsub()

  1.         pub.subscribe(self.chan_sub)
  1.         pub.parse_response()

  2.         return pub

发布者

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import redisHelper_basic

  6.  

  7. obj = redisHelper_basic.RedisHelper()

  1. obj.public(‘hello’)

订阅者

  1. __author__ = ‘Golden’

  2. #!/usr/bin/env python3

  3. # -*- coding:utf-8 -*-

  4.  

  5. import redisHelper_basic

  6. obj = redisHelper_basic.RedisHelper()

  1. redis_sub = obj.subscribe()

  2.  

  3. while
    True:

  4.     msg = redis_sub.parse_response()

  1.     print(msg)

结果

  1. [b’message’, b’channel1′, b’hello’]

 

网站地图xml地图