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
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']
附注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类
- from redisco import models
- class Person(models.Model):
- name = models.Attribute(required=True)
- created_at = models.DateTimeField(auto_now_add=True)
- fave_colors = models.ListField(str)
类里面支持的所有数据类型如下:
Model Attributes
>>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 | 01 importdatetime |
02 | 02 |
03 | 03 deftest1(string): |
04 | 04 importredis |
05 | 05 r=redis.StrictRedis(host='211.69.*', port=6379, db=1) |
06 | 06 now=datetime.datetime.now() |
07 | 07 foriinrange(0,10000): |
08 | 08 r.set(i, string) |
09 | 09 printdatetime.datetime.now()-now |
10 | 10 |
11 | 11 deftest2(string): |
12 | 12 importredisco |
13 | 13 fromredisco.containersimportHash,List,SortedSet,Set |
14 | 14 r=redisco.connection_setup(host='211.69.*', port=6379, db=1) |
15 | 15 h=Hash("h") |
16 | 16 now=datetime.datetime.now() |
17 | 17 foriinrange(0,10000): |
18 | 18 h[i]=string |
19 | 19 printdatetime.datetime.now()-now |
20 | 20 |
21 | 21 if __name__=="__main__": |
22 | 22 string="0" |
23 | 23 test1(string) |
24 | 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
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数据库的时候是否压缩数据对象
#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文件的操作都 是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.