详解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实现订单自动过期功能的示例代码
May 08 Redis
基于Redis实现分布式锁的方法(lua脚本版)
May 12 Redis
redis实现排行榜功能
May 24 Redis
详解缓存穿透击穿雪崩解决方案
May 28 Redis
压缩Redis里的字符串大对象操作
Jun 23 Redis
Redis如何实现分布式锁
Aug 23 Redis
Redis 常见使用场景
Aug 30 Redis
解决linux下redis数据库overcommit_memory问题
Feb 24 Redis
Redis中有序集合的内部实现方式的详细介绍
Mar 16 Redis
一文搞懂Redis中String数据类型
Apr 03 Redis
详解Redis的三种常用的缓存读写策略步骤
May 06 Redis
python中使用redis用法详解
Dec 24 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
ThinkPHP文件缓存类代码分享
2015/04/22 PHP
PHP面向对象程序设计模拟一般面向对象语言中的方法重载(overload)示例
2019/06/13 PHP
Laravel 实现添加多语言提示信息
2019/10/25 PHP
Prototype使用指南之enumerable.js
2007/01/10 Javascript
JS类库Bindows1.3中的内存释放方式分析
2007/03/08 Javascript
用javascript动态调整iframe高度的代码
2007/04/10 Javascript
JavaScript 弹出窗体点击按钮返回选择数据的实现
2010/04/01 Javascript
用javascript为页面添加天气显示实现思路及代码
2013/12/02 Javascript
javascript实时显示北京时间的方法
2015/03/12 Javascript
ECharts仪表盘实例代码(附源码下载)
2016/02/18 Javascript
jQuery自制提示框tooltip改进版
2016/08/01 Javascript
json与jsonp知识小结(推荐)
2016/08/16 Javascript
js实现带三角符的手风琴效果
2017/03/01 Javascript
bootstrap fileinput插件实现预览上传照片功能
2018/01/23 Javascript
React项目动态设置title标题的方法示例
2018/09/26 Javascript
详解Vue的常用指令v-if, v-for, v-show,v-else, v-bind, v-on
2018/10/12 Javascript
vue实现打地鼠小游戏
2020/08/21 Javascript
vue或react项目生产环境去掉console.log的操作
2020/09/02 Javascript
Python使用numpy实现BP神经网络
2018/03/10 Python
python读取中文txt文本的方法
2018/04/12 Python
python切片及sys.argv[]用法详解
2018/05/25 Python
python应用Axes3D绘图(批量梯度下降算法)
2020/03/25 Python
解决Jupyter因卸载重装导致的问题修复
2020/04/10 Python
python 将视频 通过视频帧转换成时间实例
2020/04/23 Python
浅谈CSS3中的变形功能-transform功能
2017/12/27 HTML / CSS
印尼在线精品店:Berrybenka.com
2016/10/22 全球购物
英国经典球衣网站:Classic Football Shirts
2017/05/20 全球购物
Smashbox英国官网:美国知名彩妆品牌
2017/11/13 全球购物
初中音乐教学反思
2014/01/12 职场文书
售后求职信范文
2014/03/15 职场文书
个人承诺书怎么写
2014/05/24 职场文书
党员自我评议对照检查材料
2014/09/27 职场文书
关于办理居住证的介绍信模板
2019/11/27 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
2021/10/16 HTML / CSS
Redis主从复制操作和配置详情
2022/09/23 Redis