设为首页 收藏本站
查看: 921|回复: 0

[经验分享] redis初识

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-12-17 08:38:17 | 显示全部楼层 |阅读模式
  Redis相对Memcached来说功能和特性上的优势已经很明显了。
   
  而对于性能,Redis作者的说法是平均到单个核上的性能,在单条数据不大的情况下Redis更好。为什么这么说呢,理由就是Redis是单线程运行的。
  因为是单线程运行,所以和Memcached的多线程相比,整体性能肯定会偏低。
  因为是单线程运行,所以IO是串行化的,网络IO和内存IO,因此当单条数据太大时,由于需要等待一个命令的所有IO完成才能进行后续的命令,所以性能会受影响。
   
   
  而就内存使用上来说,目前Redis结合了tcmalloc和jemalloc两个内存分配器,基本上和Memcached不相伯仲。如果是简单且有规律的key value存储,那么用Redis的hash结构来做,内存使用上会惊人的变小,优势是很明显的。
   
  1.源码编译安装后,启动程序是在源码包中的src目录中的redis-server,其他中开启命名中需要加上redis对应的配置文件
    举例,redis安装源码包(也就是安装目录):   /usr/local/src/redis-2.8.9
          redis配置文件在(一般是在安装目录下):/usr/local/src/redis-2.8.9/redis.conf
  启动redis的命令:进入到/usr/local/src/redis-2.8.9/src/,使用 ./redis-server /usr/local/src/redis-2.8.9/redis.conf
   
  2.安装后,redis-cli命令行操作工具会被自动安装,使用cli程序进入redis服务器,其中cli也是在安装目录的src目录下,进入到src目录后直接使用命令:redis-cli  即可,
   2.1 设置密码登陆:在redis.conf配置文件中,添加requirepass 密码,重启redis即可
  2.2 设置密码后的登陆有2中方式:在使用redis-cli时候,后面添加 -a 密码, 或者进入redis 之后,使用auth 密码 来获取权限 
  redis远程登录:redis-cli -h ip地址 -p 端口 -a 密码(如果没有密码则不用)
   
  3.key值中不能存在空格和换行符号“\n”,因为这两个符号是redis的特殊符号
   
  4. string类型:二进制安全,一般用来存储静态文件、图片、视频文件等,string支持incr和decr的操作(增减操作),可用于统计访问次数等
   
  5. list类型:双向链表,可用于实现“消息队列”的功能,rpush把数据插入队尾,lpop从队头取出数据,例如在大并发量时候,可以考虑使用list实现排队功能来访问操作数据库,从而减轻db的压力
   
  6. set类型:无序集合,类似数组,一般可用于记录不重复的数据,例如注册用户数据不能重复,通过记录到set类型,又或者是记录一些操作
   
  7. 有序set类型
   
  8. hash类型:适用于存储对象
   
   
  9.支持事务,使用multi命令启动事务,exec来执行事务,使用discard删除一个事务,虽然支持了一组操作命令的事务,但是在事务某个步骤发生错误并没有提供回滚的机制
  phperdis扩展中事务的操作代码如下:
  $ret = $redis->multi()->set('key1', 'val1')->get('key1')->set('key2', 'val2')->get('key2')->exec();
  
  在事务中添加监控的条件:watch函数,监控某一个键值对应的值,如果该值发生变化则接下来的事务都终止运行,如下:
  $ret = $redis->multi()->set('key1', 'val1')->watch('key1')->set('key1', 'val1_1')->set('key2', 'val2')->get('key2')->exec();
  
  //如果key1是因设置的过期时间到了而被自动删除的,则不会触发到watch
   
   //multi函数返回一个redis对象,并且进入multi-model模式,以后调用的方法都会返回同一个redis对象,直到exec方法调用以后,过程中执行的每个结果都会存入数组中作为返回
   
  10. redis的主从复制设置:
  1、先在主reids设置密码认证,参看上面的 2 
  2、在从redis的配置文件中添加slaveof 和 masterauth这两个参数
  例如:slaveof 192.168.209.128 6379
  masterauth ajia123
  重启从redis,注意,需要设置防火墙允许访问redis的端口,这里默认的是6379  
                   
  11.redis停止:/usr/local/src/redis-2.8.9/src/redis-cli  shutdown (如果设置了密码认证,则需要加上 -a 密码),也可以使用kill redis的进程号 的方式停止
   
  12. Redis数据存储
  redis 的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。
 
save seconds updates:在指定时间内,达到多少次更新操作时,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
 
appendonly yes/no:是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
 
appendfsyncno/always/everysec:no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。
 
   
  phpredis扩展中对于各种数据类型的常用操作:
   
  <?php
   
  $redis = new Redis();                     //记得开启redis
  $redis->connect("127.0.0.1", 6379);
  $redis->auth('ajia123');                  //如果redis设置了密码验证,需要该方法
   
   
  //字符串的操作 =======================================================
   
  $rel = $redis->set("key4", "wskey33");                   //赋值,成功则返回true 
  $rel = $redis->set( "key4", 'is ok', array( 'nx', ex=>'60' ) )  //效果与setnx+expire一致,但是为原子性操作,高并发可用
  $redis->expire("key4", 60);                                    //设置过期时间,这两语句等于setex函数
  $redis->setTimeout( "key4", 60 );                          //设置过期时间
  $redis->pexpire('key4', 60000)                              //pexpire以毫秒为单位设置过期时间,1秒=1000毫秒
  $redis->expireAt('key4', time() + 30);                    //设置过期时间,以时间戳的形式,  这里设置到距离当前时间30秒后过期
   
  $rel2 = $redis->setex("key1", 120, 'key1_value');         //赋值,同时设置过期时间 
   $tmp = $redis->persist('key1');                          //去除key的过期时间,设置成永不过期
   
  $rel3 = $redis->setnx("key1","again_key1_value");         //setnx也是赋值,但是它不允许对同一个重复赋值,如果一个key已经赋值了,则返回false
   
  $redis->mset( array("k1"=>"k1value", "k2"=>"k2value") );  //多个赋值
   
  $redis->append("k1", " and append");                      //如果键值存在值,则将新值添加在原有值的后面,如果键值不存在则等同于赋值
   
  $rel4 = $redis->exists("k3");                             //判断键值是否存在,存在返回true
   
  $redis->set("isInt",10);
  $redis->incr("isInt");                                    //对int类型的进行加1, 对应的有decr和decrBy
  $redis->incrBy("isInt", 10);                              //incrBy对int类型的key进行自定义加多少
   
   
  $lTime = $redis->ttl("key4");                             //如果设置了过期时间,ttl可以查看距离过期时间所剩的时间,以秒为单位
   
  $one = $redis->get("key4");                               //取值
  $keyArr = $redis->mget( array('k1', 'k2', 'k3') );        //多个取值,不存在的会返回false
   
  $redis->delete("key2","key1");                            //删值,多个用逗号隔开,也可以写成数组的形式:array("key1","key2");
  $randKey = $redis->randomKey();                           //随机返回一个key
   
  //队列操作 ============================================================
   
  //$redis->delete("theList");
  $len = $redis->llen("theListEx");
  $redis->lpush('theListEx', 'leftFirstValue'.$len);        //往名为theList的队列的头部插入元素leftFirstValue, 当如果队列不存在,会先创建再插入, 另外lpushx也是头部插入元素,但如果该队列并不存在,则不进行任何操作
   
  $redis->rpush('theListEx', 'rightFirstVlaue'.$len);       //往名为theList的队列的尾部插入元素rightFirstVlaue,另外rpushx...
  $redis->lpush('theList2Ex', 'll2Value'.$len);
   
  //echo $redis->llen("theListxx");                         //获取队列的元素个数
  //echo $redis->lsize("theList");                          //获取队列的元素个数
   
  $rel1 = $redis->lpop("theList");                          //获取队列头部第一个元素,并且删除
  $rel2 = $redis->rpop("theList");                          //获取队列尾部最后一个元素,并且删除
   
  $rel3 = $redis->blpop( array('theList', 'theList2'),30 ); //是lpop的阻塞版本,从左到右扫描多个队列(这里是theList和theList2两个队列),返回对第一个非空队列进行lpop操作的结果,如果所有的队列为空或不存在,阻塞30秒,如果设置为0则表示不阻塞;在阻塞时候,如果有其他客户端对这个操作中的多个队列中的任意队列进行push操作,该阻塞解除,如果超时了,则返回false
   
  $rel3 = $redis->blpop( 'theList', 'theList2', 30 );        //blpop的另一种写法
   
  $rel4 = $redis->brpop( array('theList', 'theList2'),30 );  //与lpop类似,但是进行的是rpop的操作
   
  $rel5 = $redis->lrange("theListEx", 0, -1);                //获取队列所有的元素,-1表示最后一个元素,-2表示倒数第二个元素,依次类推
   
  $rel6 = $redis->lget("theListEx", 100);                    //获取队列中坐标为100的元素,坐标从0开始,如果不存在则返回false, lindex也是该作用
   
  $redis->ltrim( 'theListEx',0,1 );                          //对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
   
  $rel7 = $redis->lrange("theListEx", 0, -1);
   
  $redis->lset( 'theListEx', 0, "ajia" );                    //给名称为theListEx的队列中index位置为0的元素赋值为ajia
  $rel8 = $redis->lget( 'theListEx', 0 );
   
  $redis->linsert("theListEx", Redis::BEFORE, "ajia", "xiaotou");  //向theListEx队列中ajia元素的‘前面’插入xiaotou元素,Redis::AFTER则表示元素后头
  $rel9 = $redis->lrange( 'theListEx', 0, -1 );
   
   
  $redis->lrem( 'theListEx', 'xiaotou', 0 );                 //删除队列中值为xiaotou的元素,第三个参数count:当为0的时候,表示删除所有,>0的话表示从头部开始匹配删除count个该元素, <0,则是从队尾匹配
   
  $rel10 = $redis->lrange( 'theListEx', 0, -1 );
   
   
   
  //set是一种无序集合,通过hashtable实现,其优点是能够快速查找元素是否存在,用于记录一些不能重复的数据
   
  $rel  = $redis->sadd( "s1", "firstSetValue" );        //向名为s1的set插入元素firstValue,如果该元素已经存在,则不重复插入,返回0
  $rel2 = $redis->sadd( "s1", "v2", "v3", "v4" );       //多个元素插入,已经存在的元素不会再插入,返回插入成功的个数
   
  $rel3 = $redis->srem( "s1", "v3", "v4", "sssss" );    //删除元素,返回删除成功的个数
   
  $redis->smembers( 's1' );                             //获取集合s1的所有元素
  $rel4 = $redis->sismember( 's1', 'v2ddd' );           //判断集合s1中是否含有某元素
  $rel6 = $redis->ssize('s2');                          //获取集合s1中的元素个数
   
  $redis->sadd('s2', 's2_value');
  $rel5 = $redis->smove( 's1', 's2', 'firstSetValue' ); //将s1中的firstSetValue元素迁移到s2集合中去
   
  $rel7 = $redis->srandmember( 's1' );                  //随机获取集合s2中的一个元素,不会删除该元素
  $rel  = $redis->spop('s1');                           //随机获取集合中的一个元素,并且将它从集合中暂时删去,而不是真正删去
   
  $rel2 = $redis->smembers("s1");
   
  $redis->sadd('s3', 'v1', 'v2', 'v3');
  $redis->sadd('s4', 'v2', 'v4', 'v3', 'v5');
   
  $rel = $redis->sinter( 's3', 's4' );                 //求交集, sinterstore( 's34', 's3', 's4' ),将s3和s4的交集存于集合s34中
  $rel = $redis->sunion( 's3', 's4' );                 //求并集
  $rel = $redis->sdiff( 's4', 's3' );                  //求集合s4中在集合s3中没有的元素,也就是求差集
   
   
   
  //有序集合store set =======================================================
   
  $rel = $redis->zadd( 'zs1', 0, 'z0', 1, 'z1', 8,'z8', 6, 'z6' );      //插入多个集合元素,其中z0的排序是0, z1的排序是1
  $rel = $redis->zrange( 'zs1', 0, 0 );                //获取第一个元素
  $rel = $redis->zrange( 'zs1', 0, -1 );               //获取所有的元素
  $rel = $redis->zrevrange('zs1', 0, -1);              //获取所有的元素,并且对其按照score递减来排序
   
  $rel = $redis->zrem('zs1', 'z1');                    //删除元素
   
  $rel = $redis->zadd('zs1', 22, '222', 22, '111');    //同一次zadd的操作,如果存在相同score的话,插入成功,也就是会存在相同score的元素,如果是不同的zadd操作,则新的操作会覆盖之前相同score的元素的值
   
  $rel = $redis->zrange( 'zs1', 0, -1 );
   
  $rel = $redis->zrangebyscore( 'zs1', 0, 10 );        //获取score在指定区间内的元素,例子中查找的是0 < score < 10的元素 
   
  //echo $redis->zscore("zs1", '222');                 //获取对应元素的score
  //echo $redis->zscore("zs1", '111');
   
  $rel = $redis->zrank("zs1", '111');                  //获取元素在集合中的排名,按照score的递增来排序后的排名,最小的score的排序是0,以此类推,zrevrank则是score递减排序后的排名
   
  $rel = $redis->zincrby( 'zs1', -1, 'z6' );           //修改元素的score,如果元素存在则将其score+第二个参数的值(负数表示相减),如果元素不存在则视为新增
   
   
   
  //hash类型:是每一个key对应一个hash表,该类型时适合存储对象
   
  $rel = $redis->hset("user:1", "id", '1000');                     //添加一个元素
  $rel2 = $redis->hsetnx( "user:1", 'id', '200' );           //先判断key是否存在,不存在才赋值,否则不做任何操作
  $redis->hmset("user:1", array( "name"=>"ajia", "sex"=>"boy" ));  //添加多个元素
   
  $rel = $redis->hget("user:1", "name");                           //获取一个元素
  $rel = $redis->hmget("user:1", array("id", "sex") );             //获取多个元素
   
  $rel = $redis->hgetall("user:1");                                //获取该hash中的所有key和value
   
  $rel = $redis->hlen("user:1");                                   //获取该hash的元素个数
   
  $redis->hdel("user:1", "sex");                                   //删除元素
   
  $rel = $redis->hkeys("user:1");                                  //获取该hash所有key
  $rel = $redis->hvals("user:1");                                  //获取该hash所有元素的值
   
  $rel = $redis->hexists("user:1", 'sex');                         //判断该hash中是否存在某个key
   
   
  //每个用户每分钟只能访问页面6次, 使用字符串类型
  $demo  = 'user:1:page';
  $limit = 6;
   
  $r->set( $demo, 1 );
  $r->expire( $demo, 35 );
   
  if( $r->exists( $demo ) && $r->get( $demo ) < $limit ){
      $r->incr($demo);
      echo $r->ttl( $demo );
  }else{
      exit( '每分钟每个用户只能访问100个页面' );
  }
   
  //每个用户每分钟只能访问页面6次, 使用有序集合类型
  $demo  = 'user:1:page';
  $limit = 6;
  $page  = "/index.php?p=123ggg";
   
  $r->multi()->zAdd( $demo, 1, $page )->expire( $demo, 120 )->exec();  //todo 开启事务保证expire能够无误被执行
   
  $num = $r->zscore( $demo, $page );
  if( $r->exists( $demo ) &&  $num < $limit ){
   
      $r->zIncrBy($demo, 1, $page);
      echo "剩余秒数:".$r->ttl( $demo );
      echo "<hr> 访问次数:".$num;
   
  }else{
      exit( "每分钟每个用户只能访问{$page}页面{$limit}次" );
  }
   
   
  ?>
   
  reids终端命令:
  1. 查看当前db的所有可以:keys *
  2. 清除所有的key:flushall
  3. 查看redis内存、key使用等情况:info
  4. 查看某个key的大小、值存储情况等:debug object 键名  ,其中serializedlength为值大大小
  5. 单key语句最大长度:
      键长度+值长度,单位为字节(B或bite),如果是hash类型,其值长度是hash中所有域的值的总和(1个     数字=4个字节、1个英文字母=1个字节、1个中文=2个字节)
      一个key的预计总大小跟该key在生存时间相关,也就是在没有失效前存储的大小
   

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-315336-1-1.html 上篇帖子: redis操作 下篇帖子: Redis初探01
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表