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

原文地址:https://www.cnblogs.com/tangxuliang/p/9187235.html