详解Redis基本命令与使用场景


Posted in Redis onJune 01, 2021

Redis和Memcached对比

其中有一个比较重要的区别是关于其提供的数据结构区别

Memcached

在其数据结构中仅使用字符串和整数。因此,您保存的所有内容都可以是字符串或整数。它很复杂,因为对于整数,您可以做的唯一数据操作是添加或减去它们。如果需要保存数组或对象,则必须先将它们序列化然后保存。要阅读它们,您需要取消序列化。

Redis

具有更强大的数据结构,它不仅可以处理字符串整数,还可以处理二进制安全字符串,二进制安全字符串列表,二进制安全字符串集和有序集。

关于Redis的数据结构:https://zhuanlan.zhihu.com/p/270592490

基本命令

# 如果k1的值设置过,就不设置,如果k1的值没有设置,才会设置k1的值为hello

# msetnx 同理

set k1 hello nx

 

# 如果k2没设置,就不能设置k2的值为hello,如果k2的值设置过,才能把他设置过hello

set k2 hello xx

 

# 设置多个值,其中把k1设置xx,把k2设置为33

mset k1 xx k2 33

 

# 拼接字符串

APPEND k1 " world"

 

# 范围查找(从0开始)

GETRANGE k1 0 1

 

# 范围查找(逆序,最右边编号从-1开始)

# 所以0,-1 就是拿到整个字符串

GETRANGE k1 0 -1

 

# 把k1字符串的第1个(从第0个位置开始)用xxx开始替换后续的字符

# 如果k1是hello,那么执行完下面的语句,k1会被设置为:hxxxo

SETRANGE k1 1 xxx

 

# 获取k1字符串的长度

STRLEN k1

 

# 获取数据类型

TYPE k1

 

# 查询某个命令的使用,如下命令,就是查询SET命令如何使用

help SET

 

# k1的值+1

INCR k1

 

# k1的值+22

INCRBY k1 22

 

# k1的值-1

DECR k1

 

# k1的值-22

DECRBY k1 22

 

# k1的值+0.5

INCRBYFLOAT k1 0.5

 

# 可以使用--raw选项在终端上强制进行原始输出

127.0.0.1:6379> set k3 中

OK

127.0.0.1:6379> get k3

"\xe4\xb8\xad"

127.0.0.1:6379> exit

[root@node1 utils]# redis-cli --raw

127.0.0.1:6379> get k3

 

# 获取k1的值,然后把k1的值设置为hello

GETSET k1 hello

 

# 设置k1的值为a,如果要把k1的值变为b,也可以通过setbit操作

# 也就是将 01100001 变成 01100010 (a的ASCII码是97,b的ASCII码是98),也就是将'a'中的offset 6从0变成1,将offset 7 从1变成0  (从0开始算)

set k1 a

setbit k1 6 1

setbit k1 7 0

 

# 查找字符串里面bit值为1的位置 (从左边开始数)

set k1 a

bitpos k1 1

结果为:1

 

# bitpos的 start end指的是字节位置

# 查找字符串里面bit值为1从第0个字节开始的位置

set k1 ab

BITPOS k1 1 0

1

 

# 查找字符串里面bit值为0从第1个字节开始的位置

# 其中9的ASCII码为00111001 a的ascii码为01100001

# 所以a9的ASCII码为01100001 00111001

# BITPOS k1 0 1取的位置就是:01100001 ‘0'0111001 中‘'圈住的位置

set k1 a9

BITPOS k1 0 1

9

 

 

# BITPOS找不到则返回-1

# 例如:查找字符串里面bit值为1的位置

set k1 "\x00\x00\x00"

BITPOS k1 1

-1

 

# bitcount统计的是1的数量, bitcount key [start, end] , 其中的start和end指的是byte位置而非bit位置。

# a的ASCII码为01100001

set k1 a

bitcount k1

3

场景1:统计每个用户的登录天数

假设jack这名用户,分别在第6天,第23天,第134天,和第364天登录了系统。

可以执行如下命令:

setbit jack 6 1setbit jack 23 1setbit jack 134 1setbit jack 364 1

统计jack登录的天数,直接可以通过:

bitcount jack

场景2:电商网站派发礼物

假设某个电商网站做活动,在某天要派送礼物,假设这个网站有2亿用户,请问应该备货多少礼物比较适合

思路:

首先,可以考虑一下统计整个网站的活跃用户有多少,比如我们设置三天,1号,2号,3号,统计三天登录的用户获得一个近似的活跃用户的数量:

# 编号为2的用户登在2019年1月1号录了一次

setbit 20190101   2  1

# 编号为3的用户在2019年1月2号登录了一次

setbit 20190102   3  1

# 编号为7的用户在2019年1月2号登录了一次

setbit 20190102   7  1

# 编号为7的用户在2019年1月3号登录了一次

setbit 20190103   7  1

然后通过:

# 将每一天标识的人数(位置上为1)的数进行与运算

bitop  or   destkey 20190101  20190102  20190103

然后求这个destkey中含有的1的数量,即为比较活跃的用户(派发礼物需要准备的礼物数量)

BITCOUNT destkey

抢购,秒杀,详情页,点赞,评论

都可以使用Redis的incr 方法,这样就可以规避并发下,对数据库的事务操作,完全由redis内存操作代替

更多命令

# lpush和lpop搭配可以实现栈的功能

# lpush和rpop搭配可以实现队列的功能

# 从左边进

lpush k1 a b c

# 从左边弹出

lpop k1

c

 

# lrange可以从左到右列出元素

lpush k1 a b c

lrange k1

1) "c"

2) "b"

3) "a"

 

# lindex 可以定位某个元素(从左边开始,从0开始)

lindex k1 0

"c"

 

# lset 可以设置某个位置的元素

lset k1 0 xxxxx

lrange k1 0 -1

1) "xxxxx"

2) "b"

3) "a"

 

#LREM key count value

#根据参数 count 的值,移除列表中与参数 value 相等的元素。

#count 的值可以是以下几种:

#count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。

#count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。

#count = 0 : 移除表中所有与 value 相等的值。

 

LREM k3 2 a

 

# LINSERT 

lpush k1 a b c d e f g

linsert k1 after b 6 # 也可以用before

lrange k1 0 -1

1) "g"

2) "f"

3) "e"

4) "d"

5) "c"

6) "b"

7) "6"

8) "a"# lpush和lpop搭配可以实现栈的功能

# lpush和rpop搭配可以实现队列的功能

# 从左边进

lpush k1 a b c

# 从左边弹出

lpop k1

c

 

# lrange可以从左到右列出元素

lpush k1 a b c

lrange k1

1) "c"

2) "b"

3) "a"

 

# lindex 可以定位某个元素(从左边开始,从0开始)

lindex k1 0

"c"

 

# lset 可以设置某个位置的元素

lset k1 0 xxxxx

lrange k1 0 -1

1) "xxxxx"

2) "b"

3) "a"

 

 

 

 

#当 BLPOP被调用时,如果给定 key 内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字 key 一起,组成结果返回给调用者。

# BLPOP可以实现单播FIFO队列

blpop x y z 0

 

# 打开另外一个redis-cli

# 然后执行

lpush y xxxsd

 

# 可以看到blpop x y z 0

# 返回了参数

blpop x y z 0

1) "y"

2) "xxxsd"

 

# blpop 最后一个参数是超时时间,如果设置为0,则不超时

 

# trim掉第三号元素之前和第五号元素之后的元素,从左边第0个位置开始算

 

lpush k1 a b c d e f g

(integer) 15

ltrim k1 1 3

OK

lrange k1 0 -1

1) "f"

2) "e"

3) "d"

 

# Hash

hset person name zs

(integer) 1

hset person age 18 address GZ

(integer) 2

hmget person name age address

1) "zs"

2) "18"

3) "GZ"

 

hkeys person

1) "name"

2) "age"

3) "address"

 

hvals person

1) "zs"

2) "18"

3) "GZ"

 

hgetall person

1) "name"

2) "zs"

3) "age"

4) "18"

5) "address"

6) "GZ"

 

hincrbyfloat person age 0.5

"18.5"

 

hincrbyfloat person age -1

"17.5"

 

sadd k1 a  b c a

(integer) 3

 

smembers k1

1) "b"

2) "a"

3) "c"

 

srem k1 a

(integer) 1

smembers k1

1) "b"

2) "c"

 

# 交集sinter,类似的,还有并集:sunion,差集:sdiff

# sinerstore k k1 k2 将k1和k2交集后的元素存入k

sadd k1 a b c

SMEMBERS k1

1) "a"

2) "c"

3) "b"

sadd k2 a b d

(integer) 3

SINTER k1 k2

1) "a"

2) "b"

SUNION k1 k2

1) "a"

2) "d"

3) "b"

4) "c"

SDIFF k1 k2

"c"

 

#SRANDMEMBER 命令接受可选的 count 参数:

#如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。

#如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

# 可以用来抽奖

SRANDMEMBER k3 -3

1) "b"

2) "b"

3) "c"

 

#有序集

#sorted_set

#Z开头的命令,ZADD,ZCOUNT

 

zadd fruit 8 apple 2 banana 3 orange

zrange fruit 0 -1

1) "banana"

2) "orange"

3) "apple"

zrange fruit 0 -1 withscores

1) "banana"

2) "2"

3) "orange"

4) "3"

5) "apple"

6) "8"

 

zcount fruit 3 8

(integer) 2

zscore fruit apple

"8"

 

#价格由低到高取出前两位

zarange k1 0 1

 

#价格由高到低取出前两位

zrevarange k1 0 1

 

zscore fruit apple

"8"

zrank fruit banana

0

 

zincrby fruit 2.5 banana

"4.5"

 

127.0.0.1:6379> zadd k1 2 a 3 b 4 c

(integer) 3

127.0.0.1:6379> zadd k2 3 a 1 b 2 c

(integer) 3

127.0.0.1:6379> ZUNIONSTORE k4 2 k1 k2

(integer) 3

127.0.0.1:6379> zrange k4 0 -1

1) "b"

2) "a"

3) "c"

127.0.0.1:6379> ZUNIONSTORE k4 2 k1 k2 aggregate sum

(integer) 3

127.0.0.1:6379> zrange k4 0 -1

1) "b"

2) "a"

3) "c"

127.0.0.1:6379> ZUNIONSTORE k4 2 k1 k2 aggregate max

(integer) 3

127.0.0.1:6379> zrange k4 0 -1

1) "a"

2) "b"

3) "c"

127.0.0.1:6379> ZUNIONSTORE k4 2 k1 k2 aggregate min

(integer) 3

127.0.0.1:6379> zrange k4 0 -1

1) "b"

2) "a"

3) "c"

通过管道连接Redis发送命令

yum install nc

[root@node01 ~]# nc localhost 6379

keys *

*0

set k1 heelo

+OK

 

 

[root@node1 utils]# echo -e "set k2 99\nincr k2\n get k2" | nc localhost 6379

+OK

:100

$3

100

发布/订阅功能

127.0.0.1:6379> subscribe xxx

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "xxx"

3) (integer) 1

1) "message"

2) "xxx"

3) "hellod"

 

 

127.0.0.1:6379> publish xxx hellod

(integer) 1

如果需要考虑获取实时数据和历史数据

关于实时数据

  • pub/sub功能关于历史消息
  • 三天前(sorted_set)
  • 更早以前(来自数据库)

架构如下:

详解Redis基本命令与使用场景

Redis的事务

执行顺序

详解Redis基本命令与使用场景

示例

127.0.0.1:6379> MULTI

OK

127.0.0.1:6379(TX)> set k1 aa

QUEUED

127.0.0.1:6379(TX)> set k2 ddd

QUEUED

127.0.0.1:6379(TX)> exec

1) OK

2) OK

watch用法

127.0.0.1:6379> watch k1

OK

127.0.0.1:6379> MULTI

OK

127.0.0.1:6379(TX)> get k1

QUEUED

127.0.0.1:6379(TX)> keys *

QUEUED

127.0.0.1:6379(TX)> exec

(nil)

另外一个客户端

127.0.0.1:6379> MULTI

OK

127.0.0.1:6379(TX)> keys *

QUEUED

127.0.0.1:6379(TX)> set k1 ddsdfasdf

QUEUED

127.0.0.1:6379(TX)> exec

1) (empty array)

2) OK

为什么 Redis 的事务不支持回滚(roll back)

摘自:http://www.redis.cn/topics/transactions.html

如果你有使用关系式数据库的经验, 那么 “Redis 在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。

以下是这种做法的优点:

Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。 举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

以上就是详解Redis基本命令与使用场景的详细内容,更多关于Redis基本命令与使用场景的资料请关注三水点靠木其它相关文章!

Redis 相关文章推荐
在K8s上部署Redis集群的方法步骤
Apr 27 Redis
详解Redis主从复制实践
May 19 Redis
浅谈redis缓存在项目中的使用
May 20 Redis
redis实现的四种常见限流策略
Jun 18 Redis
redis缓存存储Session原理机制
Nov 20 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
redis调用二维码时的不断刷新排查分析
Apr 01 Redis
Redis高并发缓存架构性能优化
May 15 Redis
解决 redis 无法远程连接
May 15 Redis
浅谈Redis变慢的原因及排查方法
Jun 21 Redis
一文教你快速生成MySQL数据库关系图
Jun 28 Redis
Redis唯一ID生成器的实现
Jul 07 Redis
Django使用redis配置缓存的方法
Jun 01 #Redis
详解Redis集群搭建的三种方式
May 31 #Redis
浅谈Redis主从复制以及主从复制原理
5分钟教你docker安装启动redis全教程(全新方式)
May 29 #Redis
详解缓存穿透击穿雪崩解决方案
浅谈Redis的几个过期策略
May 27 #Redis
Redis Cluster 字段模糊匹配及删除
May 27 #Redis
You might like
PHP 网页过期时间的控制代码
2009/06/29 PHP
PHP 反向排序和随机排序代码
2010/06/30 PHP
深入解析php之sphinx
2013/05/15 PHP
php之CodeIgniter学习笔记
2013/06/17 PHP
ubuntu12.04使用c编写php扩展模块教程分享
2013/12/25 PHP
PHP $_FILES中error返回值详解
2014/01/30 PHP
JS异常处理try..catch语句的作用和实例
2014/05/05 PHP
10个简化PHP开发的工具
2014/12/25 PHP
php文件扩展名判断及获取文件扩展名的N种方法
2015/09/12 PHP
thinkphp制作404跳转页的简单实现方法
2016/09/22 PHP
PHP7.1方括号数组符号多值复制及指定键值赋值用法分析
2016/09/26 PHP
PHP对象的浅复制与深复制的实例详解
2017/10/26 PHP
XAMPP升级PHP版本实现步骤解析
2020/09/04 PHP
jquery Mobile入门—多页面切换示例学习
2013/01/08 Javascript
js加载读取内容及显示与隐藏div示例
2014/02/13 Javascript
[js高手之路]从原型链开始图解继承到组合继承的产生详解
2017/08/28 Javascript
webpack+vue中使用别名路径引用静态图片地址
2017/11/20 Javascript
Angular自定义组件实现数据双向数据绑定的实例
2017/12/11 Javascript
element 结合vue 在表单验证时有值却提示错误的解决办法
2018/01/22 Javascript
iview table高度动态设置方法
2018/03/14 Javascript
Node.js文件编码格式的转换的方法
2018/04/27 Javascript
node.js中TCP Socket多进程间的消息推送示例详解
2018/07/10 Javascript
详解使用angular框架离线你的应用(pwa指南)
2019/01/31 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python函数参数类型*、**的区别
2015/04/11 Python
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
2017/06/27 Python
python环境路径配置以及命令行运行脚本
2019/04/02 Python
Python 经典算法100及解析(小结)
2019/09/13 Python
django模型动态修改参数,增加 filter 字段的方式
2020/03/16 Python
pyspark 随机森林的实现
2020/04/24 Python
recorder.js 基于Html5录音功能的实现
2020/05/26 HTML / CSS
介绍一下常见的木马种类
2014/11/15 面试题
大学共青团员个人自我评价
2014/04/16 职场文书
贷款担保申请书
2014/05/20 职场文书
计算机实训心得体会
2016/01/14 职场文书