Redis持久化
1.RDB是Redis的一种数据持久化到磁盘的策略,是一种以内存快照形式保存Redis数据的方式。所谓快照,就是把某一时刻的状态以文件的形式进行全量备份到磁盘,这个快照文件就称为RDB文件,其中RDB是Redis DataBase的缩写。
redis.conf文件,也就是/etc/redis/6379.conf,去配置持久化,配置文件设置RDB持久化的方式如下:
save 900 1
表示每隔15min,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件
save 60 1000
表示每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,
快照也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成
save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件
2、RDB持久化机制的工作流程
(1)redis根据配置自己尝试去生成rdb快照文件
(2)fork一个子进程出来
(3)子进程尝试将数据dump到临时的rdb快照文件中
(4)完成rdb快照文件的生成之后,就替换之前的旧的快照文件
dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照
2.AOF方式是将对数据的操作以文件的形式保存起来,文件中存储的只是对数据操作的指令。
#是否开启AOF,默认关闭(no)
appendonly yes
#指定 AOF 文件名
appendfilename appendonly.aof
#Redis支持三种不同的刷写模式:
#appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
#appendfsync no #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。
#在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no
no-appendfsync-on-rewrite no
#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage 100
#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
auto-aof-rewrite-min-size 64mb
Redis 数据结构
Redis支持五种数据类型:String(字符串)、hash(哈希)、list(列表)、set(集合)以及zsetsorted set(有序集合)
们实际项目中比较常用的是String和hash,如果你是Redis的中高级用户,还需要加上以下几种数据类型,分别是:Hyperloglog 基数统计、Geospatial 地理位置、Bitmap位图场景。
如果你玩过Redis Module,像BloomFilter、RedisSearch、Redis-ML,,等等,是加分项。
String字符串类型
Redis支持的字符串类型不是定长分配的字符串,是动态变长字符串,修改字符串在没有增加特别多内容的情况下不需要重新分配内存空间,内部结构实现上有点类似于java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
常用使用场景 JSON
将结构体json序列化成字符串,然后将字符串保存在redis的value中,将结构体的业务唯一标示作为key;这种保存json的用法用的最多的场景就是缓存用户信息,将用户bean信息转成json再序列化为字符串作为value保存在redis中,将用户id作为key。从代码中获取用户缓存信息就是一个逆过程,根据userid作为key获取到结构体json,然后将json转成java bean。
List列表类型
redis的列表的数据结构和Java中的LinkedList比较类似,所以List类型的前后插入和删除速度是非常快的,但是随机定位速度非常慢,时间复杂度是O(n)需要对列表进行遍历。
常用使用场景
可用于秒杀抢购场景,在商品秒杀场景最怕的就是商品超卖,为了解决超卖问题,我们经常会将库存商品缓存到类似MQ的队列中,多线程的购买请求都是从队列中取,取完了就卖完了,但是用MQ处理的化有点重,这里就可以使用redis的list数据类型来实现,在秒杀前将本场秒杀的商品放到list中,因为list的pop操作是原子性的,所以即使有多个用户同时请求,也是依次pop,list空了pop抛出异常就代表商品卖完了。
Hash数据类型
redis的hash相当于hashmap,内部实现上和hashmap一致,数组+链表的数据结构。
常用使用场景
保存结构体信息,hash字典类型也是比较适合保存结构体信息的,不同于字符串一次序列化整个对象,hash可以对用户结构中的每个字段单独存储。这样当我们需要获取结构体信息时可以进行部分获取,而不用序列化所有字段,而将整个字符串保存的结构体信息只能一次性全部读取。
Set集合类型
redis的set相当于java中的HashSet,内部的健值是无序唯一的,相当于一个hashmap,但是value都是null。
常用使用场景
set数据类型其实没什么好讲的,使用场景也是比较单一的,就是用在一些去重的场景里,例如每个用户只能参与一次活动、一个用户只能中奖一次等等去重场景。
Zset有序集合
它类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。zset内部是通过跳跃列表这种数据结构来实现的。因为zset要支持随机的插入和删除,所以不能使用数组结构,而需要改成普通链表数据结构。zset需要根据score进行排序,所以每次插入或者删除值都需要进行先在链表上查找定位。
常用使用场景
(1)各类热门排序场景
例如热门歌曲榜单列表,value值是歌曲ID,score是播放次数,这样就可以对歌曲列表按播放次数进行排序。
当然还有类似微博粉丝列表、评论列表等等,可以将value定义为用户ID、评论ID,score定义为关注时间、评论点赞次数等等。
转载
https://zhuanlan.zhihu.com/p/161311820
https://blog.51cto.com/u_13303/6624230