redis笔记
1.redis是什么?
redis是开源,BSD许可,高级的key-value存储系统. 可以用来存储字符串,哈希结构,链表,集合,因此,常用来提供数据结构服务。
2.redis和memcache相比,redis的独特之处
1.redis除了可以做缓存,也可以做存储,这得益于redis独特的持久化的功能,memcache没有持久化,一般只用来做缓存。
2.数据结构问题,memcahce可以存储的数据结构非常单一,只有字符串一种,而redis可以存储的结构很丰富,有字符串,链表,集合,哈希
3.持久缓存问题,redis可以持久缓存,memcache一般最大缓存时间是30天,单个键的最大为1M,而redis可以达到1G,
4.机制问题,redis是单线程原子性操作,相当于天然锁机制,memcache是多线程机制,
3.redis下载安装问题
1:官方站点: redis.io 下载最新版或者最新stable版
2:解压源码并进入目录
3: 不用configure
4: 直接make
(如果是32位机器 make 32bit)
注:易碰到的问题,时间错误.原因: 源码是官方configure过的,但官方configure时,生成的文件有时间戳信息,Make只能发生在configure之后,如果你的虚拟机的时间不对,比如说是2012年解决: date -s ‘yyyy-mm-dd hh:mm:ss’ 重写时间再 clock -w 写入cmos
5: 安装到指定的目录,比如 /usr/local/redis,make PREFIX=/usr/local/redis install
注: PREFIX要大写
make install之后,得到如下几个文件
redis-benchmark 性能测试工具
redis-check-aof 日志文件检测工(比如断电造成日志损坏,可以检测并修复)
redis-check-dump 快照文件检测工具,效果类上
redis-cli 客户端
redis-server 服务端
让redis以后台进程的形式运行
编辑conf配置文件,修改如下内容;
daemonize yes
Redis对于key的操作
$red=RedisHelper::getRedisHandle(); //删除, $red->delete('key1','key2');//没有返回值 $red->del('key1','key2'); //返回删除key的数量 //重命名 $red->rename('oldkey','newkey'); //命令行或者终端操作 move key dbindex redis 127.0.0.1:6379[1]> select 2 OK redis 127.0.0.1:6379[2]> keys * (empty list or set) redis 127.0.0.1:6379[2]> select 0 OK redis 127.0.0.1:6379> keys * 1) "name" 2) "cc" 3) "a" 4) "b" redis 127.0.0.1:6379> move cc 2 (integer) 1 redis 127.0.0.1:6379> select 2 OK redis 127.0.0.1:6379[2]> keys * 1) "cc" redis 127.0.0.1:6379[2]> get cc "3"
keys pattern 查询符合要求的key 在redis里,允许模糊查询key 有3个通配符 *, ? ,[] *: 通配任意多个字符 ?: 通配单个字符 []: 通配括号内的某1个字符 $red->keys('*');//返回全部的key,以数组形式 $red->randomKey();//随机返回一个key $red->exists('aaaaaa');//判断key是否存在,返回true/false $red->type(key)//返回key的类型 $red->ttl('tian');//得到键的生存周期,-1代表永久 -2代表没有或者已经删除 不过期的key,都返回-1 Redis2.8中,对于不存在的key,返回-2 $red->expire('key',5),//设置key的过期时间,秒 $red->pExpire(key,5)//设置key的过期时间,毫秒 $red->persist('key') //把key设置为永久
Redis字符串类型的操作
$red->set(key,value);--->默认是永久的,ttl-->-1 $red->setnx(key,value);--->只有当key不存在的时候执行,如果key存在返回false-->单线程机制,天然锁 $red->setex(key,ttl,value) $red->mset(array)-->一次性设置多个值 $red->get(key)-->得到key的值 $red->mget(array)-->一次性获取多个key的值 $red->append(key,value)-->把value追加到key的原值上 $red->getRange(key,start,stop)-->得到key的值,从start到stop,下标0 $red->incr(key)-->指定的key的值加1,并返回加1后的值,如果key不存在,默认为01:不存在的key当成0,再incr操作2: 范围为64有符号 $red->incrby(key,number)
关于redis的bitmap(setbit)操作:
场景: 1亿个用户, 每个用户 登陆/做任意操作 ,记为 今天活跃,否则记为不活跃
每周评出: 有奖活跃用户: 连续7天活动
每月评,等等..
首先这么大的用户量以及信息,防止数据表里肯定不现实,海量数据还要进行聚合运算(很慢),如果非要详细的记录信息,海量信息可以考虑mongo,
需求只是判断用户是否活跃(0不活跃,1活跃),用bit运算非常合适。
如果用户登录/或者操作-->活跃用户记为1-->今日的用户登录-->假设用户ID=15,-->$redis->setbit('今天日期','用户ID',1),也就是说,在今天,id=15的用户登录了,则在以今日日期为key的bit里,第15位的偏移量置为1(表示活跃),其他的0-14为自动填充为0,
如果想要统计今日的活跃用户数,$redis->bitCount('今天日期') --->会把以今天日期为key的value中所有为1的个数统计出来。
具体看某一个用户是否登录,$redis->getBit('今天日期',userid);
假如需求连续7天登录的用户,把每天的value取出来做按位与操作,比如(16号:01011,17号:10111....)执行与操作就可以将2天都活跃用户统计出来
bitmap的方式运算速度很快,非常节省内存。
Redis链表类型的操作
$red->lpush(key,value)-->把值插入到链接头部 $red->rpop(key)-->返回并删除链表尾元素 rpush,lpop: 不解释 $red->lrange(key,start,stop) 返回链表中[start ,stop]中的元素,左数从0开始,右数从-1开始 $red->lrem(key,value,count) 作用: 从key链表中删除 value值 注: 删除count的绝对值个value后结束 Count>0 从表头删除 Count<0 从表尾删除 $red->ltrim(key,start,stop)-->剪切key对应的链接,切[start,stop]一段,并把该段重新赋给key $red->lIndex(key,index)---> 返回index索引上的值, $red->llen(key)--->返回链表的长度 $red->rpoplpush(source,dest);-->作用: 把source的尾部拿出,放在dest的头部, 并返回 该单元值 $red->brpop()--->作用:等待弹出key的尾/头元素, Timeout为等待超时时间 如果timeout为0,则一直等待 场景: 长轮询Ajax,在线聊天时,能够用到
Redis set类型的操作
集合的性质: 唯一性,无序性,确定性,
注: 在string和link的命令中,可以通过range 来访问string中的某几个字符或某几个元素
但,因为集合的无序性,无法通过下标或范围来访问部分元素
$red->sAdd('tianye123','ty1'); //往集合key中增加元素 $red->sRem('tianye123','ty1','ty3')//忽略不存在的元素后,返回真正删除掉的元素的个数 $red->sPop('tianye123')//返回并删除集合中key中1个随机元素,随机--体现了无序性 $red->sRandMember('tianye123') //返回集合中随机的一个元素,但是不删除,pop会删除 $red->sIsMember('tianye123','ty2')//判断一个value是不是在集合中,返回true/false $red->sMembers('tianye123') //返回集合中所有的元素 $red->sCard('tianye123') //返回集合中所有的元素个数 $red->sMove('source','des')//把source中的value删除,并添加到dest集合中 $red->sInter('s1','s2','s3') //求出key1 key2 key3 三个集合中的交集,并返回 $red->sInterStore('aa2','s1','s2') //求出s1,s2的交集并添加到集合aa2中 $red->sUnion('s1','s2') //求出s1,s2的并集 $red->sDiff('s2','s1') // 求s2和s1的差集,以第一个key为准
Redis 有序集合类型的操作
$red->zAdd('today',1,'ty1',2,'ty2') //添加元素,key,score1,value1,score2,vale2 $red->zRem('today','ty1','ty2') //删除集合中的元素,key,value1,value2,返回删除元素的个数 $red->zRemRangeByScore('today',2,3) //删除范围元素通过权重 key , start,end 返回删除元素的个数 $red->zRemRangeByRank('today',0,2)// 删除范围元素通过排名key,start,end 返回删除元素的个数 $red->zRank('today','ty3') // 查看value在有序集合里的排名,从0开始(升序),没有value返回false $red->zRevRank('today','ty3') //看value在有序集合里的排名,从0开始(降序),没有value返回false ($red->zRange('today',0,-1)//把集合排序后,返回名次[start,stop]的元素 $red->zRange('today',0,-1,true) //把集合排序后,返回名次[start,stop]的元素,true是把score也打印出来 同理,$red->zRevRange ->是倒叙排列 $red->zRangeByScore('today',2,3,[])//集合(升续)排序后,取score在[min,max]内的元素,可以有options ,limit offset n $red->zCard('today')//返回集合中元素的个数 $red->zCount('today',10,15) //返回按照score min,max 之间元素的个数 $red->zInter(dest,[key1,key2],[1,1],'max|min|sum');//求key1,key2的交集,聚合方法用: sum |min|max 聚合的结果,保存在dest集合内 注意: weights ,aggregate如何理解? 答: 如果有交集, 交集元素又有socre,score怎么处理? Aggregate sum->score相加 , min 求最小score, max 最大score 另: 可以通过weigth设置不同key的权重, 交集时,socre * weights
Redis 哈希类型的操作
$red->hSet('tianye','age',15) //hset key field value 作用: 把key中 filed域的值设为value 注:如果没有field域,直接添加,如果有,则覆盖原field域的值 $red->hMset('tianye',['age'=>15,'xingbie'=>1]) 设置field1->N 个域, 对应的值是value1->N (对应PHP理解为 $key = array(file1=>value1, field2=>value2 ....fieldN=>valueN)) $red->hGet('tianye','age') //hget key field 作用: 返回key中field域的值 $red->hMGet('tianye',['age','xingbie','t'])//返回key中field1 field2 fieldN域的值 $red->hGetAll('tianye') // hgetall key 作用:返回key中,所有域与其值 $red->hDel('tianye','age')//删除key中 field域 $red->hLen('tianye') //返回key中元素的数量 $red->hExists('tianye','xingbie')//判断key中有没有field域 $red->hIncrBy('tianye','weight',20)//是把key中的field域的值增长整型值value $red->hIncrByFloat //同理增加浮点数 $red->hKeys('tianye') //返回key中所有的field $red->hVals('tianye') //返回key中所有的value
Redis 事务的操作
Redis支持简单的事务
注: rollback与discard 的区别
如果已经成功执行了2条语句, 第3条语句出错.
Rollback后,前2条的语句影响消失.
Discard只是结束本次事务,前2条语句造成的影响仍然还在
Redis 持久化
Redis的持久化有2种方式 1快照 2是日志
Rdb快照的配置选项
save 900 1 // 900内,有1条写入,则产生快照
save 300 1000 // 如果300秒内有1000次写入,则产生快照
save 60 10000 // 如果60秒内有10000次写入,则产生快照
Aof 的配置
appendonly no # 是否打开 aof日志功能
appendfsync always # 每1个命令,都立即同步到aof. 安全,速度慢
appendfsync everysec # 折衷方案,每秒写1次
appendfsync no # 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof. 同步频率低,速度快,