redis初识

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在生存时间相关,也就是在没有失效前存储的大小

 

### Redis 入门教程初学者指南 Redis 是一种高性能的键对存储系统,广泛应用于缓存、消息队列以及实时数据分析等领域。作为一种开源软件,Redis 支持多种数据结构操作并提供丰富的功能特性。 #### 1. Redis 的基本概念 Redis 不仅是一个简单的键存储工具,还提供了字符串(String)、哈希(Hash)、列表(List)、集合(Set) 和有序集合(Sorted Set)等多种复杂的数据结构支持[^2]。这些数据结构使得开发者能够轻松实现各种复杂的业务逻辑需求。 #### 2. 安装与环境配置 为了开始使用 Redis,需要先完成其安装过程。通常情况下,在 Linux 或 macOS 平台上可以通过包管理器快速部署;而在 Windows 上则推荐采用 Docker 方式来运行容器化的 Redis 实例[^3]。 ```bash # 使用 apt-get (适用于 Ubuntu/Debian 系统) sudo apt update && sudo apt install redis-server # 启动服务 redis-server --daemonize yes ``` #### 3. 数据结构解析 以下是几种主要的数据类型及其用途简介: - **字符串(String)**: 存储单个或者作为计数器使用。 ```lua SET mykey "Hello" GET mykey INCR counter_key ``` - **哈希(Hash)**: 表示对象字段与其对应得映射关系。 ```lua HMSET user:1000 username "Alice" age 30 HGETALL user:1000 ``` - **列表(List)**: 双端链表形式用于 FIFO/LIFO 队列模拟。 ```lua LPUSH queue item1 RPUSH queue item2 LPOP queue RPOP queue ``` - **集合(Set)& 有序集合(Sorted Set)**: 去重后的无序集合或带分数权重排序版。 ```lua SADD unique_items apple banana orange SMEMBERS unique_items ZADD leaderboard 95 alice 87 bob 76 charlie ZRANGE leaderboard 0 -1 WITHSCORES ``` #### 4. 持久化机制 Redis 提供两种持久化方式——RDB 快照文件和 AOF 日志记录。前者定期保存当前状态至磁盘,后者则是每次写命令追加到日志中以便恢复时重新执行所有变更[^2]^。 #### 5. 应用场景举例 一些常见的 Redis 使用场景包括但不限于网站访问统计、会话管理、购物车暂存等功能模块开发过程中发挥重要作用. --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值