Redis 数据特性和SORT命令

一、位图(bitmap)

      Redis 中的位图(也称位数组或位向量)是由多个二进制位组成的数组结构。

      Redis 中的 bitmap 不是一种新的数据类型,实际上它的底层仍然是字符串,因为字符串本质上是二进制大对象(BLOB, Binary Large Object),所有字符串也可以视作位图。

      Redis 中的 bitmap 因为直接用bit位来保存数据,每一位所在的位置为偏移量(offset),用户可以在bitmap上可执行AND,OR,XOR以及其它位操作。所以某些情况下可以节省内存空间。 

     位图(bitmap)的应用场景可以实现用户上线次数统计、活跃用户统计,查询最近n天的打卡次数等

对于位数组我们可以做以下操作:

  • 设置其中某一个位的为1或者是0。
  • 统计当前位数组中有多少个1。
  • 获取指定下标的位值。
  • 获取第一个1或者是0的位下标。
  • 获取某一段区域内的位数组所对应的数值。

基本命令

1、SETBIT 命令

命令描述
SETBIT key offset value设置或者清空key的value(字符串)在offset处的bit值。返回值:返回在offset处原来的bit值。

设置一个字符串,第6个offset从0设置为1,第7个offset从1设置为0,则a就变成b.

a的ASCII码是97。转换为二进制是:01100001。

b的ASCII码是98,转换为二进制是:01100010。

c的ASCII码是99,转换为二进制是:01100011。

127.0.0.1:6379[1]> set kbitmap a
OK
127.0.0.1:6379[1]> setbit kbitmap 6 1
(integer) 0
127.0.0.1:6379[1]> get kbitmap
"c"
127.0.0.1:6379[1]> setbit kbitmap 7 0
(integer) 1
127.0.0.1:6379[1]> get kbitmap
"b"

2、BITCOUNT 命令

命令描述
BITCOUNT key [start end]统计字符串在指定起始位置被设置为1的bit数。如果key不存在,则返回0.
127.0.0.1:6379[1]> bitcount kbitmap
(integer) 3

3、GETBIT 命令

命令描述
GETBIT key offset返回key对应的string在offset处的bit值
127.0.0.1:6379[1]> getbit kbitmap 6
(integer) 1

4、BITOP 命令

命令描述
BITOP operation destkey key [key ...]

对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作。

返回值:保存到 destkey 的字符串的长度,和输入 key 中最长的字符串长度相等。

127.0.0.1:6379[1]> set kbit2 abcd1234
OK
127.0.0.1:6379[1]> bitop and kbitOR kbitmap kbit2
(integer) 8

  二、设置键的生存时间或过期时间

       在经过指定的生存时间(Time To Live , TTL)之后,redis可以自动删除对应的key-value,默认情况下键是没有生存时间的,也就是永不过期,除非清空内存。

       通过下面命令设置和查看生存时间,通常用 EXPIRE 命令单位到秒就可以了

命令描述
EXPIRE key seconds

设置key的生存时间,超过时间后,将会自动删除该key。以秒为单位

  • 设置成功,返回 1
  • key 不存在或设置失败,返回 0
PEXPIRE key milliseconds

设置key的生存时间,以毫秒为单位

  • 设置成功,返回 1
  • key 不存在或设置失败,返回 0
EXPIREAT key timestamp

设置一个UNIX时间戳的生存时间,以秒为单位

  • 如果生存时间设置成功,返回 1 。
  • 当 key 不存在或没办法设置生存时间时,返回 0 。 (查看: EXPIRE命令获取更多信息).
PEXPIREAT key milliseconds-timestamp

设置一个UNIX时间戳的生存时间,以毫秒为单位

  • 如果生存时间设置成功,返回 1 。
  • 当 key 不存在或没办法设置生存时间时,返回 0 。 (查看: EXPIRE命令获取更多信息).
TTL key

获取key的有效时间(单位:妙)

  • 如果key不存在或者已过期,返回 -2
  • 如果key存在并且没有设置过期时间(永久有效),返回 -1 。
PTTL key

获取key的有效时间(单位:毫妙)

  • 如果key不存在或者已过期,返回 -2
  • 如果key存在并且没有设置过期时间(永久有效),返回 -1 。
PERSIST key

移除给定key的生存时间

  • 当生存时间移除成功时,返回 1 .
  • 如果 key 不存在或 key 没有设置生存时间,返回 0 .

实例:

127.0.0.1:6379> set kttl asd123
OK
127.0.0.1:6379> ttl kttl
(integer) -1
127.0.0.1:6379> expire kttl 15
(integer) 1
127.0.0.1:6379> ttl kttl
(integer) 8
127.0.0.1:6379> get kttl
(nil)
127.0.0.1:6379> set kttl2 adsf
OK
127.0.0.1:6379> expire kttl2 50
(integer) 1
127.0.0.1:6379> ttl kttl2
(integer) 35
127.0.0.1:6379> persist kttl2
(integer) 1
127.0.0.1:6379> ttl kttl2
(integer) -1

 三、使用 SORT命令

      Redis 中的列表list和集合set都是无序保存的,有序set集合也只是对权重值进行排序,不是对元素本身。如果需要对元素本身进行排序,需要使用 sort命令。redis支持对list,set,sorted set元素的排序。

命令SORT key [BY pattern] [LIMIT offset count] [GET pattern] [ASC|DESC] [ALPHA] destination

描述

返回或存储key的list、 set 或sorted set 中的元素。默认是按照数值类型排序的,并且按照两个元素的双精度浮点数类型值进行比较。

返回值:返回排序后的元素列表。

1、 一般 SORT 用法:sort key [ASC|DESC] (list)

      这是最简单的情况,没有任何选项对集合自身元素排序并返回排序结果,默认以value升序(asc)。逆序使用desc选项。

127.0.0.1:6379> lpush ksort1 15 12 2 16 3
(integer) 5
127.0.0.1:6379> lrange ksort1 0 -1
1) "3"
2) "16"
3) "2"
4) "12"
5) "15"
127.0.0.1:6379> sort ksort1 desc
1) "16"
2) "15"
3) "12"
4) "3"
5) "2"
127.0.0.1:6379> lrange ksort1 0 -1
1) "3"
2) "16"
3) "2"
4) "12"
5) "15"

2、使用 ALPHA 修饰符对字符串进行排序: [ASC|DESC] [ALPHA]  (list)     

     sort 默认以数值排序,字母使用默认的sort排序,会报错,想按字母顺序排必须加上 alpha选项。

127.0.0.1:6379> rpush ksort2 abcd  abef jlkl sdls bbb
(integer) 5
127.0.0.1:6379> lrange ksort2 0 -1
1) "abcd"
2) "abef"
3) "jlkl"
4) "sdls"
5) "bbb"
127.0.0.1:6379> sort ksort2
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> sort ksort2 alpha desc
1) "sdls"
2) "jlkl"
3) "bbb"
4) "abef"
5) "abcd"

3、使用 LIMIT 修饰符限制返回结果:[[LIMIT offset count]

    LIMIT 选项可以限定返回结果的数量。 修饰符接受 offset 和 count 两个参数,offset 下标是从 0 开始。

127.0.0.1:6379> sort ksort2 alpha limit 1 3
1) "abef"
2) "bbb"
3) "jlkl"

4、使用外部 key 进行排序:[BY pattern]

      除了可以按集合元素自身值(数字,字母)排序外,还可以将集合元素内容按照给定pattern组合成新的key,并按照新key中对应的内容进行排序。

假设现在有用户数据如下:

     

127.0.0.1:6379> lpush uid 1 2 3 4
(integer) 4
127.0.0.1:6379> mset user_name_1 admin user_name_2 jack user_name_3 peter user_name_4 mary
OK
127.0.0.1:6379> mset user_level_1 9999 user_level_2 10 user_level_3 25 user_level_4 70
OK

BY 选项

默认情况下, SORT uid 直接按 uid 中的值排序:

127.0.0.1:6379> sort uid by user_levle_*
1) "1"
2) "2"
3) "3"

通过使用 BY 选项,可以让 uid 按其他键的元素来排序。 比如: 按照 user_level_{uid} 的大小来降序排序:

127.0.0.1:6379> sort uid by user_level_* desc
1) "1"
2) "4"
3) "3"
4) "2"

GET 选项

上面的例子都是返回的集合中的数值元素,使用 GET 选项, 可以根据排序的结果来取出相应的键值。

 get选项可以有多个,# 特殊符号 获取 GET 元素本身

127.0.0.1:6379> sort uid by user_level_* desc get # get user_name_* get user_level_*
 1) "1"
 2) "admin"
 3) "9999"
 4) "4"
 5) "mary"
 6) "70"
 7) "3"
 8) "peter"
 9) "25"
10) "2"
11) "jack"
12) "10"

获取外部键,但不进行排序

通过将一个不存在的键作为参数传给 BY 选项, 可以让 SORT 跳过排序操作, 直接返回结果。

通常将这种用法和 GET 选项配合, 就可以在不排序的情况下, 获取多个外部键, 相当于执行一个整合的获取操作

127.0.0.1:6379> sort uid by user_notkey desc get # get user_name_* get user_level_*
 1) "1"
 2) "admin"
 3) "9999"
 4) "2"
 5) "jack"
 6) "10"
 7) "3"
 8) "peter"
 9) "25"
10) "4"
11) "mary"
12) "70"

将哈希表作为 GET 或 BY 的参数

除了可以将字符串键之外, 哈希表也可以作为 GET 或 BY 选项的参数来使用。字符串 -> 用于区分key名称和哈希属性的名称。

127.0.0.1:6379> HMSET user_info_1 name admin level 9999
OK
127.0.0.1:6379> HMSET user_info_2 name jack level 10
OK
127.0.0.1:6379> HMSET user_info_3 name peter level 25
OK
127.0.0.1:6379> HMSET user_info_4 name mary level 70
OK
127.0.0.1:6379> sort uid by user_info_*->level desc get # get user_info_*->level get user_info_*->name
 1) "1"
 2) "9999"
 3) "admin"
 4) "4"
 5) "70"
 6) "mary"
 7) "3"
 8) "25"
 9) "peter"
10) "2"
11) "10"
12) "jack"

5、保存排序结果: STORE resultkey

    默认情况下, SORT 操作只是简单地返回排序结果,并不进行任何保存操作。

    SORT ... STORE的一种有趣应用模式,是联合 EXPIRE 超时命令返回key,以便在应用中可以缓存SORT操作的返回结果。 其他客户端将会使用已缓存的列表,代替每个请求的 SORT 调用。当key即将过期时,一个更新版本的缓存将会通过 SORT ... STORE 再次创建。如果被指定的 key 已存在,那么原有的值将被排序结果覆盖。

127.0.0.1:6379> sort uid by user_info_*->level desc get # get user_info_*->level get user_info_*->name store ksortsave
(integer) 12
127.0.0.1:6379> lrange ksortsave 0 -1
 1) "1"
 2) "9999"
 3) "admin"
 4) "4"
 5) "70"
 6) "mary"
 7) "3"
 8) "25"
 9) "peter"
10) "2"
11) "10"
12) "jack"

四、在Redis中使用管道

 Redis是一种基于客户端--服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:

1.客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。

2.服务器接收到客户端的请求命令,放入到执行队列等待执行(Redis是单线程的执行模式)

3.执行命令,获取到查询结果

4.服务器将结果返回给客户端

上面的4个步骤消耗的所有时间,称为往返时间(RTT),

2、3两步的时间(a时间)消耗取决于Redis服务器本身,

1、4两步的时间(b时间)消耗取决于客户端和服务端直接的网络延迟,

Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。管道技术最显著的优势是提高了 redis 服务的性能。如果我们想要节约总的往返时间,可以把多条命令集中传给Redis,Redis把命令的执行结果最终一次性地在集中返回给客户端,这个就是Redis管道的基本思想!

实例:

[root@centos7 redis]# cat ./pipeline.txt 
set mykey1  myvalue1
set mykey2  myvalue2
set mykey3  myvalue3
set mykey4  myvalue4
[root@centos7 redis]# cat ./pipeline.txt | /usr/local/redis/bin/redis-cli --pipe 
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 4
[root@centos7 redis]# ./bin/redis-cli 
127.0.0.1:6379> get mykey1
"myvalue1"

五、Redis的事务(了解)

    在关系型数据库中,把多条sql命令整合成一个事务,要么都执行成功,要么都执行失败。关系型数据库中事务的目的是保证数据的完整性,安全。Redis中的事务完全不是一回事,Redis的事务只是为了让Redis命令批量化执行。

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。
命令描述
MULTI标记一个事务块的开始。 Redis会将后续的命令逐个放入队列中,然后使用EXEC命令原子化地执行这个命令序列。。返回值:始终为OK
EXEC执行所有 MULTI 之后发的命令。不存在回滚,遇到错误就报错,但是会继续执行后面的语句。
DISCARD清除所有 MULTI 之后发的命令,然后恢复正常的连接状态。返回值所有返回都是 OK

实例:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 lisi
QUEUED
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 houzi
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "houzi"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> EXEC
(error) ERR EXEC without MULTI

六、Redis的pub/sub

      Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

      在这个模式中,发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端), 而是将信息发送给频道(channel), 然后由频道将信息转发给所有对这个频道感兴趣的订阅者。

     

      一旦客户端进入订阅状态,客户端就只可接受订阅相关的命令SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE和PUNSUBSCRIBE除了这些命令,其他命令一律失效。

命令描述
SUBSCRIBE channel [channel ...]监听频道发布的信息
UNSUBSCRIBE [channel [channel ...]]停止频道监听,若没有指定频道,则退订所有频道。
PSUBSCRIBE pattern [pattern ...]订阅给定的模式(patterns)。

支持的模式(patterns)有:

  • h?llo subscribes to hellohallo and hxllo
  • h*llo subscribes to hllo and heeeello
  • h[ae]llo subscribes to hello and hallo, but not hillo

如果想输入普通的字符,可以在前面添加\

PUNSUBSCRIBE [pattern [pattern ...]]若果没有提供模式则退出所有模式。,如果没有提供模式则退出所有模式。
PUBLISH channel message发送一条message 到频道 channel,返回值: 收到消息的客户端数量。

简单实例:两个客户端订阅者,一个发布者,这里没有使用指定模式。

订阅者1和2

127.0.0.1:6379> SUBSCRIBE channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "publish channel111 message content"
127.0.0.1:6379> SUBSCRIBE channel1 channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "subscribe"
2) "channel2"
3) (integer) 2
1) "message"
2) "channel1"
3) "publish channel111 message content"
1) "message"
2) "channel2"
3) "publish channe2222 message content"

发布者

127.0.0.1:6379> publish channel1 "publish channel111 message content"
(integer) 2
127.0.0.1:6379> publish channel2 "publish channe2222 message content"
(integer) 1

七、在Redis中运行 Lua脚本(先简单了解)

首先在 Redis中安装Lua: 官网下载安装包:http://www.lua.org/

注意:要确保安装 Lua 之前系统已安装 readline 和 readline-devel。

安装:make linux test    

测试,命令行中键入 lua -v

[root@centos7 ~]# yum install -y readline readline-devel
...
[root@centos7 ~]# tar -zxvf lua-5.3.5.tar.gz 
[root@centos7 ~]# cd lua-5.3.5/
[root@centos7 lua-5.3.5]# make linux test
[root@centos7 lua-5.3.5]# lua -v
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
命令描述
EVAL script numkeys key [key ...] arg [arg ...]

执行 Lua 脚本。

EVAL的第一个参数是一段 Lua 5.1 脚本程序。 这段Lua脚本不需要(也不应该)定义函数。它运行在 Redis 服务器中。

EVAL的第二个参数是参数的个数,后面的参数(从第三个参数),表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。

在命令的最后,那些不是键名参数的附加参数 arg [arg …] ,可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。

 实例:

127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

 

    参考文章:Redis sort 排序命令详解
 

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值