关于redis:Redis基础

51次阅读

共计 15841 个字符,预计需要花费 40 分钟才能阅读完成。

Redis 介绍

概述

  • Redis 是 Remote Dictionary Server(近程数据服务)的缩写.

由意大利人 antirez(Salvatore Sanfilippo)开发的一款内存高速缓存数据库, 诞生于 08 年。

依据月度排行网站 DB-Engines.com 的数据显示,Redis 是最风行的键值对存储数据库。

  • 该软件应用 C 语言编写,它的数据模型为 key-value,

开源的,构建与内存的数据结构数据库,罕用作数据存储,缓存解决和音讯队列解决

  • 反对多种数据结构类型,

包含 string(字符串)、hash(哈希)、list(链表)、set(汇合)、Zset(有序汇合)。

  • 为了保障效率数据都是缓存在内存中,它也能够周期性的把更新的数据写入磁盘或者把批改操作写入追加的记录文件。
  • 极高的读写性能,原子性操作

Redis 能读的速度是 110000 次 /s, 写的速度是 81000 次 /s。

Redis 所有单个命令的执行都是原子性的,这与它的单线程机制无关;

Redis 命令的原子性使得咱们不必思考并发问题,能够不便的利用原子性自增操作 实现简略计数器性能;

应用缓存加重数据库的负载。

在开发网站的时候如果有一些数据在短时间之内不会发生变化,而它们还要被频繁拜访,为了进步用户的申请速度和升高网站的负载,就把这些数据放到一个读取速度更快的介质上(或者是通过较少的计算量就能够取得该数据),该行为就称作对该数据的缓存。

该介质能够是:文件、数据库、内存,内存介子常常用于数据缓存。

缓存的两种模式:

  • 页面缓存 (磁盘缓存):常常用在 CMS(content manage system) 内存管理系统里边(Smarty 缓存)

index.php ==== >index.html 就间接拜访 index.html 页面;

  • 数据缓存:常常会用在页面的具体数据里边

    应用场合及其劣势

  • 高性能缓存,最常见的利用场景
  • 多类型数据结构,适宜各种类型数据,
  • Redis 分布式存储
  • 数据有生命周期,Redis 的键能够设置过期时长,一段时间当前主动删除。
  • 高并发和海量数据的解决
  • 数据长久化,数据存储到硬盘外面,服务器断电不失落。

redis 与 memcache 比拟

1、数据类型:

memcache 反对的数据类型就是字符串,

redis 反对的数据类型有字符串,哈希,链表,汇合,有序汇合。

2、长久化:

memcache 数据是存储到内存外面,一旦断电,或重启,则数据失落。

redis 数据也是存储到内存外面的,然而能够长久化,周期性的把数据给保留到硬盘外面,导致重启,或断电不会失落数据。

3、数据量:

memcahce 一个键存储的数据最大是 1M,

而 redis 的一个键值,存储的最大数据量是 1G 的数据量。

装置 redis

# 下载
wget http://download.redis.io/releases/redis-6.0.6.tar.gz
#解压
tar zxvf redis-6.0.6.tar.gz
#进入解压目录
cd redis-6.0.6

#无需配置,间接编译
make

若呈现如下提醒,则阐明未装置 gcc

/bin/sh: cc: command not found
make[1]: * [adlist.o] Error 127
make[1]: Leaving directory `/root/redis-6.0.6/src’
make: * [all] Error 2

解决:yum -y install gcc

若呈现如下提醒

make[1]: * [server.o] Error 1

make[1]: Leaving directory `/root/redis-6.0.1/src’

make: * [all] Error 2

呈现这个问题须要先确认 GCC 的版本,命令如下:

gcc -v

发现 CentOS7 默认的 gcc 版本为 4.8.5,装置 Redis6.0 须要将 gcc 版本升级到 5.3 以上,则降级 gcc 命令如下:

yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
 
#长期批改 gcc 版本
scl enable devtoolset-9 bash
#永恒批改 gcc 版本
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile

装置

#(装置编译后的文件)到指定目录:make PREFIX=/usr/local/redis install

留神:PREFIX 必须大写、同时会主动为咱们创立 redis 目录,并将后果装置此目录

装置实现后,会在 redis 的装置目录上面创立一个 bin 目录,该目录外面有 5 个文件。

redis-benchmark 命令性能测试命令

redis-check-aof 和 redis-check-rdb 日志检测工具

redis-server 是服务器端启动的命令

redis-cli 是客户端连贯服务器的命令

配置文件详解

从 redis 的解压目录外面把 redis.conf 配置文件复制到 redis 的装置目录上面(与 bin 目录同级)。

cp ~/redis-6.0.6/redis.conf /usr/local/redis

1、redis 默认不是以守护过程的形式运行,能够通过该配置项批改,应用 yes 启用守护过程

daemonize no // 改为 yes,让 redis 的过程在后盾执行,不占据以后终端。

2、当 Redis 以守护过程形式运行时,Redis 默认会把 pid 写入 /var/run/redis.pid 文件,能够通过 pidfile 指定

pidfile /var/run/redis.pid

3、指定 Redis 监听端口,默认端口为 6379,

port 6379

4、平安认证

requirepass 321612

留神:

        设置的明码是明文的,因而要对 redis.conf 配置文件,进行严格的受权。

5、外网 php 客户端连贯 Linux 的 redis

开启 redis-server 后,redis-cli 只能拜访到 127.0.0.1,因为在配置文件中固定了 ip,

bind 127.0.0.1   改为 #bind 127.0.0.1

protected-mode yes 改为 protected-mode no

redis 从 3.2 版本后减少了 protected-mode 参数,protected-mode 参数是为了禁止外网拜访 redis,
如果启用了,则只能通过 lookbackip(127.0.0.1)拜访 redis,如果外网拜访 redis,会报出异样。

启动

启动 redis 服务

语法:

    redis-server(写门路) redis.conf(写门路)
cd /usr/local/redis/bin
./redis-server ../redis.conf

启动 redis 客户端

语法:redis-cli -h 主机 ip - p 端口号

./redis-cli

PING 命令,该命令用于检测 redis 服务是否启动

redis 敞开服务

  • 断电、非正常敞开。容易数据失落

    ps -ef | grep redis
    kill -9 PID

  • 失常敞开、数据保留

    通过客户端进行 shutdown,敞开 redis 服务

    exit
    /usr/local/redis/bin/redis-cli shutdown    

装置 php 的 redis 扩大

CentOS7 为 php7.2 装置 php-redis 扩大

yum -y install php-pecl-redis

凋谢 6379 端口

firewall-cmd --zone=public --add-port=6379/tcp --permanent

firewall-cmd --reload

selinux 长期敞开(不必重启机器):

setenforce 0          #设置 SELinux 成为 permissive 模式

php 操作 redis

$redis = new Redis();
$redis->connect('localhost');
$redis->auth('321612');

// 字符串类型
$redis->set('age',12);
$redis->set('username','libai');

// 哈希类型
$redis -> hset('user:id:1', 'name', 'songjiang');
$redis -> hmset('user:id:2', ['name'=>'xiaohei','age'=>12,'email'=>'xiaohei@souhu.com']);

// 链表类型
$redis -> lpush('user_list', '王刚');
$redis -> lpush('user_list', '宋江');
$redis -> lpush('user_list', '李白');

// 字符串
$username = $redis->get('username');
$age = $redis->get('age');

// 哈希
$data = $redis -> hgetall('user:id:2');

// 链表
$info = $redis->lrange('user_list',0,-1);

案例:记住明码谬误次数

$username = $_POST['username'];
$password = $_POST['password'];

$redis = new Redis();
$redis->connect('localhost');

// 构建键
$login_key = $username.'login_num';
$num = $redis->get($login_key);

if($num>=3){
    // 设定过期工夫
    $redis->setTimeout($login_key,3600*24);
    exit('锁定账号');
}

// 明码
$pwd = '123456';

if ($password == $pwd) {echo 'login success';} else {$redis->incr($login_key);
    echo '明码谬误!';
}

key 命名标准

key 单词与单词之间以:离开

个别状况下:

第一段搁置我的项目名或缩写,如 project

第二段把表名转换为 key 前缀,如 user:

第三段搁置用于辨别区 key 的字段,对应 mysql 中的主键的列名,如 userid

第四段搁置主键值,如 18,16

例:

user:id:3506728370            {id:3506728370,name: 春晚,fans:12210947,blogs:6164,focus:83}

#表名: 主键名: 主键值: 属性名    
user:id:3506728370:fans      12210947

user:id:3506728370:blogs     6164

user:id:3506728370:focus     83

string(字符串)

redis 的 string 能够蕴含任何数据,包含序列化的对象、数组。

单个 value 值最大下限是 1G 字节,如果只用 string 类型,redis 就能够被看做加上长久化个性 (服务器重启之后,数据不失落) 的 memcache。

基本操作

  • set 增加 / 批改数据

    语法:

    set 键名称 值
    

    返回值:

    设置胜利返回 OK,设置失败返回 nil
    

    例:

    增加一个 name="xiaoqian" 的键值对
    set name xiaoqian
    
    留神:从新设置则间接笼罩。
  • get

    获取 key 对应的 string 值,如果 key 不存在返回 nil

    语法:

    get key 
    
    如果 key 不是 string 类型,返回错误信息。
  • del 删除数据

    语法:

    del key
    
  • mset

    语法:

    mset key value [key value]
    
    同时设置多个 key,如果 key 存在会笼罩,该命令是原子的,所有的键会同时设置胜利或失败,胜利返回 OK
    

    例:

    mset name xiaohei age 12 email xiaohei@163.com
    
  • mget

    语法:

    mget key [key...]
    
    查问所有 key 的值
    

    返回值:

    列出所有键的值,绝不会执行失败,如果键是 string 类型,返回其值,如果键不存在或者不是 string 类型,返回 nil
    

    例:

    mget name email title
    // xiaohei
    // xiaogei@163.com
    // nil
    
  • strlen 返回 key 的字符串长度
语法:strlen key 
    
返回值:如果 key 不存在返回 0
    如果不是字符串类型,返回错误信息。例:set age 300

    strlen age //3
  • append 追加信息到原始信息后部(如果原始信息存在就追加,否则新建)

    语法:

    append key value
    

    例:

    append age 200
    
    get age //300200

数值增减

  • incr

    对 key 的值做加加操作,每执行一次值加 1,值类型要是数据类型。

    语法:

    incr key
    
    将 key 中存储的数字值增一操作,如果 key 不存在,则 key 的值会先被初始化为 0,而后再执行 incr 操作,key 的值必须是整型。

    例:age 原先 12

    incr age
    //13
    
  • incrby

    执行加法的命令,能够指定相加的值

    语法:

    incrby key 相加的值
    
  • decr(减 1) decrby(减指定的值)

留神:

string 在 redis 外部存储默认就是一个字符串,当遇到增减类操作 incr,decr 时会转成数值型进行计算

redis 所有的操作都是原子性的,采纳单线程解决所有业务,命令是一个一个执行的,因而无需思考并发带来的数据影响。

时效性

  • setex 设置生效工夫

    语法:

    setex key seconds value
    
    给一个键设置为字符串类型,并指定生存工夫(单位:秒),该命令是原子的,如果设置失败或指定生存工夫失败,会复原初始状态。

    返回值:

    如果设置胜利,返回 OK,如果设置失败,返回错误信息。

    例:

    setex height 10 198

其余

  • setnx (判断键是否存在)

    语法:

    setnx key value
    
    如果 key 不存在,将其设置为字符串类型
    

    返回值:

    如果设置胜利,返回 1,设置失败,返回 0
    

    例:name 曾经存在时,body 不存在

    setnx name xiaobai
    // 0
    
    setnx body 1234
    //1
    
  • getset

    语法:

    getset key value
    
    原子的给一个 key 设置新值,并且将旧值返回,

    返回值:

    如果 key 不是字符串类型,返回一个谬误
    

    利用场景:

    比方获取计数器并且重置为 0。

    例:

    get name
    //xiaohei
    getset name xiaohuihui
    //xiaohei
    get name
    //xiaohuihui

hash(哈希)

hash 类型能够看成是具备 key 和 value 的容器,该类型非常适合存储对象信息,相似于关联数组。

一个存储空间保留多个键值对数据

基本操作

  • hset 设置哈希外面的 field 和 value 的值。

    语法:

    hset key field value
    

    例:

    hset user:id:1 name xiaobai
    
    hset user:id:1 age 12
    
    hset user:id:1 email xiaobai@sohu.com
    
  • hget 获取哈希外面的 field 的值

    语法:

    hget key 指定的 field
    

    例:

    hget user:id:1 name
    //xiaobai
    
    hget user:id:1 age
    //12
    
  • hgetall 获取指定哈希中所有的 field 和 value

    语法:

    hgetall key
    

    例:

    hgetall user:id:2
    //name
    //xiaohong
    //age
    //12
    //email
    //xiaohong@sohu.com
    
  • hdel 删除数据

    语法:

    hdel field1 [field2]
    
  • hmset 一次性设置多个 field 和 value。

    语法:

    hmset key field1 value1 field2 value2    
    

    例:

    hmset user:id:2 name xiaohong age 12 email xiaohong@sohu.com
    
  • hmget 一次性获取 多个 field 的 value

    语法:

    hmget key field1 field2......
    

    例:

    hmget user:id:2 name age email
    //xiaohong
    //12
    //xiaohong@souhu.com
    
  • hlen 获取哈希表中字段的数量

    语法:

    hlen key 
    

    例:

    hlen user:id:2
    //3
    

    留神:

    看的是 field 的数量
    
  • hexists 获取哈希表中是否存在指定的字段

    语法:

    hexists key field
    

    例:

    hexists user:id:2 age 

其余

  • hkeys 获取哈希表中所有的字段名

    语法:

    hkeys key 
    
  • hvals 获取哈希表中所有的字段值

    语法:

    hvals key
    
  • 设置指定字段的数值数据减少指定范畴的值

    hincrby key field increment

    hincrbyfloat key field increment

hash 实现购物车

业务剖析

  • 仅剖析购物车的 redis 存储模型:增加、浏览、更改数量、删除、清空
  • 购物车与数据库间长久化同步(不探讨)
  • 购物车与订单间关系(不探讨)

    ​ 提交购物车:读取数据生成订单

    ​ 商家长期价格调整:隶属于订单级别

  • 未登录用户购物车信息存储(不探讨)

    ​ cookie 存储

解决方案:

  • 以客户 id 作为 key,每位客户创立一个 hash 存储构造存储对应的购物车信息
  • 将商品编号作为 field,购买数量作为 value 进行存储
  • 增加商品:追加全新的 field 与 value
  • 浏览:遍历 hash
  • 更改数量:自增 / 自减,设置 value 值
  • 删除商品:删除 field
  • 清空:删除 key
hmset user:id:1 g1 100 g2 200
hmset user:id:2 g2 1 g4 7 g5 100

// 增加商品
hset user:id:1 g3 5

// 查看购物车
hgetall user:id:1

// 删除商品
hdel user:id:1 g1

// 更改数量
hincrby user:id:1 g3 100

以后设计仅仅是将数据存储到了 redis 中,并没有起到减速的作用,商品信息还须要二次查询数据库

  • 每条购物车中的商品记录保留成两条 field
  • field1 专用于保留购买数量

    • 命名格局:商品 id:nums
    • 保留数据:数值
  • field2 专用于保留购物车中显示的信息,蕴含文字描述,图片地址,所属商家信息等

    • 命名格局:商品 id:info
    • 保留数据:json
hmset user:id:3 g1:nums 100 g1:info {……}
hmset user:id:4 g1:nums 100 g1:info {……}

以后设计有很大的冗余,商品信息反复存储了

  • 能够把商品信息做成独自的 hash
hset user:id:3 g1:nums 200 
hsetnx goods:info g1:info {……}

hset user:id:4 g1:nums 100 
hsetnx goods:info g1:info {……}

hash 实现抢购

销售手机充值卡的商家对挪动、联通、电信的 30 元、50 元、100 元商品推出抢购流动,每种商品抢购下限 1000 张

解决方案:

  • 将商家 id 作为 key
  • 将参加抢购的商品 id 作为 field
  • 将参加抢购的商品数量作为对应的 value
  • 抢购时应用降值的形式管制产品数量
  • 理论业务中还有超卖等理论问题,这里不做探讨
hmset business:id:1 c30 1000 c50 1000 c100 1000

hincrby business:id:1 c50 -1

list(列表)

list 类型其实就是一个字符串的双向链表,依照插入程序排序。

能够增加一个元素到链表的头部 (右边) 或者尾部(左边),一个链表最多能够蕴含 2 32 -1 个元素(4294967295,每个链表超过 40 亿个元素),

这使得 list 既能够用作栈,也能够用作队列。

利用场景:

粉丝列表
最新文章
音讯队列等

增加 / 批改

  • lpush 从链表的头部增加一个或多个元素

    语法:

    lpush key value1 [value2] 
    
    操作为原子性操作,如果 key 不存在,一个空列表会被创立并执行 lpush 操作。

    返回值:

    执行 lpush 命令后,列表的长度。

    例:

    lpush user_list libai
    //1
    lpush user_list lihei
    //2
    lpush user_list songjiang
    //3
    
  • rpush 从链表的尾部增加元素

    语法:

    rpush key value1 [value2] 
    

    例:

    rpush user_list wusong
    //5
    
    lrange user_list 0 -1
    //wuyong
    //dufu
    //lihei
    //libai
    //wusong
    
  • linsert 将元素插入到链表中某个元素之前或之后

    语法:

    linsert key before|after 链表中的某个元素 新的元素
    

    返回值:

    执行胜利,返回插入操作实现之后,列表的长度
    如果没有找到链表中的元素,返回 -1
    如果链表不存在或空链表,返回 0
    

    例:

    linsert user_list before lihei dufu
    //4
    
  • lset(改值) 批改链表中指定下标的元素。

    语法:

    lset key 下标 新值
    

    例:

    lset user_list 0 wuyong
    
    lrange user_list 0 -1
    //wuyong
    //dufu
    //lihei
    //libai

获取

  • lrange 获取链表外面的元素

    语法:

    lrange key start(索引) stop(索引)
    

    留神:

    如果开始下标是 0,完结下标是 -1,则返回链表中所有的元素。链表外面的元素是序号的(从 0 开始,头部开始),相似于索引数组。

    例:

    lrange user_list 0 -1
    //songjiang
    //lihei
    //libai
    
  • lindex 返回列表中指定下标的元素

    语法:

    lindex key index
    

    例:

    lindex user_list 2
    //lihei
    
  • llen 返回列表的长度

    语法:

    llen key
    

    例:

    llen user_list
    //5

获取并移除

  • lpop 删除并返回链表中头部的元素

    语法:

    lpop key 
    

    例:

    lpop user_list
    //wuyong
    
    lrange user_list 0 -1
    //dufu
    //lihei
    //libai
    //wusong
    
  • rpop 删除并返回链表尾部的元素

    语法:

    rpop key 

删除

  • lrem 删除链表中的元素

    语法:

    lrem key count value
    
    依据参数 count 的值,删除链表中与 value 相等的元素。count>0,从表头开始向表尾搜寻,删除与 value 相等的元素,数量为 count。count<0,
        从表尾开始向表头搜寻,删除与 value 相等的元素,数量为 count。count=0,删除表中所有与 value 相等的值。

    返回值:

    被删除的元素的数量。

    例:

    从尾部删一个
    lrange user_list -1 lihei        
    
  • ltrem 保留指定范畴的元素,其余的删除

    语法:

    ltrim 链表的名称 开始下标 完结下标 
    

    例:

    lrange user_list 0 -1
    //lihei
    //dufu
    //libai
    //wusong
    
    ltrim user_list 1 2
    //ok 
    
    lrange user_list 0 -1
    //dufu
    //libai 

阻塞数据获取

规定工夫内获取并移除数据

blpop key1 [key2] timeout

blpop list0 30

brpop key1 [key2] timeout


案例:一个网站中,想要获取最新登录的 10 个用户。

如果通过 list 链表实现以上性能,能够在 list 链表中只保留最新的 10 个数据,每进来一个新数据就删除一个旧数据。

每次就能够从链表中间接取得须要的数据。极大节俭各方面资源耗费。

例:lpush user_login songjiang 
    
    if (llen(user_login)>10) {
        // 从尾部弹出元素
        rpop user_login
    }

    // 查
    lrange user_login 0 -1

秒杀案例:

原理:

    应用 redis 链表中队列,进行 pop 操作,因为 pop 操作是原子的,即便有很多用户同时达到,也是顺次执行。
$redis = new Redis();
$redis->connect('127.0.0.1',6379); 
$redis->auth('321612');

//1、先将商品库存退出队列
// 商品数量
$goods_num = 100;
// 增加到队列
for ($i=0; $i < $goods_num; $i++) {$redis -> lpush('goods_store',1); // 理论存商品 id
}
$redis = new Redis();
$redis->connect('127.0.0.1',6379); 
$redis->auth('321612');

//2、开始抢购
// 设置库存的生效工夫
$redis->setTimeout('goods_store',30);
$redis = new Redis();
$redis->connect('127.0.0.1',6379); 
$redis->auth('321612');

//3、客户端执行下单操作,下单前判断 redis 队列库存量
$id = $redis->lpop('goods_store');
if(!$id){
    echo '抢购失败!';
    return;  
}

echo '抢购胜利!'; 
// 跳转到下单页面,实现下单操作

案例:注册发邮箱

register.php

$username = $_POST['username'];
$email = $_POST['email'];
// 实现注册,插入到 mysql 数据库

// 发送邮件到邮箱,让用户激活

$redis = new Redis();
$redis->connect('127.0.0.1');
$redis->auth('321612');

// 把发送邮件的操作增加到一个队列外面(异步操作)
$redis->lpush('email',json_encode(['email'=>$email,'username'=>$username]));
echo  'register success';

send_email.php

$redis = new Redis();
$redis->connect('127.0.0.1');
$redis->auth('321612');

// 依据列表外面的队列执行发送邮件的操作
while(true){$info = $redis->lpop('email');
    
    // 发送邮件
    
}

set(汇合)

redis 的 set 是 string 类型的无序汇合。

set 元素最大能够蕴含 (232-1)(整型最大值) 个元素。

对于 set 汇合类型除了根本的增加、删除操作,其余有用的操作还蕴含汇合的取 并集(union),交加(intersection),差集(difference)。

sina 公司的好友关注关系就大量应用了 set 汇合类型。

留神:

    每个汇合中的各个元素不能反复。

基本操作

  • sadd 向汇合中增加元素
语法:sadd key member1 [member2]

例:sadd libai_friend likui
    // 1
    sadd libai_friend xionger
    // 1
    sadd libai_friend xiongda
    // 1
    sadd libai_friend yangguo limochou
    // 2


  • smembers 获取汇合中的全副元素
语法:smembers key

例:smembers libai_friend
    //xiongda
    //xionger
    //limochou
    //likui
    //yangguo


  • srem 删除汇合中的元素

    语法:

    srem  key member1 member2
    
  • scard 获取汇合中元素的个数

    语法:

    scard 汇合名称
    

    例:

    scard libai_friend
    // 6 
    
    scard dufu_friend
    // 5        
    
  • sismember 判断汇合中是否蕴含指定数据

    语法:

    sismember key member

操作随机数据

  • srandmember 随机获取汇合中指定数量的数据

    语法:

    srandmember  key [count]
    

    例:

    sadd news n1    
    sadd news n2    
    sadd news n3    
    sadd news n4    
    
    srandmember news 2
    //n4
    //n1
    
    srandmember news 2
    //n2
    //n1
    
  • spop 随机获取汇合中的某个数据并将该数据移出汇合

    语法:

    spop  key
    

    例:

    spop news 
    //n5

交并差集

交加:两个汇合中共有的元素

差集:在第一个汇合外面有的,在第二个汇合外面没有的。

并集:两个汇合合并在一块,去掉重复部分

  • sinter 获取交加(在两个汇合中都存在的元素)

    语法:

    sinter key1 key2
    

    例:

    sinter libai_friend dufu_friend
    //xionger
    //likui
    
  • sunion 求并集(两个汇合合并后,去掉反复的元素)

    语法:

    sunion key1 key2 
    

    例:

    sunion libai_friend dufu_friend
    
  • sdiff 获取汇合中的差集(在汇合 1 中存在,不在汇合 2 中存在的元素)

    语法:

    sdiff key1 key2
    

    例:

    sdiff libai_friend dufu_friend
    
    sdiff dufu_friend libai_friend
  • 求两个汇合的交并差集并存储到指定汇合中

sinterstore destination  key1 key2

例:sinterstore u3 u1 u2


sunionstore destination  key1 key2

例:sunionstore u3 u1 u2


sdiffstore destination  key1 key2

例:sdiffstore u3 u1 u2
  • smove source destination key1 key2 将指定数据从原始汇合中挪动到指标汇合中
例:把 u2 的 w1 挪动到 u1 里
    smove u2 u1 w1

zset(sorted set: 有序汇合)

sorted set 是 set 的一个降级版本,在 set 的根底上减少了一个程序属性(权值),

这一属性在增加批改元素的时候能够指定,每次指定后,zset 会主动从新按新的值调整程序。

留神:

增加进去的元素,会主动依据序号排序。

​ 只有元素不一样即可,有序汇合外面能够有雷同序号

​ 取值的时候,索引跟序号没关系

基本操作

  • zadd 向有序汇合中增加元素。如果该元素存在,则更新其序号。

    语法:

    zadd key score1 member1 [score2 member2]
    

    例:

    zadd zst1 23 xiaolong
    zadd zst1 67 libai
    zadd zst1 88 xiaolong   // 元素存在,则更新其程序。zadd zst1 67 liubei     // 能够有雷同序号
    
    
    
  • zrange 按序号升序获取有序汇合中的内容。

(把汇合排序后,返回名次 [start, stop] 的元素,默认是升序排列,withscores 是把 score 也打印进去)

语法:zrange key start stop [WITHSCORES] 

例:zrange zset1 0 -1 withscores 
    //xiaolonog
    //12
    //libai
    //23
    //liubei
    //23
    //xiaolong
    //45

留神:下标不是序号,是数据的索引

  • zrevrange 按序号降序获取有序汇合中的内容。

    语法:

    zrevrange key start(索引) stop(索引) [WITHSCORES] 
    

    例:

    zrevrange zset1 0 -1 withscores
    //xiaolong
    //45
    //liubei
    //23
    //libai
    //23
    //xiaolonog
    //12
    
    
  • 按条件获取数据
    zrangebyscore key min max [withscores] [limit]
    zrevrangebyscore key max min [withscores]

    例:zrangebyscore scores 50 80 withscores
        //zhangsan 
        //67
        //zhouqi
        //71
  • zrem key member [member] 删除数据
  • 按条件删除数据

    zremrangebyrank 删除汇合中 排名 在指定范畴的元素(程序从小到大排序)

    zremrangebyscore key min max

    语法:

      zremrangebyrank key start stop
    

    第一步:从小到大排序 (依据序号)
    第二步:删除元素(依据索引范畴)

      例:删除依据序号从小到大排序后的索引从 0 到 0 的元素,也就是删除第一个元素(下标是 0 的)
          zremrangebyrank zset1 0 0
    
    

  • 汇合交并操作

zinterstore destination mumkeys key [key ……]

zunionstore destination numkeys key [key……]

元素个数

  • zcard key 返回有序汇合中元素的个数
zcard zset1 
//5
  • zcount key min max 指定范畴内汇合中元素的个数

索引(排名)

  • zrank key member
  • zrevrank key member
zadd movies 143 aa 97 bb 201 cc

zrank movies bb
//0

zrevrank movies bb
//2

score 值

  • zscore key member 获取给定元素对应的 score
zscore movies aa
//143

zscore movies cc
//201
  • zincrby key increment member 批改给定元素对应的 score
zincrby movies 1 aa

zscore movies aa
//144

案例:利用 sort set 实现获取最热门的前 5 帖子信息

思路:

以 mysql 中的 id 作为元素,回复量作为序号,
判断元素数量是否大于 5 个,
大于 5 个则 通过 zremrangebyrank hot_message 0 0
查的时候查 redis,不查 mysql

zadd hotmsg 2345 12 
zadd hotmsg 3678 100
zadd hotmsg 23456 89 
zadd hotmsg 1234 13
zadd hotmsg 1234 78

// 每减少一个新元素,就删除一个权值最小的旧元素,保留权值最高的 5 个元素
zadd hotmsg 5678 90


案例:时效性工作治理

例如观影试用 VIP、游戏 VIP 体验、云盘下载体验 VIP、数据查看体验 VIP。当 VIP 体验到期后,如何无效治理此类信息。即使对于正式 VIP 用户也存在对应的治理形式。

网站会定期开启投票、探讨,限时进行,逾期作废。如何无效治理此类过期信息。

解决方案:

  • 对于基于工夫线限定的工作治理,将解决工夫记录为 score 值,利用排序功能辨别解决的先后顺序
  • 记录下一个要解决的工夫,到期后处理对应工作,移除 redis 中的记录,并记录下一个要解决的工夫
  • 当新工作退出时,断定并更新以后下一个要解决的工作工夫
  • 为晋升 sorted_set 的性能,通常将工作依据特色存储成若干个 sorted_set。例如 1 小时内,1 天内,周内,月内,季内,年度等,操作时逐级晋升,将行将操作的若干个工作纳入到 1 小时内解决的队列中
zadd tx 1509802345 uid:1
zadd tx 1509802390 uid:7
zadd tx 1510384284 uid:888

zrange tx 0 -1 withscores
//uid:1
//1509802345
//uid:7
//1509802390
//uid:888
//1510384284

案例:带有权重的工作 / 音讯队列

当工作或者音讯待处理,造成了工作队列或音讯队列时,对于高优先级的工作要保障对其优先解决,如何实现工作权重治理

解决方案:对于带有权重的工作,优先解决权重高的工作,采纳 score 记录权重即可

zadd tasks 4 order:id:5
zadd tasks 1 order:id:425
zadd tasks 9 order:id:345


zrevrange tasks 0 0
//order:id:345

zrem tasks order:id:345

多条件工作权重设定

如果权重条件过多时,须要对排序 score 值进行解决,保障 score 值可能兼容 2 条件或者多条件,

例如外贸订单优先于国内订单,总裁订单优先于员工订单,经理订单优先于员工订单

  • 因 score 长度受限,须要对数据进行阶段解决,尤其是工夫设置为小时或分钟级即可(折算后)
  • 先设定订单类别,后设定订单发动角色类别,整体 score 长度必须是对立的,有余位补 0。第一排序规定首位不得是 0

    • 例如外贸 101,国内 102,经理 004,员工 008
    • 员工下的外贸单 score 值为 101008
    • 经理下的国内单 score 值为 102004
zadd tt 102004 order:id:1
zadd tt 101008 order:id:2

通用指令

Redis 提供了丰盛的命令对数据库和各种数据类型进行操作

1、键值相干的命令
2、服务器相干的命令

key 基本操作

  • DEL 该命令用于在 key 存在时删除 key。

    语法:

    del key
    

    例:

    del name
    
  • EXISTS 判断一个 key 是否存在。

    语法:

    exists key
    

    返回值:

     1 代表存在(示意存在的数量),0 代表不存在
    

    例:

    exists name
    //1
    exists name
    //1
    exists age
    //1
    
  • TYPE 返回 key 所贮存的值的类型。

    语法:

    type key 
    

    例:

    type email 
    //string 
    
    type user:id:2
    //hash 
    
    type user_list
    //list

key 时效性管制

1、为指定 key 设置有效期

  • EXPIRE 为给定 key 设置过期工夫,以秒计。

    语法:

    expire key seconds
    

    例:

    expire user_list 10
    
  • PEXPIRE key milliseconds 设置 key 的过期工夫以毫秒计。
  • EXPIREAT key timestamp

EXPIREAT 的作用和 EXPIRE 相似,都用于为 key 设置过期工夫。
不同在于 EXPIREAT 命令承受的工夫参数是 UNIX 工夫戳(unix timestamp)。

  • PEXPIREAT key milliseconds-timestamp 设置 key 过期工夫的工夫戳(unix timestamp) 以毫秒计

2、获取 key 的无效工夫

  • TTL 以秒为单位,返回给定 key 的残余生存工夫(TTL, time to live)。

    语法:

    ttl key 
    

    例:

    ttl user_list
    
  • PTTL key 以毫秒为单位返回 key 的残余的过期工夫。

3、切换 key 从时效性转换为永久性

  • PERSIST key 移除 key 的过期工夫,key 将长久放弃。

key 查问

1、keys pattern 返回以后数据库外面的键

* 匹配任意数量的任意符号

? 配合一个任意符号

[] 匹配一个指定符号

例:

keys *  查问所有

keys it* 查问所有以 it 结尾

keys *heima 查问所有以 heima 结尾

keys ??heima 查问所有后面两个字符任意,前面以 heima 结尾

keys user:? 查问所有以 user: 结尾,最初一个字符任意

keys u[st]er:1 查问所有以 u 结尾,以 er:1 结尾,两头蕴含一个字母,s 或 t

其余 key 通用操作

  • RENAME key newkey 批改 key 的名称
  • RENAMENX key newkey 仅当 newkey 不存在时,将 key 改名为 newkey
  • sort 对所有 key 排序
  • DUMP key 序列化给定 key,并返回被序列化的值。

db 操作

  • select

    抉择数据库,在 redis 外面默认有 0 -15 号数据库,
    默认在 0 号数据库操作,能够通过 redis.conf 配置文件进行设置

    语法:

    select 数据库的编号
    

    例:

    select 1
    // ok
    
    keys *
    // empty lisr or set
    
    select 0
    // ok 
    
    keys *
    //email
  • MOVE key db 将以后数据库的 key 挪动到给定的数据库 db 当中。

    例:

    move name 1
    
    
  • flushdb (谨慎应用) 清空以后数据库外面所有的键

    例:

    flushdb
    //ok
    keys *
    //empty list or set
  • flushall (谨慎应用) 清空所有数据库外面的所有的键
  • dbsize 返回以后数据库外面键的个数

    例:

    dbsize
    // 8 
    
  • RANDOMKEY 从以后数据库中随机返回一个 key。

正文完
 0