• Redis初步学习


    一、编译安装 Redis

    下载地址:https://redis.io

    (1)编译: make 

    (2)复制 redis 相关程序和配置文件到 /usr/local/redis

    cp ~/downloads/redis-4.0.10/src/redis-server /usr/local/redis/
    cp ~/downloads/redis-4.0.10/src/redis-cli /usr/local/redis/ 
    cp ~/downloads/redis-4.0.10/redis.conf /usr/local/redis

    (3)编辑 redis.conf 配置文件

    bind 127.0.0.1 
    port 6379
    daemonize yes                   # 以守护进程运行
    pidfile /var/run/redis_6379.pid  

    (4)示例启动脚本

    » redis

    REDIS_SERVER=/usr/local/redis/redis-server
    REDIS_CLI=/usr/local/redis/redis-cli
    REDIS_CONF=/usr/local/redis/redis.conf
    
    start_server()
    {
      $REDIS_SERVER $REDIS_CONF
    }
    stop_server()
    {
      $REDIS_CLI shutdown
    }
    cli()
    {
      $REDIS_CLI
    }
    
    case "$1" in
      'server')
        start_server
        ;;
      'client')
        cli
        ;;
      'stop')
        stop_server
        ;;
      *)
        echo 'unknow!'
    esac

    (5)启动

    ./redis server

    执行结果:

    二、Redis 数据结构

    2.1 String 类型

    string 是 redis 最基本的类型,而且 string 类型是二进制安全的。

    redis 的 string 可以包含任何数据。包括 jpg 图片或者序列化的对象,最大上限是1G字节。 如果只用 string 类型,redis 就可以被看作加上持久化特性的 memcached。

    命令:

    • set key value:设置指定 key 的值
    • get key:获取指定 key 的值
    set name txl         # 设置 name = txl
    get name             # 获取 name
    keys name            # 获取对应的 key,可以用匹配模式
    del name             # 删除 key 为 name 的数据

    2.2 Hash 类型

    redis hash 是一个 string 类型的 field 和 value 的映射表。

    hash 特别适合用于存储对象。相较于将对象的每个字段存成单个 string 类型。将一个对象存储在 hash 类型中会占用更少的内存,并且可以更方便的存取整个对象。

    命令:

    • hset key field value:将哈希表 key 中的字段 field 的值设为 value
    • hsetnx key field value:只有在字段 field 不存在时,设置哈希表字段的值
    • hget key field:获取存储在哈希表中指定字段的值
    • hdel filed1 [filed2...]:删除一个或多个哈希表字段
    • hlen key:获取哈希表中字段的数量
    • hexists key field:查看哈希表 key 中,指定的字段是否存在
    • hkeys key:获取哈希表 key 中的所有字段
    • hvals key:获取哈希表 key 中的所有值
    实例:统计网站在线人数

    思路:用户登录时,记录 Hash 类型的用户信息到 redis 中。如:key 为 UserLogin,filed 为 用户ID(或sessionid),value 为用户 ID、登录 IP、登录时间的 Json。最后通过 shell 调用 redis-cli 客户端的 hlen 方法就可以统计网站在线人数。

    但是需要定时清理离线用户。如:理想情况下,用户主动注销,同时清除 redis 对应的用户记录。但是当用户非正常退出或长时间无任何请求时,可以设定一个机制:

    当用户访问网站任意页面时,都加载一段脚本,触发该用户的时间标识,如:

    <script src=“/redis/useronline.php”></script>

    并同时记录在 redis 中。只需定时执行清理脚本:判断服务器时间和用户时间标识的时间差,如超过20分钟没有任何更新则认为该用户为离线用户,删除该用户记录。

    » usersonline

    # 统计所有离线用户
    IDS=`/usr/local/redis/redis-cli hvals users_login | awk -F ',' '{print $1 $3}' | awk 'gsub(/{"uid":|"utime"|}/,"",$1)' | awk -F ':' '
      BEGIN{result=""; time_diff=0}
      {
        time_diff=systime()-$2;
        #print time_diff;
        if(time_diff>1800)
        {
          result=result" "$1;
        }
      }
      END{print result}
    '`
    # 从 redis 中删除离线用户记录
    /usr/local/redis/redis-cli hdel users_login  $IDS
    echo $IDS" is deleted"

    执行结果:

    2.3 List(列表)类型

    List 是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部或尾部。

    命令:

    • lpush key value1 [value2...]:将一个或多个值插入到列表头部
    • rpush key value1 [value2...]:将一个或多个值插入到列表尾部
    • llen key:获取列表长度
    • lrange key start stop:获取列表指定范围内的元素(0代表第一个,-1代表最后一个)
    • lpop key:移出并获取列表的第一个元素
    • rpop key:移出并获取列表的最后一个元素

    2.4 Set(集合)类型

    Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

    命令:

    • sadd key member1 [member2...]:向集合添加一个或多个成员
    • scard key:获取集合的成员数
    • smembers key:返回集合中的所有成员
    • sismember key member:判断 member 元素是否是集合 key 的成员(1代表是,0代表不是)
    • spop key:移除并返回集合中的一个随机元素
    • srem key member1 [member2...]:移除集合中一个或多个成员
    • smove source destination member:将 member 元素从 source 集合移动到 destination 集合
    • sdiff key1 [key2...]:返回给定所有集合的差集
    • sdiffstore destination key1 [key2...]:返回给定所有集合的差集并存储在 destination 中
    • sinter key1 [key2...]:返回给定所有集合的交集
    • sinterstore destination key1 [key2...]:返回给定所有集合的交集并存储在 destination 中
    • sunion key1 [key2...]:返回所有给定集合的并集
    • sunionstore destination key1 [key2...]:所有给定集合的并集存储在 destination 集合中

    2.5 Sorted set(有序集合)类型

    Sorted set 有序集合和集合一样也是 String 类型元素的集合,且不允许重复的成员。集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

    不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。

    命令:

    • zadd key score1 member1 [score2 member2...]:向有序集合添加一个或多个成员,或者更新已存在成员的分数
    • zcard key:获取有序集合的成员数
    • zcount key min max:计算在有序集合中指定区间分数的成员数
    • zrange key start stop [withscores]:通过索引区间返回有序集合成指定区间内的成员,分数从低到高(strart从0开始,stop如果为负数代表到最后第几个)
    • zrangebyscore key min max [withscores] [limit]:通过分数返回有序集合指定区间内的成员
    • zrevrange key start stop [withscores]:通过索引区间返回有序集中指定区间内的成员,分数从高到底(strart从0开始,stop如果为负数代表到最后第几个)
    • zrevrangebyscore key max min [withscores]:通过分数返回有序集合指定区间内的成员
    • zscore key member:返回有序集中,成员的分数值
    • zrank key member:返回有序集合中指定成员的索引,索引从低到高
    • zrevrank key member:返回有序集合中指定成员的索引,索引高低到低
    • zincrby key increment member:有序集合中对指定成员的分数加上增量 increment
    • zrem key member1 [member2...]:移除有序集合中的一个或多个成员
    • zremrangebyrank key start stop:移除有序集合中给定的排名区间的所有成员
    • zremrangebyscore key min max:移除有序集合中给定的分数区间的所有成员
    实例①:消息队列单点处理(redis+shell)

    当处理高并发请求时往往会使用消息队列来做“缓冲”。

    如门户网站后台发布页面(生成静态或缓存文件),可以在消息队列中存放多个“发布任务”:

    1. 后端程序不断地“压任务”,存放有序集合到 redis,如 score 存放任务时间戳,member 存放文件名(可以放序列化过后的类、存储过程或 shell 脚本名等等)
    2. Shell 脚本定时处理消息队列(任务),将生成文件发布到网站目录中

    » job

    # 获取redis中第一条任务
    GET_JOB="/usr/local/redis/redis-cli zrange job 0 0"
    
    function dojob()
    {
      # 生成文件
      echo "job:$1" > $2"/"$1
      # 清除redis中该条任务
      /usr/local/redis/redis-cli zrem job $1
    }
    # 导出dojob函数用于awk调用
    export -f dojob
    
    $GET_JOB | awk 'BEGIN{wwwroot="/var/www/job"}
    {
      # 调用dojob并将任务名(文件名)和生成路径传递过去
      "dojob "$1" "wwwroot|getline;
      #print $1;
    }
    '
    实例②:消息队列多进程处理(redis+php)

    » job_fork.php

    #! /usr/local/php7.2.6/bin/php
    <?php
    
    // 10个进程同时处理
    for($i=0; $i<10; $i++)
    {
        $pid = pcntl_fork();
        if($pid == 0)
        {
            while (true) {
                $redis = new Redis();
                $redis->connect('180.76.232.93',6379);
                // 判断队列是否有序列,如果没有则继续循环
                if(count($redis->keys('job'))==0) {
                    continue;
                }
                // 加锁
                if($redis->setnx('joblock',1)==1) {
                    // 从队列中读取第一个
                    $getjob = $redis->zrange('job',0,0);
                    // 删除当前队列
                    $redis->zrem('job',$getjob[0]);
                    // 解锁
                    $redis->del('joblock');
             
                    // 注意,这里要用到redis原子事务 multi和exec
                    // $redis->multi(); //开启事务
                    // redis相关的命令...
                    // $redis->exec(); //结束事务
           
                    // 执行任务
                    file_put_contents('/var/www/job/'.$getjob[0],'job:'.$getjob[0]);
                    // 应该输出到日志中                 
                    echo $getjob[0]."is done".PHP_EOL;   
                    sleep(1);
                }    
            }
        }
    }  

    2.6 HyperLogLog 结构

    HLL 是用来做基数统计的算法,它的优点是在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的。

    命令:

    • pfadd key element [element...]:添加指定元素到 HLL 中,重复值不会累计
    • pfcount key [key...]:返回给定 HLL 的基数估算值
    • pfmerge destkey sourcekey [sourcekey...]:合并若干 key 到目标 key,重复值依旧不会累加

    2.7 Bitmap 类型

    Bitmap 是属于 String 类型的一种数据结构,就是通过一个 bit 位来表示某个元素对应的值或者状态,其中的 key 就是对应元素本身。我们知道 8 个 bit 可以组成一个 byte,所以 Bitmap 本身会极大的节省储存空间。它可以用于很多的统计、数据分析等应用场景。

    命令:

    • setbit key offset value:设置或者清空 key 的 value(字符串)在 offset 处的 bit 值(只能是0或者1)
    • getbit key offset:获取指定索引的值
    • bitcount key [start end]:统计出指定范围(start到end,单位是字节不是位,如不指定则就是获取全部)bit 值为 1 的数量

    参考:https://segmentfault.com/a/1190000008188655

  • 相关阅读:
    Microsoft .NET Framework v4.0 正确安装方法
    彻底解决C#实现DataTable导出EXCEL表格
    利用log4net记录操作日志
    [转]驱动程序开发—编译正传(5)
    [转]驱动程序开发-概述(1)
    论富客户端程序的webservice实现
    在Vista中编程控制防火墙设定(C#)
    [转]驱动程序开发—编译前传(4)
    C#系统较时
    [转]驱动程序开发—工具篇(2)
  • 原文地址:https://www.cnblogs.com/tangxuliang/p/9187235.html
Copyright © 2020-2023  润新知