Redis

Redis

概述

Redis是一个key-value存储系统,是一个分布式缓存数据库。

1. Redis基础操作

1.1 Redis初始操作

1.1.1 启动redis服务

docker start redis 

1.1.2 查看启动redis的进程信息

ps -ef|grep redis

1.1.3 进入redis容器

docker exec -it redis01 bash    //redis01 为容器名

1.1.4 登录redis服务

1.1.4.1 登陆本地redis
redis-cli
或者
redis-cli -p 6379
或者
redis-cli -p 6379 -a  password  	  //-a后面为password,此操作需要开启redis.conf文件中的 requirepass选项
1.1.4.2 登录远程redis服务
redis-cli  -h ip  -p 6379  -a  password

1.1.5 查看redis信息

首先登录redis,然后输入info指令

127.0.0.1:6379> info		//查看当前redis节点的详细配置信息

1.1.6 关闭redis服务

shutdown

1.2 Redis数据存储操作

1.2.1查看redis中的key

keys *

1.2.2 基于K-V形式存储数据

set K V

1.2.3 基于K获取数据

get K

1.2.4 基于K删除数据

del key

1.2.5 清除redis中的数据

redis默认有16个数据库,可通过select 0-15 切换.

flushdb			//清除当前数据库数据
flushall        //清除所有数据库数据

1.3 Key有效时间设计

其中,ttl查看Key的剩余时间,当返回值为**-2**时,表示键被删除。
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1

1.3.1 设置生效时长-秒

设置时长: expire Key seconds
查看剩余时长:ttl Key
例:

set age 18
expire age 1
ttl age

1.3.2 设置生效时长-毫秒

设置时长: pexpire Key milliseconds
查看剩余时长:ttl Key
例:

set age 18
expire age 1000
ttl age

1.3.3 取消时长设置

语法:persist Key

persist age

2. Redis常用数据类型

Reids中基础数据结构包含字符串、散列,列表,集合,有序集合。

2.1 String类型

字符串类型是redis中最简单的数据类型,它存储的值可以是字符串,其最大字符串长度支持到512M。

2.1.1 自增

incr/incrby

incr key	//递增
incrby key increment	//指定系数自增

2.1.2 自减

decr/decrby

decr key		//递减
decrby key decrement  //指定步长递减

2.1.3 尾部追加

append

append key value

2.1.4 字符串长度

strlen

strlen key

2.1.5 同时设置/获取多个键值

mset/mget

mset key value [key value ...]
mget key [key ...]

2.2 Hash类型

Redis散列类型相当于Java中的HashMap,实现原理跟HashMap一致,一般用于存储对象信息,存储了字段(field)和字段值的映射

2.2.1 赋值和取值

hset/hget

hset key field value
hget key field

2.2.2 自增和自减

hincrby
increment为正数时是指定步长自增,为负数时是指定步长自减

 hincrby key field increment

2.2.3 同时设置和获取多个对象属性

hmset/hmget

hmset key field value [field value ...]
hmget key field value [field value ...]

2.2.4 属性是否存在

hexists

hexists key field

2.2.5 删除属性

hdel

hdel key field

2.2.6 只获取字段名或字段值

hkeys/hvals

hkeys key
kvals key

2.3 List类型

Redis的list类型相当于java中的LinkedList,其原理就就是一个双向链表。支持正向、反向查找和遍历等操作,插入删除速度比较快。经常用于实现热销榜,最新评论等的设计。

2.3.1 在key对应list的头部添加字符串元素

lpush

lpush key element [element ...]

2.3.2 在key对应list的尾部添加字符串元素

rpush

rpush key element [element ...]

2.3.3 返回指定列表指定区间内的元素

lrange

 lrange key start stop

2.3.4 从list的头部删除元素,并返回删除元素

lpop

lpop key [count]

2.3.5 从list的尾部删除元素,并返回删除元素

rpop

rpop key [count]

2.3.6 删除指定key

del

del key [key ...]

2.3.7 在key对应list的特定位置之前或之后添加字符串元素

linsert

linsert key BEFORE|AFTER pivot element

2.3.8 设置list中指定下标的元素值(一般用于修改操作)

lset

lset key index element

2.3.9 从key对应list中删除count个和value相同的元素

lrem:
count>0时,按从头到尾的顺序删除
count<0时,按从尾到头的顺序删除
count=0时,删除全部

lrem key count element

2.3.10 保留指定key 的值范围内的数据

ltrim

ltrim key start stop

2.3.11 返回key对应list的长度

llen

llen key

2.3.12 返回名称为key的list中index位置的元素

lindex

lindex key index

2.3.13 从第一个list的尾部移除元素并添加到第二个list的头部

rpoplpush

rpoplpush source destination

2.3.14 阻塞式队列

brpop/blpop

brpop key [key ...] timeout
blpop key [key ...] timeout

2.3.15 获取指定元素的下标

lpos

lpos key element 

2.4 Set类型

Redis的Set类似Java中的HashSet,是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

2.4.1 添加元素,重复元素添加失败

sadd

sadd key member [member ...]

2.4.2 获取全部内容

smembers

smembers key

2.4.3 判断是否包含指定元素

sismember key member

2.4.4 移除并返回集合中的一个随机元素

spop

spop key [count]

2.4.5 删除指定元素

srem key member

2.4.6 获取成员个数

scard

scard key

2.4.7 移动一个元素到另外一个集合

smove

smove source destination member

2.4.8 并集

sunion

sunion key [key ...]

3.Java中操作redis

3.1 Jedis

依赖jedis
Jedis是Java中操作redis的一个客户端,类似通过jdbc访问mysql数据库。

3.1.1 修改redis配置文件

基于vim打开redis.conf文件,然后注释 bind 127.0.0.1这一行,并修改protected-mode的值修改为no.

3.1.2 Redis数据库连接池

连接池对象:JedisPool
连接池配置对象:JedisPoolConfig

3.1.3 简单工程

3.1.3.1 单点登录

在这里插入图片描述

  • 当用户访问系统时,系统通过是否携带token来判断用户是否登录.
        如果没有token,则返回登陆页面.
        如果携带token,则判断token的正确性
            token正确,进入系统,token不正确,返回登陆页面
  • 登录成功后,将认证信息写入到redis中,并返回客户端token
3.1.3.2 投票系统

在这里插入图片描述

  • 用户点击投票按钮,判断用户是否登录(token),没有登录则跳转登陆页面
  • 登录以后,判断用户是否投过票(sismember),投过则直接提示,没有投过则完成投票逻辑(sadd)
  • 用户可在活动页面查看总投票数(scard)
  • 管理员可以看到投票人员信息(smembers)

3.2 RedisTemplate

Spring data模块提供的一个操作redis数据库数据的API对象,需要添加spring-boot-starter-data-redis依赖
把操作数据的对象提取出来,需要注入对应的操作对象.
注入时候使用 @Resource(name = “stringRedisTemplate”) 注解,name的值为要注入的对象

3.2.1 StringRedisTemplate

该对象是spring data模块推出的一个用于操作redis字符串类型数据的一个API对象,底层序列化方式使用的是StringRedisSerializer,存储key/value默认会将key/value都转换为字符串再进行存储

3.2.2 RedisTemplate

RedisTemplate对象也Spring data模块提供的一个操作redis数据库数据的API对象,此对象主要用于操作redis数据库中的复杂数据类型数据,默认序列化方式为JdkSerializationRedisSerializer
默认采用了JDK的序列化方式,存储key/value默认会将key/value都转换为字节再进行存储
此方式可以自行修改序列化方式

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());

3.2.3 简单工程

3.2.3.1 秒杀队列

会将用户的秒杀或抢购请求先存储到一个redis队列,使用list集合,先进先出,lpush rpop

3.2.3.2 分布式id

生成一个分布递增的id,多张表基于这个方法中生成的id作为主键id值(分布式环境不会采用数据库表中自带的自增策略-auto_increment)

3.2.3.3 购物车

存储一些不经常变化的数据,使用hash数据类型存储比较方便

3.3 Spring测试redis分片访问

Redis分片访问是一种客户端API操作方式这里采用jedis方式,分片访问使用一致性哈希算法.
当配置多台Reids服务时(服务之间没有主从关系),存储数据使用分片访问,数据会均匀存储到每个redis服务器(根据一致性Hash算法,哈希环)
对k进行哈希运算,得出对应的节点位置信息,然后存储到对应的节点,也就是redis服务器.

ShardedJedisPool(config, list)	//分片连接池

3.4 Spring测试redis哨兵模式的数据操作

这里采用jedis方式
由于是哨兵模式,不知道具体主从关系,所以把数据交给哨兵,由哨兵根据主从关系进行操作,完成主从复制

//主从关系组名,哨兵服务器列表
JedisSentinelPool("mymaster", sentinelSet)	//哨兵连接池

3.5 Spring测试Redis集群模式

这里采用RedisTemplate方式,集群模式使用哈希槽算法.
通过哈希槽算法,把16384个槽位平均分布(连续槽位)到多个主服务器上,存数据的时候,计算得出K的哈希槽值,然后放入对应的主服务器节点上.取数据时,计算K的哈希槽值,然后去对应的主服务器节点获取数据.

//方式一
@Autowired
private RedisConnectionFactory factory;
factory.getClusterConnection()
//方式二
@Autowired
@Qualifier("stringRedisTemplate")
private RedisTemplate redisTemplate;
redisTemplate.opsFor()

4. Redis数据的持久化

4.1 Rdb方式

  • Rdb方式是通过手动(save-阻塞式,bgsave-异步)或周期性方式保存redis中key/value的一种机制,Rdb方式一般为redis的默认数据持久化方式.系统启动时会自动开启这种方式的持久化机制。
  • 执行shutdown关闭redis,是一种安全退出的模式,会保存一份rdb快照
  • kill -9粗暴杀死redis进程,模拟redis故障异常退出,数据就丢失了.
  • Save 命令 : 同步保存操作
  • bgsave命令:异步保存操作

4.2 Aof方式

  • Aof方式是通过记录写操作日志的方式(把写过的每条指令保存在日志文件中),记录redis数据的一种持久化机制,这个机制默认是关闭的。
  • 每秒钟强制写入磁盘一次
  • 在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里
  • 当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
  • 设置AOF文件启动新的日志重写过程的最小值(64MB)
# 是否开启AOF,默认关闭
appendonly yes
# 指定 AOF 文件名
appendfilename appendonly.aof
# Redis支持三种刷写模式:
# appendfsync always #每次收到写命令就立即强制写入磁盘,类似MySQL的sync_binlog=1,是最安全的。但该模式下速度也是最慢的,一般不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做平衡,推荐该方式。
# appendfsync no     #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不推荐。
    
#在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes
no-appendfsync-on-rewrite yes
#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage 100
#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
auto-aof-rewrite-min-size 64mb

4.3 如何选择redis的持久化方式?

第一:不要仅仅使用RDB,因为那样会导致你丢失很多数据。
第二:也不要仅仅使用AOF,因为AOF做冷备没有RDB做冷备进行数据恢复的速度快,并且RDB简单粗暴的数据快照方式更加健壮。
第三:综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择; 用RDB来做不同程度的冷备。

5. Redis 事务处理

5.1 概述

Redis采用乐观锁的方式进行事务控制(mysql使用悲观锁),它使用watch命令监视给定的key,当exec(提交事务)时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。注意watch的key是对整个连接有效的,如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令都会清除连接中的所有监视。

5.2 基本指令

在进行数据操作之前,
先开启监控—>然后开启事务—>执行数据操作—>提交事务—>关闭监控

  • multi 开启事务
  • exec 提交事务
  • discard 取消事务
  • watch 监控,如果监控的值发生变化,则提交事务时会失败
  • unwatch 去掉监控

6. Redis高级特性

6.1 Redis主从复制

master(主) 负责读写,并将数据同步到salve(从),从节点负责读操作

6.1.1 主从同步原理分析

Redis的主从结构可以采用一主多从结构,Redis主从复制可以分为全量同步增量同步

  • Redis全量同步:

Redis全量复制一般发生在 Slave初始化 阶段,这时Slave需要将Master上的所有数据都复制一份。
具体步骤如下:
1)从服务器连接主服务器,发送sync命令;
2)主服务器接收到sync命名后,开始执行bgsave(异步保存)命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
3)主服务器bgsave执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

  • Redis增量同步

Redis增量复制是指Slave初始化后,开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

  • 全量同步与增量同步的区别

全量同步: 就是每天定时(避开高峰期)或者采用一个周期实现将数据拷贝到一个地方也就是Rdb存储。
增量同步: 比如采用对行为的操作实现对数据的同步,也就是AOF。
全量与增量的比较: 增量同步比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。

6.2 Redis哨兵模式

哨兵(Sentinel)是Redis的主从架构模式下,实现高可用性(high availability)的一种机制。
由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时(默认30秒),自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
需要添加配置文件,配置主从关系

6.3 Redis集群的高可用

对于redis集群(Cluster),一般最少设置为6个节点,3个master,3个slave
需要创建虚拟网卡和配置文件

总结

1.Redis和MenCached的比较

RedisMenCached
都是分布式内存数据库都是分布式内存数据库
单线程多线程
支持数据落地,两种故障恢复模式:RDB,AOF只保存在内存中,掉电丢失
支持数据丰富:String/Hash/List/Set/Zset只支持String
可支持到String 512M / Hash 2*32只支持10M

2. 缓存穿透

问题描述: 缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都请求到数据库上,从而数据库接异常。
缓存穿透解决方案:
1 . 利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
2 . 采用异步更新策略,无论Key是否取到值,都直接返回。Value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
3 . 提供一个能迅速判断请求是否有效的拦截机制比如,利用布隆过滤器,内部维护一系列合法有效的Key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

3. 雪崩问题

问题描述: 缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都请求到数据库上,从而导致数据库连接异常。
缓存雪崩解决方案:
1 . 给缓存的失效时间,加上一个随机值,避免集体失效。
2 . 使用互斥锁,但是该方案吞吐量明显下降了。
3 . 双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B设置较长失效时间。
双缓存的实现过程: 从缓存A读数据库,有则直接返回; A没有数据,直接从B读数据,直接返回并且同时刷新A。并且利用异步更新线程,更新数据时候同时更新缓存A和缓存B。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值