12.python通过redis-py,redisco操作redis

1.安装redis


1.1、准备部分:

什么是redis?

Redis是REmote DIctionary Server的缩写。一个非关系型数据库

为什么要用redis?

1, 因为redis快,Redis is pretty fast!, 110000 SETs/second, 81000 GETs/second

2, 省去了复杂的SQL。

3, 可以省去memcache了。


1.2、下载,解压和编译:


$ wget http://redis.googlecode.com/files/redis-2.6.13.tar.gz
$ tar xzf redis-2.6.13.tar.gz
$ cd redis-2.6.13
$ make

为什么没用标准的Linux安装三板斧呢?官方维基是这样说的:Redis can run just fine without a configuration file (when executed without a config file a standard configuration is used). With thedefault configuration Redis will log to the standard output so you can check what happens. Later, you canchange the default settings.

1.3、运行redis

编译的可执行文件在src目录中,使用以下命令运行Redis:

$ src/redis-server

12.python通过redis-py,redisco操作redis_第1张图片

1.4、连接Redis

你可以用内置客户端连接Redis:

$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

1.5、配置redis


在运行redis前,我们要配置一下。redis的配置文件在你的安装目录里。名为:redis.conf。

简单说几点redis.conf:

redis默认不是用守护进程的,如果需要更改,把daemonize no改成daemonize yes。(测试的时候可以不改,看看打印信息。)

如果对redis默认6379端口不爽的,可以更改port 6379

如果想把数据文件放到一个指定文件夹,更改dir /opt/data/

默认是dir ./ 也就是默认放到安装目录下。

连接超时时间,timeout 300,没什么改头……

dir 是数据文件路径。默认在安装目录下。

*下面的配置二选一,详见本文注释部分2。

###### SNAPSHOTTING ######内存快照方式:

默认的内存快照策略是,

在900秒(15分钟)内,至少有1次数据变更;

或者300秒内,有至少10次数据变更;

或者60秒内,有至少1000次数据变更;时间+数据变更次数,共同影响内存快照的出现。

###### APPEND ONLY MODE ###### AOF方式

appendfsync everysec 每秒同步。这里可以注释掉,打开下面的选项appendfsync no

其余的配置,conf里面的注释写的挺清楚,我就不多废话了。大家看着自己配就行了。

注释:

▲redis的默认端口号是6379,(据redis的作者antirez的博文说,6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。而MERZ长期以来被antirez及其朋友当作愚蠢的代名词。)

▲Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之 后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aof即append only mode,在写入内存数据的同时将操作命令保存到日志文件。

参考:

nosql发烧友集散地:

http://blog.nosqlfan.com

redis认识的几个误区:

http://blog.nosqlfan.com/html/868.html

借鉴:

http://shopscor.javaeye.com/blog/792817


2.安装redis-py


运行

   打开Python解释器:

>>> import redis
>>> r = redis.Redis(host='localhost', port=6379, db=0)   #如果设置了密码,就加上password=密码
>>> r.set('foo', 'bar')   #或者写成 r['foo'] = 'bar'
True
>>> r.get('foo')  
'bar'
>>> r.delete('foo')
True
>>> r.dbsize()   #库里有多少key,多少条数据
0
>>> r['test']='OK!'

>>> r.save()   #强行把数据库保存到硬盘。保存时阻塞
True

--------------------------------

>>> r.flushdb()   #删除当前数据库的所有数据
True

 >>> a = r.get('chang')
>>> a    # 因为是Noen对象,什么也不显示!
>>> dir(a)  
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

>>> r.exists('chang')  #看是否存在这个键值
False

>>> r.keys()   # 列出所有键值。(这时候已经存了4个了)
['aaa', 'test', 'bbb', 'key1']

 

import redis
 
r = redis.Redis(host=’localhost’, port=6379, db=0)
 
r['test'] = ‘test’ #或者可以r.set(‘test’, ‘test’) 设置key
 
r.get(‘test’)  #获取test的值
 
r.delete(‘test’) #删除这个key
 
r.flushdb() #清空数据库
 
r.keys() #列出所有key
 
r.exists(‘test’) #检测这个key是否存在
 
r.dbsize() #数据库中多少个条数

附注A:

来看一下redis.Redis的 init() 函数定义:

 __init__(self, host='localhost', port=6379, db=0, password=None, socket_timeout=None, connection_pool=None, charset='utf-
8', errors='strict', decode_responses=False, unix_socket_path=None)

最新的redis 2.6.0加入了连接池,具体用法可以看作者博客。

 

 附注B:

其他命令API,请参照redis-Python作者的博客,写的挺清楚了:

https://github.com/andymccurdy/redis-py


3.redisco

redisco:

1)纯pyhton开发而成,你可以直接看它的源码(github地址:https://github.com/iamteem/redisco).

2) 带有redis的所有功能,因为它是基于redis这个官方的库上开发而成的.

3) 可以以django自带orm的方式将数据存入redis,并且提供了大多数和django的orm相同的查询功能.



其实我主要就是要介绍上面的第三点,redisco的 model(django里也叫着名字)类,它提供的这种能让数据以类似python内部的dict或者class的形式存储到redis里,这样我们对 redis的使用就接近nosql数据库了(因为redis自带持久化存储的功能)。


手把手教程范例教程开始:


创建一个你要存进redis的模型,你可以理解为是mysql里的表,需要继承models.Model类


Python代码   收藏代码
  1. from redisco import models  
  2. class Person(models.Model):  
  3.     name = models.Attribute(required=True)  
  4.     created_at = models.DateTimeField(auto_now_add=True)  
  5.     fave_colors = models.ListField(str)  
 

类里面支持的所有数据类型如下:

 


Model Attributes

Attribute Stores unicode strings. If used for large bodies of text, turn indexing of this field off by setting indexed=True. IntegerField Stores an int. Ints are stringified using unicode() before saving to Redis. Counter An IntegerField that can only be accessed via Model.incr and Model.decr. DateTimeField Can store a DateTime object. Saved in the Redis store as a float. DateField Can store a Date object. Saved in Redis as a float. FloatField Can store floats. BooleanField Can store bools. Saved in Redis as 1's and 0's. ReferenceField 可以引用其他的model.Model类,比如可以在一个通讯录类里增加一个字段它的类型是人物这个类他们都继承model.Model类但可以互相引用这样你就可以直接通过 通讯录.人物这样的方式调用(之后的文章会详细介绍) ListField 列表类型,使用跟python的list一样可以将 python里的unicode, int, float和其他redisco.model类放进去 生成一个Person类的数据
 >>person = Person(name="hupu")

   因为name是必填字段所以必须要给


  然后 调用save方法就存储到redis里去了。


>>person.save()
True

返回True就是成功了。



查询刚刚存进去的数据,跟django的orm真的很像

>>conchita = Person.objects.filter(name='hupu')[0]


查询所有的Person

>> all_person = Person.objects.all()


查询age大于某5岁


>> all_person = Person.objects.zfilter(age__gt=5)            小于 就是 字段名__lt 范围 就是 字段名__in=(0,5)


查询范围的都是一个list别忘了[0] 来获得一个结果


最后提一点,redisco.model.Model类存储数据时,对于除了Counter类型以外的所有类型字段有更改比如 person.age = 5 将年龄改为5 都要调用person.save()方法才能更改成功。

 

 

 

 

更多的功能可以看它的测试代码里的例子https://github.com/iamteem/redisco/blob/master/tests/models.py 和 https://github.com/iamteem/redisco  首页的文档。

4.test

在Python下一般使用redis-py, 或者在此基础上的redisco;

测试环境:

在100Mb/s 局域网

服务器: redis 2.4 rc8/rhel6.0

客户端:Python2.7.2/Win7

01	importdatetime
02	 
03	deftest1(string):
04	    importredis
05	    r=redis.StrictRedis(host='211.69.*', port=6379, db=1)
06	    now=datetime.datetime.now()
07	    foriinrange(0,10000):
08	        r.set(i, string)
09	    printdatetime.datetime.now()-now   
10	 
11	deftest2(string):
12	    importredisco
13	    fromredisco.containersimportHash,List,SortedSet,Set
14	    r=redisco.connection_setup(host='211.69.*', port=6379, db=1)
15	    h=Hash("h")
16	    now=datetime.datetime.now()
17	    foriinrange(0,10000):
18	        h[i]=string
19	    printdatetime.datetime.now()-now 
20	     
21	if __name__=="__main__":
22	    string="0"
23	    test1(string)
24	    test2(string)


结果:CPU不是瓶颈,大约1000写操作/s,比传输中的10W差的远了,看来网络IO是不小的瓶颈。而且不在于传输的数据量,而在于操作次数


redis配置

下面是抄过来的配置解释:

redis.conf配置选项如下:


daemonize 是否以后台进程运行,默认为no
pidfile 如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid
bind 绑定主机IP,默认值为127.0.0.1(注释)
port 监听端口,默认为6379
timeout 超时时间,默认为300(秒)
loglevel 日志记录等级,有4个可选值,debug,verbose(默认值),notice,warning
logfile 日志记录方式,默认值为stdout
databases 可用数据库数,默认值为16,默认数据库为0
save <seconds> <changes> 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
save 900 1

900秒(15分钟)内至少有1个key被改变
save 300 10300秒(5分钟)内至少有300个key被改变
save 60 1000060秒内至少有10000个key被改变
rdbcompression 存储至本地数据库时是否压缩数据,默认为yes
dbfilename 本地数据库文件名,默认值为dump.rdb
dir 本地数据库存放路径,默认值为 ./
slaveof <masterip> <masterport> 当本机为从服务时,设置主服务的IP及端口(注释)
masterauth <master-password> 当本机为从服务时,设置主服务的连接密码(注释)
requirepass 连接密码(注释)
maxclients 最大客户端连接数,默认不限制(注释)
maxmemory <bytes> 设置最大内存,达到最大内存设置后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,任到达最大内存设置,将无法再进行写入操作。(注释)
appendonly 是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认值为no
appendfilename 更新日志文件名,默认值为appendonly.aof(注释)
appendfsync 更新日志条件,共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次(默认值)。
vm-enabled 是否使用虚拟内存,默认值为no
vm-swap-file 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-max-memory 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0。

#当dump.rdb数据库的时候是否压缩数据对象
rdbcompression yes
#dump数据库的数据保存的文件名
dbfilename dump.rdb
#Redis的工作目录
dir /var/lib/redis/
###########Replication #####################
#Redis的复制配置
# slaveof <masterip> <masterport>
# masterauth <master-password>

############## SECURITY ###########
# requirepass foobared

############### LIMITS ##############
#最大客户端连接数
# maxclients 128
#最大内存使用率
# maxmemory <bytes>

########## APPEND ONLY FILE MODE #########
#是否开启日志功能
appendonly no
# 刷新日志到disk的规则
# appendfsync always
appendfsync everysec
# appendfsync no
################ VIRTUAL MEMORY ###########
#是否开启VM功能
vm-enabled no
# vm-enabled yes
vm-swap-file logs/redis.swap
vm-max-memory 0
vm-page-size 32
vm-pages 134217728
vm-max-threads 4
############# ADVANCED CONFIG ###############
glueoutputbuf yes
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
#是否重置Hash表
activerehashing yes

Redis官方文档对VM的使用提出了一些建议: 当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大. 当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value. 最好使用linux ext3 等对稀疏文件支持比较好的文件系统保存你的swap文件. vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数.如果设置为0,那么所有对swap文件的操作都 是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.




你可能感兴趣的:(redis,python,redis-py,redisco)