redis 学习笔记

视频链接

介绍

非关系型数据库 NoSQL
键值对 redis
列存储 hbase
文档型数据库 MongoDB kv v是结构化的
图形化数据库 Neo4j 图结构

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库缓存消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

环境

java

yum install java-1.8.0-openjdk.x86_64
vi /etc/profile

#set java environment
JAVA_HOME=/usr/lib/jvm/jre-1.6.0-openjdk.x86_64
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME CLASSPATH PATH

. /etc/profile
java -version
c++
yum install gcc-c++
yum install net-tools

解压redis,进入redis
make
make install

redis.conf 找到daemonize yes 后台启动

redis-server redis.conf
redis-cli -p 6379

测试连通性
ping
set name xx
get name
keys *
shutdown 关闭连接

查看连接 ps -ef|grep redis

基础知识

redis默认有16个数据库
默认舒勇第0个,可以用select进行切换
select 3
flushdb 清除数据库
flushall 清除全部数据库
exists 存在
move name 1 移动到指定数据库
expire name 1 设置键过期时间,前面是秒数
ttl name 查看键的存活时间
type name 查看键类型

redis是单线程的,基于内存操作,因此瓶颈不是cpu而是内存和网络带宽
官网QPS(每秒请求数) 10w+
多线程上下文切换耗时。对于内存系统来说没有上下文切换效率最高。

redis五大基本数据类型

string hash list set zset

String

append key “xx” 追加value,如果不存在相当于新建key
strlen key 查看k长度
incr/decr key 加/减 1
incrby/decrby key 10 加/减 步长
getrange key 0 3 获得从0到3 0到-1为全部
setrange key 1 xx 从1开始改为xx abcd axxd
setex k s v 设置过期时间
setnx k v 不存在再设置
mset k1 v1 k2 v2 k3 v3
mget k1 k2 k3
msetnx k1 v1 k2 v2 原子性操作一个不成功全部不成功
getset k v 存在返回原值,不存在返回nil,最终设置v为新v
设置对象 set user:1{name:zhangsan,age:3}
mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age

List

lpush list 1 将值插入到左边,头部
rpush list 2 将值插入到尾部
lrange list 0 -1
lpop 移除左边(最前)的元素
rpop 移除右边(最后)的元素
lindex list 0 通过下标获取list的值
llen list 返回列表的长度
lrem list 2 three 从左边开始移除两个three
ltrim list 1 2 截取 1到2
rpoplpush ml ol 移出ml最后一个元素到ol中
lset list 0 item 将列表中的第一位设置为item 不存在会报错
linsert list before/after “1” “2” 将2 插入到1之前/后

小结:
是个链表;
key不存在创建新的链表;
key存在,新建内容;
移除所有值,空链表代表不存在;
两边插入效率快,中间相对慢;
消息队列 lpush rpop 栈 lpush lpop

Set

set中的值不能重复
sadd ms “hello” 在集合ms中添加hello
smembers ms 获取ms中所有元素
sismember ms hello 查看ms中是否存在hello
scard ms 获取ms中的元素个数
srem ms hello 移除ms中的hello
srandmember ms 获取ms中的随机元素
spop ms 随即删除集合中的元素
smove ms ms2 xx 把xx从ms移动到ms2

sdiff ms1 ms2 ms1中有,ms2中没有
sinter ms1 ms2 ms1和ms2的合集
sunion ms1 ms2 并集

Hash

key-value(map)
hset h k v 设置一个具体的k-v
hget h k 获取哈希h中的k的值
hmset h k1 v1 k2 v2 设置哈希h中的多个值,重复k值会覆盖v
hmget h k1 k2 获取哈希h中k1,k2的值
hgetall h 获取全部数据
hdel h k 删除哈希h中的k
hlen hash 计算hash的长度
hexitsts hash filed1 查看hash中字段是否存在
hkeys hash 获取全部的key
hvalues hash 获取全部values
hincre/decre hash filed 1 给字段增加/减少1
hsetnx hash field hello 没有设置成功,否则失败
hset user:1 k v
hget user:1 k

ZSet有序集合

zadd ms 1 one 2 two
zrange ms 0 -1
zrangebyscore salary -inf + inf 从小到大
zrangebyscore salary -inf +inf withscore
zrangebyscore salary -inf 2500 withscore
zrevrangebyscore salary 0 -1 从大到小进行排序
zrem salary xiaohong 移除小红
zcard salary 获取有序集合中的个数
zcount salary 1 3 获取指定区间的数量
实用:工资表,成绩表,权重消息,排行榜

三种特殊数据类型

geospatial 地理位置

geoadd china:city 经度 纬度 shanxi 经度 纬度 beijing 设值
geopos china:city beijing chongqing 获取城市的经纬度
geodist china:city beijing shanxi (m/km/mi英里/ft英尺)获取山西到北京的距离
georadius china:city 当前经度 纬度 半径 单位
georadius china:city 110 30 1000 km 经度110纬度30半径1000km内的城市
georadius china:city 110 30 500 km withdist 显示距离
georadius china:city 110 30 500 km withcoord 显示他人的经纬度
georadius china:city 110 30 500 km withdist withcoord count 1 筛选出指定的结果

georadiusbymember china:city beijing 500 km 找出位于指定元素周围的其他元素

geohash china:city beijing chongqing 返回经纬度的11个字符的哈希字符串
经纬度字符串越接近距离越近
geo的底层就是zset,可以使用zset命令操作geo

Hyperloglog

基数 占内存小12kb 可用于统计访问量(容错)
pfadd myset a b c d e f
pfcount myset 统计个数
pfmerge ms3 ms1 ms2 统计ms1,ms2的并集为ms3

bitmaps

位存储 位图
统计用户信息,活跃/不活跃
setbit sign 1 0
getbit sign 1
bitcount sign (start end) 统计集合中的个数

事务

redis命令有原子性,事务没有原子性。
没有隔离级别的概念。
一次性,循环性,排他性
开始事务multi
命令入队
执行事务exec
事务中的命令不会直接执行,需要命令exec
discard取消事务

编译性异常:命令错误,所有命令都不会执行
运行时异常:错误命令报错,其他命令正常运行

悲观锁和乐观锁

悲观锁

悲观锁先获取锁在进行读写
悲观锁分为
共享锁(shared locks) 又称读锁 S锁(其他人可读不可写)
排他锁(exclusive locks)又称写锁 X锁(当前可读可写,其他人不可读不可写)
实现:传统关系型数据库的锁机制;Java中的synchronize

乐观锁

乐观锁先修改,提交时再去判断是否冲突
实现:CAS;版本控制,修改时先去检查版本是否与拿到的版本一致

Watch

watch 充当乐观锁
unwatch 解除监视
set money 100
watch money
事务执行成功,监视自动取消
执行失败返回nil
执行失败,先unwatch,再wathch获取最新值和版本号

volatile

volatile保证可见性,禁止指令重排。

可见性

JMM(Java memory model)-java内存模型,是 Java 虚拟机规范中所定义的一种内存模型。
每个线程都有自己的工作内存,线程的工作内存中存储了共享变量的备份。
线程对共享变量的读写在本地内存中完成,不能直接访问主内存,多线程之间的共享变量也不能直接访问,需要主内存进行中转。
请添加图片描述
这样会导致没有及时更新的问题,需要解决可见性的问题。可以通过加锁和关键字volatile

加锁

进入synchronize代码块,会清除缓存,从主内存中获取共享变量,进行操作,刷新回主内存,然后释放锁。

volatile

vilatitle修饰共享变量时,每个线程修改变量都会从主内存中获取。修改完后刷新到主内存,并通过cpu总线嗅探通知其他变量修改,需要重新获取。

嗅探机制

cpu速度快,内存速度慢,一般都会有寄存器来解决。
请添加图片描述
每个处理器会监听从总线来的数据,如果发现数据的内存地址和当前缓存地址不同,就会判断缓存失效,从主内存中重新获取。

大量使用volatile会导致总线风暴。
volatile 关键字可以保证共享数据的可见性,但是并不能保证对数据操作的原子性。也就是说,多线程环境下,使用 volatile 修饰的变量是线程不安全的。可以使用锁机制或者原子类。
对任意单个使用 volatile 修饰的变量的读 / 写是具有原子性,但类似于 flag = !flag 这种复合操作不具有原子性。简单地说就是,单纯的赋值操作是原子性的。

禁止指令排序
编译器不会对 volatile 读与 volatile 读后面的任意内存操作重排序;编译器不会对 volatile 写与 volatile 写前面的任意内存操作重排序

SpringBoot

windows连接linux中的redis

关闭防火墙
配置文件删除bind端口(虚拟机无法用ip连接redis时可以bind虚拟机的ip试试)
protected-mode no
requirepass 123456

Jedis

Jedis是Redis官方推荐的面向Java的操作Redis的客户端,而RedisTemplate是SpringDataRedis中对JedisApi的高度封装。
SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache。

RedisTemple和StringRedisTemple的区别:

RedisTemple使用JdkSerializationRedisSerializer 存入数据会序列化成字节再存储
StringRedisTemplate使用StringRedisSerializer序列化

SpringBoot操作数据:spring-data jpa jdbc mongdb redis
在springboot中,redis后来被lettuce替代
jeds:直连,多线程操作,不安全。可以用jedis poll连接池来解决。BIO
lettuce: 采用netty,实例可以再多线程进行共享,不存在线程不安全的情况,可以减少线程。NIO

Spring自动配置类 spring-boot-autoconfigure RedisAutoConfiguration
每个配置类会绑定一个配置文件 RedisProperties
在这里插入图片描述
导入依赖
配置地址,端口,密码
redistemplate操作不同的数据类型,api和指令一样
opsForValue 操作字符串
opsForList
opsForSet
opsForHash
opsForZset
opsForGeo
opsForHyperLogLog

RedisConnection connection=redisTemplate.getConnectionFactory().getConnection();
connection.flushAll();
connection.flushDb();

自定义RedisTemplate

在这里插入图片描述
工具类redisutils(百度就有)

Redis.conf详解

1.配置文件 unit单位 对大小写不敏感
2.包含其他redis配置文件
在这里插入图片描述
3.网络
bind 127.0.0.1
protect-mode yes
port 6379
4.通用
daemonize yes 以守护进程的方式进行,默认no
pidfile /var/run/redis_6379.pid 如果后台运行,需要制定一个pid文件
loglevel debug/verbose/notice/warning
logfile “日志的文件位置和名称”
database 16 数据库的数量
5.快照
持久化,在规定时间内执行了多少次操作会持久化,rdb/aof
redis是内存数据库,如果没有持久化,那么数据会断电即失。
900s内,有一个key进行了修改,则进行持久化
save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes 持久化出错是否继续工作
rdbcompression yes 是否压缩rdb文件,需要消耗cpu资源
rdbchecksum yes 保存rdb文件进行错误校验
dir ./ rdb文件保存的目录
6.复制
7.安全
requirepass 密码
8.客户端
maxclient 10000 设置连接redis的最大客户端数量
maxmemory 字节 redis配置的最大内存容量
maxmemory-policy noeviction #内存到达上限之后的处理策略
在这里插入图片描述
9.aof配置
appendonly no 默认不开启,默认rdb方式持久化
appendfilename “appendonly.aof” 持久化的文件的名字
appendsync everysec(每秒)/always(每次修改)/no(不同步)

RDB和AOF

RDB(Redis DataBase)

在指定时间内fork子进程将内存写入快照,恢复时将快照文件读到内存中。
1.save规则满足的情况下会触发rdb规则
2.执行flushall也会触发rdb规则
3.退出redis,也会产生rdb文件
如何恢复,将rdb文件放在redis启动目录下,redis启动时就会检查dump.rdb恢复其中的数据
优点
1.适合大规模的数据恢复
2.如果对数据完整性要求不高
缺点
1.需要一定的时间间隔。 如果redis宕机,最后一次修改的数据就丢失了。
2.fork子进程时会占用一定的空间

AOF (append only file)

记录所有命令,恢复时把所有命令重新执行一遍。
以日志的形式来记录每个操作,只追加文件,不可以改写文件。
appendonly no 默认不开启,需要手动配置
appendsync everysec(每秒)/always(每次修改)/no(不同步)
no-appendfsync-on-wrire no 阻塞
如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?在linux的操作系统的默认设置下,最多会丢失30s的数据。
无法忍受延迟yes,无法忍受数据丢失no

如果aof文件有错误,redis无法启动。redis-check-aof --fix

重写规则
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

如果aof文件大于64m,会fork新的进程将文件进行重写(比如一个值修改四次,只会记录最后修改的值)

优点
1.每次修改都同步,文件完整性更好
2.每秒同步一次,可能会丢失一秒的数据
3.从不同步,效率最高
缺点
1.相对于数据文件,aof远远大于rdb,修改的速度也比rdb慢
2.aof运行效率慢,redis默认就是rdb持久化

扩展

1.只做缓存不需要进行持久化
2.同时开启两种同步方式,优先采用aof进行恢复,因为aof更加完整
3.rdb只在从机上使用

Redis发布订阅

redis发布订阅是一种消息通信模式
接收端subscribe ln
发送端publish ln “ln”

1 PSUBSCRIBE pattern [pattern …]
订阅一个或多个符合给定模式的频道。
2 PUBSUB subcommand [argument [argument …]]
查看订阅与发布系统状态。
3 PUBLISH channel message
将信息发送到指定的频道。
4 PUNSUBSCRIBE [pattern [pattern …]]
退订所有给定模式的频道。
5 SUBSCRIBE channel [channel …]
订阅给定的一个或多个频道的信息。
6 UNSUBSCRIBE [channel [channel …]]
指退订给定的频道。

应用:实时消息,实时聊天,订阅

主从复制

主从复制只能从主节点复制到从节点。Master以写为主,Slave为读为主。
主从复制的作用:
1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2.故障恢复:当主节点出现问题,可以由从节点提供服务,实现快速故障恢复。
3.负载均衡:主从复制,读写分离,分担服务器负载,提高服务的并发量。
4.高可用基石
单台reids最大内存不超过20G

info replication 查看当前库信息

搭建集群
从机配置文件修改
port 端口
pidfile 修改进程文件
logfile ""修改文件名
dbfilename dump.rdb 修改快照文件

命令配置从机(暂时)重启丢失主机配置
slaveof ip port 作为xx的从机
slaveof no one 变为主机
配置文件
replicaof ip port
masterauth password
主机断电,从机可读,集群失去写功能。从机回归正常,依旧可以读取主机写的数据。

复制原理

slave启动后会连接到master发送一个sync的命令
master收到命令后,启动后台存盘进程,同时收集所有用于修改的数据集命令,在后台进程执行完毕后,将整个数据文件到slave,并完成一次全量同步。
全量复制:salve服务接收到数据库文件,将其存盘并加载到内存中。
增量复制:master继续将新的收集到的修改命令依次传给slave,完成同步
只要重新连接master,一次全量复制自动执行。

哨兵模式

1.配置哨兵配置文件sentinel.conf
sentinel monitor myredis host port 1
1代表多少个哨兵认为主机失联,那这个主机就失联了
2.启动哨兵
redis-sentinel sentinel.conf

优点:
1.哨兵集群,基于主从复制
2.主从切换,故障转移,高可用
3.主从模式的升级,手动到自动,更加健壮
缺点
1.redis不好在线扩容
2.实现哨兵模式配置复杂

哨兵配置

port 26379 端口
dir /tmp
sentinel monitor mymaster host port 6379 2
sentinel auth-pass mymaster password
设置哨兵连接主从的密码,注意必须为主从设置一样的密码

sentinel down-after-milliseconds mymaster 30000
多少毫秒主节点无应答认为主节点下线
sentinel parallel-syncs mymaster 1
主从切换时多少个从机进行同步,越大说明多个从机主从切换不可用,越小说明主从切换耗时长
sentinel failover-timeout mymaster 180000
默认三分钟的故障转移
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

缓存穿透和雪崩

穿透(查不到)

因为缓存中没有,透过缓存直接访问数据库,多次重复访问导致数据库崩溃。
布隆过滤器
缓存空对象
1.如果空值可以被存储,缓存需要更多空间来存储空值的键,因为这当中有许多空值的键
2.对空值设置了过期时间,缓存层和存储层数会有一段时间窗口的不一致,影响需要一致性的业务。

击穿(量太大)

解决:
永不过期
分布式锁(同一个key只有一个线程有权限去查询)

雪崩

断电
解决:
高可用
服务降级
服务预热:流量大时,提前访问一遍,将数据存储到缓存中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小明和大树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值