Redis学习笔记

Redis学习笔记

1. 基本安装

1.1 linux安装

vagrant centos7虚拟机

从官网下载redis文件,将文件移动到/opt目录下解压

mv redis-6.2.7.tar.gz /opt # 移动到/opt目录下
tar -zxvf redis-6.2.7.tar.gz # 解压
yum install gcc-c++ #安装gcc
cd redis-6.2.7
make # 编译
make install # 确认编译

在这里插入图片描述

备份和编辑redis.config文件

备份

cd /usr/local/bin/ #进入该目录
mkdir kconfig # 创建目录
cp /opt/redis-6.2.7/redis.config /usr/local/bin/kconfig # 移动到目标目录

编辑

vi kconfig/redis.config # 当前目录 /usr/local/bin/ 与kconfig同目录 

开启进程守护,即可以后台运行 daemonize yes

在这里插入图片描述

2. 运行redis

运行命令

cd /usr/local/bin #
redis-server kconfig/redis.config # 通过指定的端口运行redis-server
ps -ef|grep redis # 查看redis进程

在这里插入图片描述

关闭服务

shutdown

3. 基本知识

redis 默认16个数据库

数据库的操作

SELECT NUMBER # 切换数据库
DBSIZE # 查看数据库大小
FLUSHALL # 清空所有数据库
FLUSHDB # 清空当前数据库

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4. 五大数据类型

4.1 Redis-Key

get 获取key的值

set

move 移除key

keys * 查看所有keys当前的数据库

EXPIRE key db 设置key的过期时间

ttl key 查看key过期的剩余时间

type key 查看key数据类型

get/set
在这里插入图片描述

移除key

在这里插入图片描述

过期设置

在这里插入图片描述

4.2 String

127.0.0.1:6379> set k v  # 设置key
OK
127.0.0.1:6379> APPEND k "zsl" # 在k的内容后面添加字符串
(integer) 4
127.0.0.1:6379> EXISTS k # 查看是否存在这个key
(integer) 1
127.0.0.1:6379> get k
"vzsl"
127.0.0.1:6379> STRLEN k # key长度
(integer) 4
127.0.0.1:6379>

########步长

127.0.0.1:6379> set v 0
OK
127.0.0.1:6379> incr v # 自增1
(integer) 1
127.0.0.1:6379> incr v
(integer) 2
127.0.0.1:6379> incrby v 10 # 自增10
(integer) 12
127.0.0.1:6379> incrby v 12
(integer) 24
###### 字符串范围获取 GETRANGE 

127.0.0.1:6379> set name zsls 
OK
127.0.0.1:6379> getrange name 0 2 # 获取第一个字符串到第三个
"zsl"
127.0.0.1:6379>
###### 


###############

127.0.0.1:6379> set k zsllovepjh
OK
127.0.0.1:6379> get zslloveph
(nil)
127.0.0.1:6379> get k
"zsllovepjh"
127.0.0.1:6379> setrange k 1 ZSL # 替换指定位置开始的字符串
(integer) 10
127.0.0.1:6379> get k
"zZSLovepjh"
###############

#############
127.0.0.1:6379> set k1 zero
OK
127.0.0.1:6379> FLUSHALL
OK 
127.0.0.1:6379> setex k 20 zero # 设置过期时间 设置k的值为zero 过期时间为20s
OK
127.0.0.1:6379> get k
"zero"
127.0.0.1:6379> ttl k
(integer) 14
127.0.0.1:6379> setnx mk zero # 不存在再进行设置
(integer) 1
127.0.0.1:6379> keys *
1) "mk"
127.0.0.1:6379> setnx mk "zs" # 如果存在则设置失败
(integer) 0
#############


##############################原子性操作
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 设置多个key的值
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> mget k1 k2 k3 # 获取多个key的值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 vv1 k4 v4 k5 v5 # 其中一个key设置失败,则都失败,反之都成功
(integer) 0
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
4) "mk"
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379>
##############################



127.0.0.1:6379> mset user:1:name zsl user:1:age 21 #设置对象 set key:{id}:{field}
OK
127.0.0.1:6379> keys *
1) "user:1:name"
2) "user:1:age"
127.0.0.1:6379> mget user:1:name user:1:age
1) "zsl"
2) "21"
127.0.0.1:6379>
##############################
getset # 先get再set
127.0.0.1:6379> getset k1 12
(nil)
127.0.0.1:6379> get k1
"12"

4.3 List

基本的数据类型,列表。

基本命令

LPUSH KEY VLUE

LRANGE KEY START END

127.0.0.1:6379> LPUSH list one # 将值存入列表 (将一个值或者多个值插入到列表头部)
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1# 取0到最后一个位置的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> LRANGE list 0 1 # 取0-1位置的值  
1) "three"
2) "two"
127.0.0.1:6379> RPUSH list right # 从尾部插入值
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lrange l 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> LPOP list 2  #从头部位置开始弹出 2 个元素
1) "4"
2) "3"
127.0.0.1:6379> lrange list 0 -1  
1) "2"
2) "1"
127.0.0.1:6379> lindex list 1 # 取下标为1的值
"1"

127.0.0.1:6379> lrem l 1 2 # 移除列表中一个为2的值
(integer) 1
127.0.0.1:6379> lrange l 0 -1
1) "3"
2) "1"

##################################################
ltrim 
127.0.0.1:6379> lrange list 0 -1 
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> LTRIM list 1 2 # 通过下标截取指定的长度。
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "2"
2) "3"

#####################################################
rpoplpush # 移除列表最后一个元素,将他移动到新的列表中!

127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> lpush list 2
(integer) 2
127.0.0.1:6379> lpush list 3
(integer) 3
127.0.0.1:6379> lpush list 4
(integer) 4
127.0.0.1:6379> rpoplpush list mylist # 将list最后一个元素移动到mylist列表下,并在list列表中移除该元素
"1"
127.0.0.1:6379> lrange mylist 0 -1
1) "1"
127.0.0.1:6379> lrange list 0 -1
1) "4"
2) "3"
3) "2"
# lset 指定下标的值。
127.0.0.1:6379> lset list 2 4
OK
127.0.0.1:6379> lrange list 0 -1
1) "4"
2) "3"
3) "4"

#############################################
127.0.0.1:6379> LRANGE list 0 -1
1) "4"
2) "3"
3) "4"
127.0.0.1:6379> linsert list before 4 before # 在指定元素值前面插入新的元素
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "before"
2) "4"
3) "3"
4) "4"
127.0.0.1:6379> LINSERT list after 4 after # 在指定元素值后面插入新的元素
(integer) 5
127.0.0.1:6379> LRANGE list 0 -1
1) "before"
2) "4"
3) "after"
4) "3"
5) "4"

小结

  • 实际上是一个链表,before、after、left、right
  • 如果key不存在,创建新的链表
  • 如果key存在,新增新内容
  • 如果移除了所有值,空链表,也代表不存在!
  • 在俩边插入或者改动值,效率最高!中间元素,相对来说效率低一点。

4.4 Set

集合的元素是唯一不重复的。

127.0.0.1:6379> sadd set 1 # 集合添加元素
(integer) 1
127.0.0.1:6379> sadd set 12
(integer) 1
127.0.0.1:6379> sadd set 123
(integer) 1
127.0.0.1:6379> SMEMBERS set
1) "1"
2) "12"
3) "123"
127.0.0.1:6379> SISMEMBER set 1 # 判断元素是否在集合set里
(integer) 1

127.0.0.1:6379> SISMEMBER set 12
(integer) 1
127.0.0.1:6379> SISMEMBER set 122
(integer) 0

127.0.0.1:6379> scard set # 获取set的元素数量
(integer) 3

127.0.0.1:6379> SRANDMEMBER set 1 # 随机抽选出指定个数的元素
1) "123"
127.0.0.1:6379> SRANDMEMBER set 1
1) "123"
127.0.0.1:6379> SRANDMEMBER set 1
1) "1"


127.0.0.1:6379> spop set # 随机弹出元素/也可以随机弹出指定个数的元素
"2"
127.0.0.1:6379> spop set
"4"
127.0.0.1:6379> SMEMBERS set
1) "1"
2) "3"



127.0.0.1:6379> sadd set1 zsl
(integer) 1
127.0.0.1:6379> sadd set2 pjh
(integer) 1
127.0.0.1:6379> SMOVE set1 set2 zsl # 将set1的“zsl”元素移动到set2
(integer) 1
127.0.0.1:6379> SMEMBERS set2
1) "zsl"
2) "pjh"
127.0.0.1:6379> SMEMBERS set1
(empty array)




127.0.0.1:6379> sadd s1 1
(integer) 1
127.0.0.1:6379> sadd s1 2
(integer) 1
127.0.0.1:6379> sadd s1 3
(integer) 1
127.0.0.1:6379> sadd s2 1
(integer) 1
127.0.0.1:6379> sadd s2 4
(integer) 1
127.0.0.1:6379> SDIFF s1 s2 # 差集
1) "2"
2) "3"
127.0.0.1:6379> SINTER s1 s2 # 交集
1) "1" 
127.0.0.1:6379> SUNION s1 s2 # 并集
1) "1"
2) "2"
3) "3"
4) "4"

4.5 Hash

Map集合,key-map!

127.0.0.1:6379> hset map name zsl # 设置一个具体的key-value
(integer) 1
127.0.0.1:6379> hget map name # 获取map的一个字段值
"zsl"
127.0.0.1:6379> hmset map age 22 sex man # 设置多个值
OK
127.0.0.1:6379> hmget map name age sex # 获取多个字段的值
1) "zsl"
2) "22"
3) "man"

127.0.0.1:6379> hgetall map # 获取map中所有的key和value
1) "name"
2) "zsl"
3) "age"
4) "22"
5) "sex"
6) "man"

127.0.0.1:6379> hdel map age # 删除指定的字段
(integer) 1
127.0.0.1:6379> hgetall map 
1) "name"
2) "zsl"
3) "sex"
4) "man"

127.0.0.1:6379> hlen map # 获取map的字段个数
(integer) 2

127.0.0.1:6379> HEXISTS map age # 查看字段是否存在
(integer) 0
127.0.0.1:6379> HEXISTS map name
(integer) 1

127.0.0.1:6379> hvals map # 获取所有值
1) "zsl"
2) "man"
127.0.0.1:6379> hkeys map # 获取所有字段
1) "name"
2) "sex"

127.0.0.1:6379> hsetnx map age 22 # 如果不存在age,则创建age,否则失败
(integer) 1
127.0.0.1:6379> hsetnx map age 22 # 
(integer) 0
127.0.0.1:6379> hgetall map
1) "name"
2) "zsl"
3) "sex"
4) "man"
5) "number"
6) "14"
7) "age"
8) "22"

小结

hash适合于对象的存储,String更加适合字符串存储!

4.6 Zset(有序集合)

127.0.0.1:6379> zadd zset 1 one 2 two 3 three # 设置多个值
(integer) 3
127.0.0.1:6379> arange 0 -1
(error) ERR unknown command `arange`, with args beginning with: `0`, `-1`,
127.0.0.1:6379> zrange zset 0 -1
1) "one"
2) "two"
3) "three"


127.0.0.1:6379> zadd salary 50000 zsl 5000 pjh 1 zzz
(integer) 3
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf # 显示全部数据,从小到大排序
1) "zzz"
2) "pjh"
3) "zsl"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores # 显示全部数据,从小到大排序 并显示scores
1) "zzz"
2) "1"
3) "pjh"
4) "5000"
5) "zsl"
6) "50000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 6000 withscores # 指定区间有序显示数据,并显示scores
1) "zzz"
2) "1"
3) "pjh"
4) "5000"

127.0.0.1:6379> zrange salary 0 -1
1) "zzz"
2) "pjh"
3) "zsl"
127.0.0.1:6379> ZREM salary zzz # 移除
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "pjh"
2) "zsl"

小结

案例思路:set 排序、存储班级成绩表、工资表排序

普通消息:1.重要消息 2. 带权重进行判断。

排行榜应用实现,Top N

4.7 三种特殊数据类型

4.7.1 geospatial 地址位置
127.0.0.1:6379> geoadd china:city 116.40 39.90 bj # 添加地理位置
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 sh 106.50 29.53 cq 120.16 30.24 hz
(integer) 3
127.0.0.1:6379> geopos china:city bj sh # 获取地理位置
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "121.47000163793563843"
   2) "31.22999903975783553"

GEODIST

俩地之间的距离

127.0.0.1:6379> geopos china:city bj sh
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "121.47000163793563843"
   2) "31.22999903975783553"
127.0.0.1:6379> geodist china:city bj sh # 查询北京与上海俩个城市的距离默认 m
"1067378.7564"
127.0.0.1:6379> geodist china:city bj sh km
"1067.3788"
127.0.0.1:6379> geodist china:city bj sh ft
"3501898.8071"
127.0.0.1:6379> geodist china:city bj sh mi
"663.2401"

GEORADIUS

127.0.0.1:6379> GEORADIUS china:city 110 30 500 k withcoord
(error) ERR unsupported unit provided. please use m, km, ft, mi
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord
1) 1) "cq"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord withdist
1) 1) "cq"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord withdist count 1
1) 1) "cq"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"

GEORADIUSBYMEMBER

# 找出指定位置元素周围的其它元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city bj 1000 km
1) "bj"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city bj 10000 km
1) "cq"
2) "hz"
3) "sh"
4) "bj"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city bj 10000 km withdist
1) 1) "cq"
   2) "1464.0708"
2) 1) "hz"
   2) "1127.3378"
3) 1) "sh"
   2) "1067.3788"
4) 1) "bj"
   2) "0.0000"

GEOHASH 返回一个或者多个位置元素的Geohash表示

127.0.0.1:6379> geohash china:city bj cq # 
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

底层原理:是zset,所有我们可以用zset命令来操作geo


127.0.0.1:6379> zrange china:city 0 -1
1) "cq"
2) "hz"
3) "sh"
4) "bj"
127.0.0.1:6379> zrem china:city cq
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "hz"
2) "sh"
3) "bj"
4.7.2 Hyperloglog

基数概念

A{1,3,5,7} B{1,3,4,6}

基数(不重复的元素) = 2

简介

用于基数统计的算法!

优点:占用的内存是固定,2^64不同的元素技术,只需要12KB内存。

应用场景:网页的UV(一个人访问一个网站多次,但是还是算作一个人!)

使用

127.0.0.1:6379> PFADD key a b  c d e e f # 创建一组元素
(integer) 1
127.0.0.1:6379> pfcount key # 统计 key 元素的基数数量
(integer) 6
127.0.0.1:6379> PFADD key1 a c s o p s d f
(integer) 1
127.0.0.1:6379> PFCOUNT key1
(integer) 7
127.0.0.1:6379> PFMERGE keey3 key key1 # 合并key key1到keey3
OK
127.0.0.1:6379> PFCOUNT keey3
(integer) 9
4.7.3 Bitmaps

位存储

统计用户信息,活跃,不活跃!登录,不登陆!只要是俩个状态的都可以使用Bitmaps

测试

127.0.0.1:6379> setbit sign 0 0 # 周一 未打卡
(integer) 0
127.0.0.1:6379> setbit sign 1 1 # 打卡
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0

##################################
# 查看打卡
127.0.0.1:6379> getbit sign 5
(integer) 1
127.0.0.1:6379> getbit sign 4
(integer) 0
127.0.0.1:6379> bitcount sign # 统计打卡天数
(integer) 2

5.事务

简介

本质:是一组redis命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!一次性、顺序性、排他性!

redis 事务没有隔离级别的概念

Redis单条命令式保存原子性的,但是事务不保证原子性

测试

127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
1) OK
2) OK
3) "v2"
4) "v1"

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> DISCARD # 取消事务
OK
127.0.0.1:6379> get k2
(nil)

命令错误,事务中所有命令都不会被执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k 1
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> setget k2 12
(error) ERR unknown command `setget`, with args beginning with: `k2`, `12`,
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.

事务队列存在语法性,那么执行命令的时候,其它命令是可以正常执行的,错误命令抛出错误!

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> incr k1
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range
4) "v1"

监控

悲观锁:

  • 认为什么时候都会出现问题,无论做什么都会加锁!

乐观锁:

  • 认为什么时候都不会出现问题,所有不会上锁!更新数据的时候去判断在此期间是否有人修改过这个数据,
  • 获取version
  • 更新时比较version

redis 监视测试

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money # 监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> get money
QUEUED
127.0.0.1:6379(TX)> get out
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
3) "80"
4) "20"

多线程测试

线程1:

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 300
QUEUED
127.0.0.1:6379(TX)> incrby out 300
QUEUED
127.0.0.1:6379(TX)> exec # 失败
(nil)

线程2:

127.0.0.1:6379> get money
"1080"
127.0.0.1:6379> set money 3000
OK
127.0.0.1:6379> unwatch # 如果事务执行失败,先解锁
OK
127.0.0.1:6379> watch money # 获取最新的值,再次监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 300
QUEUED
127.0.0.1:6379(TX)> incrby out 300
QUEUED
127.0.0.1:6379(TX)> exec # 对比监视的值是否发生变化,如果没有变化,那么可以执行成功,如果变了就执行失败
1) (integer) 2700
2) (integer) 320

```bash

> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> get money
QUEUED
127.0.0.1:6379(TX)> get out
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
3) "80"
4) "20"

多线程测试

线程1:

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 300
QUEUED
127.0.0.1:6379(TX)> incrby out 300
QUEUED
127.0.0.1:6379(TX)> exec # 失败
(nil)

线程2:

127.0.0.1:6379> get money
"1080"
127.0.0.1:6379> set money 3000
OK
127.0.0.1:6379> unwatch # 如果事务执行失败,先解锁
OK
127.0.0.1:6379> watch money # 获取最新的值,再次监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 300
QUEUED
127.0.0.1:6379(TX)> incrby out 300
QUEUED
127.0.0.1:6379(TX)> exec # 对比监视的值是否发生变化,如果没有变化,那么可以执行成功,如果变了就执行失败
1) (integer) 2700
2) (integer) 320

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值