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——快照文件解析器