Redis学习笔记

2013-12-30 02:36:51

Redis:常用于数据库、缓存、队列系统等

Redis源自意大利Salvatore Sanfilippo的个人项目,2009年开源,2010年被VMware资助,托管在github上。


第一章 概述

Redis是一个字典结构的存储服务器:提供字典,用hash方式快速获得数据

1.集合数据类型,可以直接做交并集等运算

2.Redis数据库中的所有数据都存储在内存中,普通的PC机,1s内读取10万个键值。

3.TTL:Time To Live

4.可以限定数据最大内存空间,达到限制后按照规则自动淘汰。

5.与memcached相比,Redis的特点:支持持久化,丰富的数据类型


关于队列支持???

Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易地实现一个高性能的优先级队列。

Redis还支持“发布、订阅”的消息模式???



第二章 安装与实例介绍

1.redis-server与redis-cli

redis-server —port 6380//默认6379端口

2.可以设置开机自动启动

3.停止用redis-cli SHUTDOWN


4.一个Redis实例提供了多个用来存储数据的字典。每个字典都可以当做一个独立的数据库。

默认支持16个数据库,以配置databases参数来修改这一数字。

每个数据库对外都是以0开始的递增数字命名。在cli中用命令 SELECT number来切换到响应的数据库。

—客户端与Redis建立连接后会自动选择0号数据库

--不支持自定义数据库的名字!

—不支持为每个数据库设置密码

—多个数据库之间不是完全隔离,通过FLUSHALL命令可以清空所有数据库

所以,不同应用应该使用不同的redis实例。

redis-cli只是连接了一个redis实例服务

一个空的redis实例占用内存只有1MB左右。


第三章 入门 ——五大数据类型

一、.通用命令:

 KEYS pattern

 SET key value

 GET key

 EXISTS key  存在返回数字1,否则返回0 

 TYPE key

 DEL key

二、string字符串

基本数据类型,键值存储最大容量512MB。

字符串命令:

对数字字符串,递增INCR命令是原子操作,常用作统计访问量等,设置文章id号等。

INCRBY key increment

DECR key

DECRBY key decrement

INCRBYFLOAT key increment

APPEND key value——向尾部追加

STRLEN key

MSET k1 v1 k2 v2 k3 v3

MGET k1 k3

字符串里如果有空格用.代替,否则需要加双引号!

位操作:GETBIT key offset    SETBIT key offset value

三、hash散列类型

不用一次性全改属性,快速修改和获取,同时去冗余存储删除

字段值只能是字符串,一个hash键可以包括2^32-1个字段

hash命令:

HSET key field value

HGET key field

HMSET key field value field value …

HMGET key field field …

HGETALL key  获得全部属性


EXISTS key field

HSETNX key field value——如果不存在,则赋值。避免了HEXISTS和HSET两个命令之间的竞争,即多线程同步问题

INCRBY key field increment


HDEL key field field ...


HKEYS key

HVALS key


HLEN key 获取字段数量

四、列表类型

内部使用双向链表实现,两端插入删除比较快

list命令:

LPUSH key value value…

RPUSH key value value…

LPOP key

RPOP key


LLEN key


LRANGE key start stop

LRANGE key 0 -1——列出所有元素


LREM key count value


例子:存放所有评论:

$serializedComment = serialize($author,$email,$time,$content)

LPUSH post:42:comments, $serializedComment


LINDEX key index       获取索引元素

LSET key index value  设置索引元素


LTRIM key start end 只保留列表指定片段

LTRIM与LPUSH命令组合使用来限制元素的数量,比如只保存最近100条LOG

LPUSH logs $newlog

LTRIM logs 0 99

INSERT key BEFORE|AFTER pivot value 将value插入到pivot前面或者后面

RPOPLPUSH source destination从source列表右边弹出,进入des列表左边

五、set集合

内部是使用值为空的hash table散列表实现的

SET命令:

SADD  key member

SREM key member


SMEMBERS key获得集合中所有的元素


SISMEMBER  key member判断是否存在集合中


SDIFF A B …A-B

SINTER key key … A*B 交集

SUNION key key … A+B 并集


SET其他命令:

SCARD key 获得集合中元素个数

SDIFFSTORE destination key key…

sinterstore

SUNIONSTORE类似

SRANDMEMBER key随机获得一个元素

SPOP key随机选择一个元素弹出

六、sorted set有序集合

内部使用散列表和跳跃表实现,读取中间部分的数据速度为OlogN

调整位置也比列表方便(比如像更改发表日期)


sorted set命令:

ZADDR key score member [score member …]

ZSCORE key member

ZRANGE key start stop [WITHSCORES]

ZREVRANGE key start stop [WITHSCORES]

ZRANGEBYSCORE key min max [WITHSCORES]

INCRBY key increment member


第四章 进阶


一、事务

MUTI

EXEC——一个事务中,一条指令运行错误,其他指令仍然运行!!由此造成的后果redis不负责!!!

WATCH


二、有效期

EXPIRE

TTL

限制访问频率

缓存: maxmemory设置大小,

maxmemory-policy设置缓存替换策略,比如allkeys-lru

三、排序

(一)有序集合

.有序集合常用场景是大数据排序:ZINTERSTORE ZUNIONSTORE

注意:只提供交并操作+存储命令,而没有单独的交并操作命令

(二)SORT命令

可以对列表、集合、有序集合三种类型键进行排序

注意:

1)对有序集合排序时,只对元素自身排序,而非元素分数

2)ALPHA参数


1.DESC参数


2.LIMIT OFFSET COUNT


3.BY参数

支持字符串类型和散列表类型的键


4.GET参数

支持字符串类型和散列表类型的键

SORT tag:ruby:posts BY post:*->time DESC GET post:*->title

GET #会返回元素本身的值


5.STORE参数

把结果存储到某键,而不是只显示

保存结果为列表类型


6.性能优化

SORT的时间复杂度为n+mlogm,其中n为待排序元素个数,m表示要返回的元素个数


四、消息通知

1.任务队列

生产者-消费者

好处:解耦和,易扩展:如分布式扩展

2.REDIS实现队列

生产者LPUSH,消费者RPOP,BRPOP

同时还有RPUSH ,LPOP, BLPOP

3.优先级队列

利用BRPOP 多个列表即可实现

4.发布者和订阅者

PUBLISH channel.1 hi

SUBSCRIBE channel.1

5.按规则订阅

SUBSCRIBE channel.?*


五、管道

客户端与Redis使用TCP协议链接,命令较多时往返时间可能影响性能!

管道减少了客户端与Redis的通信次数!降低延时


六、节省空间

1.精简键名和键值!

2.存储类型


第五章 实践

5.1 PHP与Redis

Redis推荐的PHP客户端是Predis和phpredis,前者是php库,后者是C语言写的PHP扩展。后者性能在大批量命令时,优于前者(实践中可以查看)。

实际应用中开销更多在网络传输上,单纯注重客户端性能意义不大。


Predis要求PHP 5.3.


1.实例化后直接调用参数

$redis->get(‘foo’);

$r->lpush(’numbers’,’1’,’2’,’3');


2.简便用法

(1)MGET/MSET

$userName = array(‘user:1:name’ => ’Tom’,’user:2:name’=>’Jack’);

$r->mset($userName);


相当于

$r->mset(‘user:1:name’,’Tom’,’user:2:name’,’Jack’);


php包含:索引数组,关联数组,多维数组

array_keys(array,value,strict)函数取关联数组键值为value的键名,返回为一个索引数组。

$user=array_keys($userName);

$r->mget($user);

 (2)HMSET/HMGET/HGETALL

$user1=array(’name’=>’Tom’,’age’=>’32’);

$r->hmset(‘user:1’,$user1);

$user=$r->hgetall(‘user:1’);//返回为关联数组

echo $user[‘name’];

(3)LPUSH/SADD/ZADD

$items=array(‘a’,’b’);

$redis->lpush(‘list’,$items);//<==> $redis->lpush(‘list’,’a’,’b’);

$redis->sadd(’set’,$items);//$redis->sadd(‘set’,’a,’b’);


$itemScore=array(’Tom’=>’100’,’Jack’=>’89’);

$redis->zadd(‘zset’,$itemScore);//redis->zadd(‘zset’,’100’,’Tom’,’89’,’Jack’);

(4)SORT

$redis->sort(‘my list’,array(

‘by’=>’weight_*’,

’limit’=> array(0,10),

‘get’ => array(‘value_*’,’#’),

‘sort’=>’asc’,

‘alpha’=>true,

‘store’=>’result’

));


实践:

注册、登录。bcrypt与crypt函数

——设置userid与email对应的hashes:userid.to.email

忘记密码:

1.访问频率限制—— 这里是基于邮箱的,基于IP的代码类似!

$keyName=“rate.limiting:{$email}”;

$now=time();

if($redis->llen($keyName)<10){

$redis->lpush($keyName,$now)

}else{

$time=$redis->lindex($keyName,-1);

if($now-$time)<60{

echo’visit limit 10 times!’;

exit;

}else{

$redis->lpush($keyName,$now);

$redis->ltrim($keyName,0,9);

}

}

2.发送修改密码邮件

发送验证码后,要把用户的邮箱地址存入名为retrieve.password.code



第7章 管理

一、持久化

1.RDB文件

Redis默认文件存储在dump.rdb文件。配置dir与dbfilename两个参数改变配置。

SAVE和BGSAVE命令可以执行快照

1GB的rdb文件载入大概要20到30秒

2.AOF方式

开启后每次更新都写

二、复制

主从数据库自动同步

三、安全

redis应该工作在可信的工作环境下!可以设置密码

四、通信协议

客户端与redis之间的通信

五、管理工具

1.耗时命令日志 SLOWLOG

2.监控MONITOR

3.phpRedisAdmin 类似于phpmyadmin的界面工具

4.Rdbtools——快照文件解析器