zoukankan      html  css  js  c++  java
  • redis详解

    reids使用场景:

    1.一般的数据缓存

    2.队列应用:非实时业务如发放积分或需要削峰降流的秒杀等场景都会用到队列

    3.发布订阅

    4.计数器

    5.排行榜:微博的热榜就是很好的例子

    6.资源锁:这个秒杀的时候往往也会用到,防止超卖等现象发生,当然还有很多其他防并发的用途。

    redis的五种常用数据类型:string,hash,set,zset.list

    redis淘汰策略:

          noevication:不删除策略,达到maxmemory,直接返回错信息

         allkeys-lru: 优先删除最近最少使用的key

         volatile-lru: 优先删除设置过expire的最近最少使用的key.

         allkeys-random: 随机删除部分key

         volatile-random:随机删除设置过过期时间的key

         volitile-ttl : 删除设置过期时间中的剩余时间最少的key

    一般来说:

    如果分为热数据与冷数据, 推荐使用 allkeys-lru 策略。 也就是, 其中一部分key经常被读写. 如果不确定具体的业务特征, 那么 allkeys-lru 是一个很好的选择。
    如果需要循环读写所有的key, 或者各个key的访问频率差不多, 可以使用 allkeys-random 策略, 即读写所有元素的概率差不多。
    假如要让 Redis 根据 TTL 来筛选需要删除的key, 请使用 volatile-ttl 策略。

    Redis为了保证高可用性,采用Master-slave形式部署,采用AOF或RDB进行持久化,采用集群culster机制来分布式存储。

    redis哨兵:
    很显然,只使用单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行。所以有必要将sentinel集群,这样有几个好处:
    即使有一些sentinel进程宕掉了,依然可以进行 集群的主备切换;
    如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);
    如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息

    对象序列化:serialize 方便存储redis(strig)
    1.hash

    是一个string类型的field 和 value的映射表,适合存储对象;

    常用命令:hget,hset,hgetall 等;

    hset myhash name cyh

    hset user:001 name cyh
    hget user:001 name --返回cyh 把user:001当作一个表 name为字段名 cyh为字段值

    hsetnx user:002 name ss --如果存在则返回0不保存进去

    hmset user:003 name ss age 20 sex women -- 批量设置
    hmget user:003 name age sex -- 批量返回(ss ,0 ,women)
    hget user:003 age --20

    hincrby user:003 age 5 --自增5
    hexists user:003 age --判断hash表里面的字段是否存在的方法
    hlen user:003 --返回字段的数量

    hdel user:003 age --删除age字段的值

    hkeys user:003 --返回所以字段名(array_keys)
    hvals user:003 --返回所有的值(array_vales)

    hgetall user:003 --返回所有键值

    expire age 10 --给age设置过期时间十秒钟

    ttl age --返回-1查看是否过过期

    2.list(有序非去重集合)

    常用命令:lpush,rpush(存数到队列),lpop(取数),rpop,lrange等。

    使用场景:做消息队列系统

    下面这个程序模拟了20w人一瞬间涌入这个页面进行秒杀,能够秒杀成功的只有500人,我们把先进来的用户放入redis队列中,当队列中的用户达到500时,后来用户就转到秒杀结束页面。这里用随机数来表示不同的用户。

    $redis = new redis();

    $redis->connect('localhost','6379');

    $redis->select(1);

    $redis_name = 'miaosha';

    $num = 500;   抢购名额

    $i = 20000;    抢购人数

    $n = 0;        验证执行数量是否正确

    while($i--){

       $n++;

      $uid = mt_rand(100000,99999)

       if( $redis->llen($redis_name) <  $num){

                 $redis->rpush($reids_name,$uid);

                echo  $uid. '秒杀成功';

     }else{

                echo $uid . "秒杀失败"

    }   

    $redis->close();

    }


    3.string:最简单的数据类型(k-v)
    set name cyh
    get name

    setnx name cyh (防止覆盖,如果存在这个key则返回0存不进去)

    setex color 10 red 设置键值并设置有效值

    setrange name 6 qq.com 替换字符串,从下标为6(下表从0开始)的开始替换,后面的参数为替换的内容

    mset key1 val1 key2 val2 批量设置

    getrange name 0 5 获取字符串(0到5)

    incr id3 自增操作
    decr 自减
    incrby id 5 自增五个
    decrby id 5

    append name.ss 给name的value追加字符串

    strlen name 求键的长度


    4.set(去重无序集合)

    常用命令:sadd,spop,smembers,sunion 等。


    5.zest

    使用场景:排行榜应用,取TOP N操作

    redis事务特性:不具有事务的原子性(加入队列中的某个事务没有执行成功,但是整个事务不会全部回滚),会导致数据不具有一致性
    $redis->muilti --开始事务上下文
    ok
    $redis->set age 10 --先将事务放入队列中
    queued
    $redis->set age 20
    queued
    $redis->exec --执行事务
    1ok
    2ok
    $redis->get age
    20
    $redis->discard --取消事务(事务回滚:清空队列并退出事务上下文)


    redis 乐观锁:类似版本控制器(更新后版本号加1,如果提交版本号大于当前版本号则更新当前版本号,否则则认为是过期数据)
    watch age --监控age

    $redis->set age 30

    $redis->muilti
    $redis->set age 20
    queued
    $redis->exec --事务将执行失败 、
    (当watch监控age时,发现从监视起这个key发生过变化,则整个事务将失败,(打开watch就相当于对当前key增加了一个乐观锁)
    也可以调用watch多次监视多个key,这样就可以对指定的key加乐观锁,watch的key是对整个事务都有效的,事务也一样
    unwatch ,discard,exec都会清除连接中的所有监视
    当前事务的age不是最新的age,属于过期数据不允许执行)

     

    redis 持久化机制:
    redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘来保证持久化。

    redis持久化的方式:
    1.快照模式(snapshoting 文件dump.rdb 二进制) 也是默认方式: 相当于把数据做一个备份(将数据存到文件里)
    ans:
    这种方式是将内存中的数据以快照的方式写到二进制文件中,默认的文件名为dump.rdb。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照
    save 300 10 #300秒内如果有10个key被修改过,则发起快照保存

    2.append_only_file(aof 文件appendonly.aof 某种协议) 增量型持久化: 将写和更改的操作存到一个文件里面(insert.update)extend:所有被写入 AOF 的命令都是以 redis 的协议('RESP')格式来保存的。
    ans:
    由于快照方式在一定时间间隔内做一次的,如果redis意外宕机,就会丢失掉最后一次快照后的所有修改。
    aof比快照有更好的持久化,由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中。
    当redis重启时,会重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

    appendonly yes --启用aof持久化
    appendfsync always --收到写命令就立即写入磁盘,最慢,但是数据最完整
    appendfsync everysec --每秒写入磁盘一次 性能折中
    appendfsync no --完全依赖os,性能最好,持久化没保障


    发布与订阅:
    是一种消息通信模式,主要是解决消息订阅者和发布者之间的耦合性,redis作为一个pub/sub的server,在订阅者和发布者之间起到路由的功能
    订阅者可以通过subscribe和psubscribe向redis service订阅自己感兴趣的消息类型,redis将信息类型称为通道,当发布者通过publish命令向
    redis service发送特定的消息类型的信息时,订阅改信息的全部client都会收到此消息

    可以做一个web聊天系统

    subscribe tv1 tv2
    cyh


    publish tv1 cyh


    虚拟内存:
    把不经常使用的数据交换到磁盘上

    常规使用:
    $redis = new redis();
    redis->connect();


    -- 添加
    $redis->hset()

    --批量添加
    $uid = $redis->incr("userid");
    $redis->hMset('user:' . uid,array('uid'=>$uid,name'=>'cyh','age'=>'20'))
    $redis->hMset('header:rows1',array('name'=>'cyh','age'=>'20'))

    -- 批量获取
    require("redis.php");
    foreach($i = 1 ; $i <= ($redis->get("userid")) ; $i++){
    $data[] = $redis->hgetall("user:" . $i);
    }

    -- 删除
    $redis->del("user" . $uid)


    -- 分页
    总数
    $count = $redis->lsize("uid");

    页大小
    $page_size = 10;

    当前页码
    $page_num = $GET_['page'];

    页总数
    $page_count = ceil($count/$page_size)

    $ids = $redis->lrange('uid',($page_num-1)*$page_size,(($page_num-1)*$page_size+($page_size-11))
    foreach($ids as $v){
    $data[] = $redis->hgetall('user:'.$v);
    }

  • 相关阅读:
    Windows10 Docker 安装 dotnet core sdk 超时
    解决 jQuery-datepicker无法弹出日期的问题
    SQL2008 'OFFSET' 附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无效。
    “entities.LastOrDefault()”引发了类型“System.NotSupportedException”的异常
    快速开发平台
    快速设计ComboBox下拉框
    流程设计-流程模式
    流程设计-流程工具
    快速开发一款APP
    SDP开发
  • 原文地址:https://www.cnblogs.com/-cyh/p/10129006.html
Copyright © 2011-2022 走看看