详解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 相关文章推荐
Redis如何一键部署脚本
Apr 12 Redis
redis不能访问本机真实ip地址的解决方案
Jul 07 Redis
SpringBoot集成Redis的思路详解
Oct 16 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
Redis模仿手机验证码发送的实现示例
Nov 02 Redis
解决linux下redis数据库overcommit_memory问题
Feb 24 Redis
Redis 操作多个数据库的配置的方法实现
Mar 23 Redis
Redis分布式锁的7种实现
Apr 01 Redis
redis调用二维码时的不断刷新排查分析
Apr 01 Redis
Redis实现订单过期删除的方法步骤
Jun 05 Redis
Redis批量生成数据的实现
Jun 05 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基础知识:类与对象(3) 构造函数和析构函数
2006/12/13 PHP
php设计模式 Singleton(单例模式)
2011/06/26 PHP
PHP获取youku视频真实flv文件地址的方法
2014/12/23 PHP
精解window.setTimeout()&amp;window.setInterval()使用方式与参数传递问题!
2007/11/23 Javascript
JavaScript入门教程(9) Document文档对象
2009/01/31 Javascript
jquery 模式对话框终极版实现代码
2009/09/28 Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
2009/10/26 Javascript
基于JQuery的动态删除Table表格的行和列的代码
2011/05/12 Javascript
JS判断当前日期是否大于某个日期的实现代码
2012/09/02 Javascript
判断在css加载完毕后执行后续代码示例
2014/09/03 Javascript
alert出数组中的随即值代码
2014/09/25 Javascript
jquery实现页面关键词高亮显示的方法
2015/03/12 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
2015/04/12 Javascript
jquery+html5烂漫爱心表白动画代码分享
2015/08/24 Javascript
原生javascript实现图片无缝滚动效果
2016/02/12 Javascript
在ASP.NET MVC项目中使用RequireJS库的用法示例
2016/02/15 Javascript
移动端横屏的JS代码(beta)
2016/05/16 Javascript
通过vue-cli来学习修改Webpack多环境配置和发布问题
2017/12/22 Javascript
小程序实现左滑删除效果
2019/07/25 Javascript
python 运算符 供重载参考
2009/06/11 Python
python概率计算器实例分析
2015/03/25 Python
Python循环语句之break与continue的用法
2015/10/14 Python
Numpy截取指定范围内的数据方法
2018/11/14 Python
对python自动生成接口测试的示例讲解
2018/11/30 Python
python 划分数据集为训练集和测试集的方法
2018/12/11 Python
python简单贪吃蛇开发
2019/01/28 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
Python 调用 Outlook 发送邮件过程解析
2019/08/08 Python
新年福利来一波之Python轻松集齐五福(demo)
2020/01/20 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
Python 忽略文件名编码的方法
2020/08/01 Python
AVIS安飞士奥地利租车官网:提供奥地利、欧洲和全世界汽车租赁
2016/11/29 全球购物
什么是Deployment descriptors;都有什么类型的部署描述符
2015/07/28 面试题
党务公开方案
2014/05/06 职场文书
健康教育评估方案
2014/05/25 职场文书
Nginx跨域问题解析与解决
2022/08/05 Servers