Redis笔记

Redis笔记

一、什么是Redis

基本概念

redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库(非关系性数据库)。

redis的优势

  1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
  2. 支持丰富数据类型,支持string,list,set,sorted set,hash
  3. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
  4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

基础知识

16个数据库,默认是0个;

select 3
disize 
flushdb
flushAll

二、redis的应用场景

缓存

(1) 对于一些要返回给前端数据的缓存,当有大量数据库sql操作时候,为了避免每次接口请求都要去查询数据库,可以把一些数据缓存到redis中,这样是直接从内存中获取数据,速度回增快很多。

(2) web端用户,用于登陆缓存session数据,登陆的一些信息存到session中,缓存到redis中

队列

redis中提供了list接口,这个list提供了lpush和rpop,这两个方法具有原子性,可以插入队列元素和弹出队列元素。

数据存储

redis是非关系型数据库,可以把redis直接用于数据存储,提供了增删改查等操作,因为redis有良好的硬盘持久化机制,redis数据就可以定期持久化到硬盘中,保证了redis数据的完整性和安全性。

redis锁实现防刷机制

redis锁可以处理并发问题,redis数据类型中有一个set类型,set类型在存储数据的时候是无序的,而且每个值是不一样的,不能重复,这样就可以快速的查找元素中某个值是否存在,精确的进行增加删除操作。

三、redis的基本数据类型

redis是一种高级的key-value非关系型数据库。其中value支持五种数据类型:string,List,set,hash,sore set

一、字符串(string)

string存储的元素类型可以是string/int/float,int类型可以进行增加和减少操作。
代码实际操作过程:

set key1 v1        # 设置值

get key1          # 获取值   

keys *           # 获取所有的key

exists key1               # 判断一个key是否存在

 append key1 "hello"        # 追加字符串,若当前key不存在,就相当于setkey
 
 strlen key1             # 获取字符串的长度 
 # ================================================================================
 # i++  
 # 步长 i+=
 set views 0      # 处置浏览量为0
 
 incr views       # 自增1
 
 incrby views  10   # 设置步长,指定增量
 
 decrby views  10   # 设置步长,指定增量
 # ================================================================================
 # 字符串范围 range
 set key1 "hello,world"  # 设置key1 的值
 
getrange key1 0 3     #截取字符串 [0,3],是闭区间

getrange key1 0 -1    # 获取全部的字符串 和 get key 是一样的
 # ================================================================================
# 替换 replace
set key2 abcdefg

setrange key2 1 xx      # 从指定位置开始的字符串 替换

get key2
"axxdefg"
# ==================================================================================
 # setex  (set with expire)   # 设置过期时间 ---秒
 # setnx (set if not exist)   # 不存在设置 (在分布式锁中会经常使用!)
 
 setex key3 30 "hello"      # 设置key3 的值为hello,30秒后过期
 
 ttl keys                # 查看当前key 还有多久过期
 
 setnx mykey "redis"        # 若mykey 不存在,则创建 mykey
 
 setnx mykey "mongoDB"       # 若mykey 存在,则创建 失败!
 
# =======================================================================================
 # mset    # 同时设置多个值
 # mget 
 mset k1 v1 k2 v2 k3 v3        # 同时设置多个值
 
 mget k1 k2 k3              # 同时获取多个值
 
 msetnx k1 v1 k4 v4           # msetnx 是一个原子性的操作,要么一起成功,要么一起失败!
# ==========================================================================================
 # 对象
 set user:1 {name:zhangsan,age:3}  # 设置一个user:1 对象,值为 JSON 字符来保存一个对象!
 
 # 这里的key 是一个巧妙的设计:user:{id}:{field},如此设计在Redis中时完全OK了! 
 mset user:1:name zhangsan user:1:age 2
 
 mget user:1:name user:1:age
 "zhangsan"
 "2"
# ==========================================================================================
#  getset  # 先get 然后 set 
 getset db redis      # 如果不存在值,则返回 nil
 get db
 "redis"
 
 getset db mongodb     # 若存在值,获取原来的值,并设置新的值
 "redis"
 get db
 "mongodb"
# ========================================================================================== 
String使用场景

String使用场景:value除了是我的字符串还可以是我们的数字!

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储!

二、列表(list)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vRzCGSLG-1640009772282)(C:\Users\小王子\AppData\Roaming\Typora\typora-user-images\image-20211213194155642.png)]

在Redis中可以把list 完成,栈、队列、阻塞队列!

所有的list 命令都是以 l 开头的!redis 不区分大小写命令!

list类型是一个有序的列表,有序表示的是从左到右还是从右到左,而且数据内容是可以重复的。
代码实际操作过程:

# =============================================================================================== 
lpush list one          # 将一个值或多个值,插入到列表头部(左)

lrange list 0 -1         # 获取list 中的值!

lrange list 0 1         # 通过区间获取具体的值!

rpush list right        # 将一个值或多个值,插入到列表尾部(右)
# =============================================================================================== 
lpop 
rpop
lpop list      #移出list 的第一个元素
rpop list      #移出list 的最后一个元素
# =============================================================================================== 
index
index list 1     #通过下标获得 list 中的某一个值!
# =============================================================================================== 
llen
llen list      # 返回列表的长度
# =============================================================================================== 
lrem
lrem list 1 one      # 移出list 集合中指定个数的value,精确匹配 
# =============================================================================================== 
trim  # 修剪; list 截取!
rpush mylist "hello"
rpush mylist "hello1"
rpush mylist "hello2"
rpush mylist "hello3"
ltrim mylist 1 2     # 通过下标截取指定的长度,这个list 已经被改变了,截断了只剩下截取的元素了!
lrange mylist 0 -1
"hello1"
"hello2"
# =============================================================================================== 
rpoplpush   # 移出列表最后一个元素,将它移动到新的列表中!
rpush mylist "hello"
rpush mylist "hello1"
rpush mylist "hello2"
rpoplpush mylist myotherlist     # 移出列表最后一个元素,将它移动到新的列表中!
lrange mylist 0 -1            # 查看原来的列表
"hello"
"hello1"
lrange myotherlist 0 -1        # 查看目标列表中,确实存在该字段!
"hello2"
# =============================================================================================== 
lset  # 将列表中指定下标的值替换为另一个值,更新操作!

exists list           # 判断这个列表是否存在

lset list 0 item       #若不存在列表,我们去更新就会报错!

lpush list value1

lset list 0 item        # 若存在,更新当前下标的值

lset list 1 other       #若不存在列表,我们去更新就会报错!
# =============================================================================================== 
linsert  # 将某个具体的value 插入到列表中某个元素的前面或后面

rpush mylist "hello"
rpush mylist "world"

linsert mylist before "world" other    # 将某个具体的value 插入到列表中某个元素的前面

lrange mylist 0 -1
"hello"
"other"
"world"
linsert mylist after world new        # 将某个具体的value 插入到列表中某个元素的后面
"hello"
"other"
"world"
"new"
# =============================================================================================== 
小结:
  1. 它实际上是一个链表,before Node after, left ,right 都可以插入值
  2. 若key 不存在,创建新的链表
  3. 若key 存在,新增内容
  4. 若移出了所有值,空链表,也代表不存在!
  5. 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~

消息排队!消息队列(Lpush Rpop), (Lpush Lpop)

三、集合(set)

set类型中提供了无序的方式来存储多个不同的元素,set类型中每个元素的值都不一样,用户可以快速对元素中的值添加删除,检查某些值是否存在,重复的元素是无法继续插入集合的
代码实际操作过程:

127.0.0.1:6379> sadd set1 12    # 添加set元素,重复元素不再添加
(integer) 1
127.0.0.1:6379> sadd set1 12
(integer) 0
127.0.0.1:6379> scard set1
(integer) 1
127.0.0.1:6379> sadd set1 13
(integer) 1
127.0.0.1:6379> scard set1  # scard计算元素总数
(integer) 2
127.0.0.1:6379> sadd set1 13
(integer) 0
127.0.0.1:6379> smembers set1   # 查看指定key集合元素

127.0.0.1:6379> sismember set1 13  # 查看13是否在集合中,返回1 表示存在 返回0表示不存在
(integer) 1
127.0.0.1:6379> srem set1 13   # 从集合中删除13
# =============================================================================================== 
# sdiff计算差集
127.0.0.1:6379> sadd set2 a b c
(integer) 3
127.0.0.1:6379> sadd set3 b c d e
(integer) 4
127.0.0.1:6379> sdiff set2 set3
1) "a"
127.0.0.1:6379> sdiff set3 set2
1) "d"
2) "e"
# 我们发现 集合的顺序不同 结果不一
# =============================================================================================== 
# sinter计算交集
127.0.0.1:6379> sinter set2 set3
1) "c"
2) "b"

四、哈希(hash)

hash类型也叫散列类型,存储的时候存的是键值对。查询条数的时候只要是健不一样,就是不同的条数,尽管值是相同的。

[root@VM_160_197_centos /]# redis-cli
127.0.0.1:6379> hset hash1 key1 12
(integer) 1
127.0.0.1:6379> hget hash1 key1
"12"
127.0.0.1:6379> hset hash1 key2 13
(integer) 1
127.0.0.1:6379> hset hash1 key3 13
(integer) 1
127.0.0.1:6379> hlen hash1    # 查询条数的时候只要是健不一样,就是不同的条数,尽管值是相同的。
(integer) 3
127.0.0.1:6379> hset hsah1 key3 14
(integer) 1
127.0.0.1:6379> hset hash1 key3 14
(integer) 0
127.0.0.1:6379> hget hash1 key3
"14"
127.0.0.1:6379> hmget hash1 key1 key2  # 同时获取key1和key2的值
1) "12"
2) "13"

五、有序集合(sort set)zset

sore set也叫有序分数集,可以把它看作一个排行榜,每一个同学都有自己的分数,且排行榜中还有一个排名的属性,排行属性从0,根据分数不断变大,排行也不断变大。
,这个类型有点复杂,上一张图吧。

sort set特性

1)sore set中的值是全局唯一的。

一个值设置了之后,再次设置不会增加,只会覆盖修改。

2)如果有两条分数相同,排名应该怎那么看?
如果两个分数值相同,会根据值两个元素变量名的字典排序顺序排列先后,可看下方操作代码。

代码实际操作过程:

Map集合,key-Map!只是这个值是一个map集合,本质和String类型没有太大区别,还是以个简单的key-value

flushdb  # 清空当前数据库

flushall   # 清空所有数据库

hset myhash field1 wanglin       # set一个具体的key-value

hget myhash field1     # 获取一个字段值
 
hmset myhash field1 hello field2 world   # set多个 key-value

hmget myhash field1 field2     # 获取多个字段值

hgetall myhash        # 获取全部的数据

hdel myhash field1     # 删除hash指定key字段

hlen myhash          # 获取hash表的字段长度

hexists myhash        # 判断hash中指定字段是否存在

hkeys myhash      # 获取所有的key

hvals myhash        # 获取所欲的值

hset myhash field3 5    # 指定增量

hsetnx myhash field4 hello    # 如果不存在则可以设置,若存在则不能设置
注意:

hash变更的数据 user name age,尤其是用户信息之类的,经常变动的信息!hash 更适合与对象的存储,String 更适合字符串存储!

127.0.0.1:6379[1]> zadd zset1 10.1 val1 //添加一个值和分数
(integer) 1
127.0.0.1:6379[1]> zadd zset1 11.1 val2
(integer) 1
127.0.0.1:6379[1]> zadd zset1 9.2 val3
(integer) 1
127.0.0.1:6379[1]> zcard zset1 //统计当前key下值的个数
(integer) 3
127.0.0.1:6379[1]> zrange zset1 0 2 withscores  //查看0到2的所有值和分数按照排名
1) "val3"
2) "9.1999999999999993"
3) "val1"
4) "10.1"
5) "val2"
6) "11.1"
127.0.0.1:6379[1]> zrank zset1 val2
(integer) 2
127.0.0.1:6379[1]> zadd zset1 12.2 val3 //覆盖iu该val3
(integer) 0
127.0.0.1:6379[1]> zrange zset1 0 2 withscores//查看0到2的所有值和分数按照排名
1) "val1"
2) "10.1"
3) "val2"
4) "11.1"
5) "val3"
6) "12.199999999999999"
127.0.0.1:6379[1]> zadd zset1 12.2 val2
(integer) 0
127.0.0.1:6379[1]> zrange zset1 0 2 withscores//这时候有两个分数相同,查看0到2的所有值和分数按照排名
1) "val1"
2) "10.1"
3) "val2"
4) "12.199999999999999"
5) "val3"
6) "12.199999999999999"

四、Redis常用命令

# 查看安装是否成功:
rpm –qa|grep gcc

# 后台启动后,查看服务: 
netstat –anp|grep 6379

五、Redis基本环境

安装

Redis笔记

六、哨兵模式

七、Redis穿透和雪崩

服务的高可用问题

导致原因

查不到数据导致的

布隆过滤器

Redis笔记

缓存空对象

Redis笔记

缓存击穿

击穿原因

量太大,缓存过期

缓存雪崩

上一篇:Qt小案例《加法计算器》


下一篇:LeetCode-025-K 个一组翻转链表