缓存java_Java缓存机制

本文详细介绍了如何在SpringBoot中集成Redis缓存,包括使用Ehcache实现数据缓存、Redis的基本数据类型操作、以及主从复制和哨兵机制的原理与配置。此外,还讨论了RDB和AOF数据持久化策略,以及Redis事务的使用和发布订阅功能。
摘要由CSDN通过智能技术生成

1 Java缓存

1.1 jvm内置缓存

Java中实现缓存的方式有很多,比如用static hashMap基于内存缓存的jvm内置缓存,简单不实用,保对象的有效性和周期无法控制,容易造成内存急剧上升。常用的有Oscache(主要针对jsp页面),Ehcache(主要针对数据库访问层),Jcache,Jbosscache等等很多

缺点:容易内存溢出、没有持久化(服务重启后丢失)、线程安全、多个服务器(多个jvm)之间的数据不能共享。

1.2 java操作eache

利用spring Boot搭建应用(可参考这里的缓存配置)。

{

id: 35,

name: "springboot2.2",

age: 99

}

原理?

f34e5912aacc9b64258e8325bc0ab837.png

1、当客户端请求数据时,如果服务器端配置了缓存,第一步去缓存里面查找,如果有跳4,没有则往2

2、发送jdbc请求操作数据库查询数据

3、将查询到的数据返回给缓存,并保存在缓存中

4、将从(缓存|数据库)查询到的数据返回给客户端。

好处?效率高(因为不用建立jdbc连接等)、降低了数据库的压力(不用每次请求都要去数据库查,数据库也会累啊)。

缺点?从上述也看到了,有可能产生数据不一致的情况,清除缓存可解决。

和oscache区别?ehcache 主要是对数据库访问的缓存,相同的查询语句只需查询一次数据库,从而提高了查询的速度,使用spring的AOP可以很容易实现这一功能。 oscache主要是对页面的缓存,可以整页或者指定网页某一部分缓存,同时指定他的过期时间,这样在此时间段里面访问的数据都是一样的。

2 Redis

关系型数据库:持久、主外键、编写SQL语句、存放在硬盘。

非关系型数据库:一般用于缓存、值存放在内存(所以效率是真的高)、key-vakye形式、容易数据丢失(不过很好解决)、有点小类似jvm内置缓存(不过这个更牛嗨,因为可以多个服务器间共享数据)。

redis?可以持久化mongdb?存储json格式

2.1 Redis概述

完全开源免费、最受BSD协议、高性能的key-value费关系型数据库。支持持久化、支持key-value(String)\list\set\zert\hash等数据结构的存储、支持备份

好处?减轻数据库访问的压力。效率高?(访问内存肯定比访问硬盘快,这是常识)

70692d9f8b47dc3e4f0845a884aaf074.png

应用场景?(token生成、session共享、分布式锁、验证码、自增id(订单id))

2.2 安装redis

2.2.1 windows安装redis

2、解压redis-latest-windws.zip文件,将start.bat文件拷贝纸redis目录

3、编辑redis.windows.conf文件,取消requirepass的注释(前面不能有空格),空格然后添加密码比如(123456)保存。以requirepass 123456为例

4、双击start.bat运行

5、通过这个客户端工具测试一下

2.2.2 linux安装redis

2、mkdir -p /usr/local/redis/bin,mkdir -p /usr/local/redis/etc

3、copy redis-3.0.0.tar.gz到用户目录比如/root

4、解压tar -zxvf redis-3.0.0.tar.gz

5、cd redis-3.0.0/后,make一下

6、进入src目录make install后就安装成功了。

7、cd cd /root/redis-3.0.0/(redis安装目录)

8、cp redis.conf /usr/local/redis/etc

9、cd src

10、cp mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server redis-sentinel /usr/local/redis/bin

11、修改 redis.conf文件

daemonize yes --- 修改为yes  后台启动

requirepass 123456  ----注释取消掉设置账号密码

ps aux | grep '6379'  --- 查询端口

kill -15 9886 --- 杀死重置

kill -9 9886 --- 强制杀死

service iptables stop 停止防火墙

12、cd /usr/local/redis/bin

./redis-server /usr/local/redis/etc/redis.conf启动服务

13、./redis-cli -h 127.0.0.1 -p 6379 -a "123456"  --- redis 使用账号密码连接或者windows下的客户端工具进行连接测试

PING 结果表示成功

14、停止redis

redis-cli shutdown  或者 kill redis进程的pid

15、放开一下端口,好像外部即使注释掉bind 127.0.0.1也不能访问/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT

2.3 redis基本数据类型

2.3.1 字符串

127.0.0.1:6379> set name raolei

OK

127.0.0.1:6379> set itboy www.itboy.com

OK

127.0.0.1:6379> get name

"raolei"

127.0.0.1:6379> get itboy

"www.itboy.com"

常用命令:

2.3.2 list

127.0.0.1:6379> lpush listkey redis

(integer) 1

127.0.0.1:6379> lpush listkey mysql

(integer) 2

127.0.0.1:6379> lpush listkey mongdb

(integer) 3

127.0.0.1:6379> lpush listkey hbase

(integer) 4

127.0.0.1:6379> lrange listkey 0 10

1) "hbase"

2) "mongdb"

3) "mysql"

4) "redis"

list是简单的字符串列表,按照插入顺序排序,可在头和尾插入,最多包含2^32-1个元素(40多亿)。

常用命令:

序号

命令及描述

1

2

3

7

9

13

14

15

2.3.3 set

的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

哈希表实现。添加,删除,查找的复杂度都是O(1)。每个集合可存储40多亿个成员

127.0.0.1:6379> sadd setkey redis

(integer) 1

127.0.0.1:6379> sadd setkey redis

(integer) 0

127.0.0.1:6379> sadd setkey redis

(integer) 0

127.0.0.1:6379> sadd setkey redis

(integer) 0

127.0.0.1:6379> sadd setkey redis

(integer) 0

127.0.0.1:6379> sadd setkey mysql

(integer) 1

127.0.0.1:6379> sadd setkey mongdb

(integer) 1

127.0.0.1:6379> SMEMBERS setkey

1) "mysql"

2) "mongdb"

3) "redis"

常用命令:

2.3.4 sorted set

与set一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

127.0.0.1:6379> zadd zsetkey 1 redis

(integer) 1

127.0.0.1:6379> zadd zsetkey 2 mysql

(integer) 1

127.0.0.1:6379> zadd zsetkey 2 mongdb

(integer) 1

127.0.0.1:6379> smembers setkey

1) "mysql"

2) "mongdb"

3) "redis"

常用命令:

2.3.5 hash

是一个string类型的field和value的映射表(和map差不多,只是兼职都是字符串),hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

127.0.0.1:6379> hmset hmset name "redis tutorial"

OK

127.0.0.1:6379> hmset hmset age 24

OK

127.0.0.1:6379> hgetall hmset

1) "name"

2) "redis tutorial"

3) "age"

4) "24"

序号

命令及描述

2

3

4

5

6

7

8

11

12

13

14

HSCAN key cursor [MATCH pattern] [COUNT count]

迭代哈希表中的键值对。

redis怎么存放对象?通过将对象序列化为json字符串,存放为字符串形式,之后读取在反序列化为对象,这样很快很快

2.4 Spring Boot集成redis

添加依赖:

org.springframework.boot

spring-boot-starter-data-redis

org.springframework.boot

spring-boot-starter-web

org.apache.commons

commons-pool2

2.4.2

配置文件:

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

###Redis (RedisConfiguration)

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

spring:

redis:

database: 0

host: 192.168.245.134

port: 6379

password: 123456

jedis:

pool:

max-idle: 8

min-idle: 0

max-active: 8

max-wait: -1ms

timeout: 5000ms

service:

@Service

public class RedisService {

@Autowired

private StringRedisTemplate stringRedisTemplate;

//字符串

public void setStringKey(String key,String value,Long time){

setObject(key,value,time);

}

public void setStringKey(String key,String value){

setObject(key,value,null);

}

//set

public void setSetKey(String key,Set value){

setObject(key,value,null);

}

//list

public void setListKey(String key,List value){

setObject(key,value,null);

}

public String getStringKey(String key){

return (String) getObject(key,new String());

}

public Set getSetKey(String key){

return (Set) getObject(key,new HashSet());

}

public List getListKey(String key){

return (List) getObject(key,new ArrayList());

}

public void setObject(String key,Object value,Long time){

if(StringUtils.isEmpty(key)||value==null){

return;

}

//字符串类型

if(value instanceof String){

String value1= (String) value;

if(time!=null){

stringRedisTemplate.opsForValue().set(key,value1,time,TimeUnit.SECONDS);

} else{

stringRedisTemplate.opsForValue().set(key,value1);

}

return;

}

//list类型

else if(value instanceof List){

List list= (List) value;

for (String s:list) {

stringRedisTemplate.opsForList().leftPush(key,s);

}

return;

}

//set

else if(value instanceof Set){

Set strings= (Set) value;

for (String s : strings) {

stringRedisTemplate.opsForSet().add(key,s);

}

return;

}

/**

* .....

*/

}

public Object getObject(String key,Object object){

if(StringUtils.isEmpty(key)||object==null){

return null;

}

else if (object instanceof String){

return stringRedisTemplate.opsForValue().get(key);

}

else if(object instanceof List){

return stringRedisTemplate.opsForList().range(key,0,stringRedisTemplate.opsForList().size(key));

}

else if(object instanceof Set){

return stringRedisTemplate.opsForSet().members(key);

}

return null;

}

}

controller:

@RestController

public class IndexController {

@Autowired

private RedisService redisService;

@RequestMapping("/setString")

public String setString(@PathParam("key") String key,

@PathParam("value") String value){

redisService.setStringKey(key,value);

return redisService.getStringKey(key);

}

@RequestMapping("/setSet")

public Set setSet(@PathParam("key") String key,

@PathParam("value") String value){

HashSet strings = new HashSet<>();

strings.add(value);

strings.add(value+"1");

strings.add(value+"2");

strings.add(value+"3");

redisService.setSetKey(key,strings);

return redisService.getSetKey(key);

}

@RequestMapping("/setList")

public List setList(@PathParam("key") String key,

@PathParam("value") String value){

ArrayList strings = new ArrayList<>();

strings.add(value);

strings.add(value+"1");

strings.add(value+"2");

strings.add(value+"3");

redisService.setListKey(key,strings);

return redisService.getListKey(key);

}

}

2.5 主从复制和哨兵机制理解

为什么?数据备份、读写分离、集群、高可用(宕机容错机制)。

8bb3da47508d4a38509e6b6b5a8bb1f0.png

一般情况下,Redis高可用都是一主多从,而不像其他比如Nginx多主多从。

所谓主从复制,主要是为了减轻单台服务器的压力(比如图中的master),通过多台服务器的冗余来保证高可用(单台宕机容错),实现读写分离、数据备份、集群等。

如图,其中master可读可写,但是当有客户端连接达到集群时,如果是读操作就从slave从节点中随机选择一台服务器进行响应,如果是写操作,那么操作主服务器。这就是读写分离了不是吗。。。

问题?主服务器写之后,怎么同步到从服务器?(主从复制搞定,往下看)

问题?主服务器宕机了,怎么写?通过哨兵机制,哨兵其实就是一个监听器,一直监听这主服务器,如果主服务器挂了,他就会使用投票(随机)从主服务器中选择一台服务器作为主服务器,此乃高可用。

问题?那如果整个集群挂了呢?有一个东西叫做keepalived监听器(其实就是一个shell写的重启服务的命令脚本),如果监听到某一台服务器挂了,他就会自动重启的(一般30秒内,听说可能不准确)。如果一直启动失败?那就没办法了,他只能发送一封邮件给运维人员了。

2.5.1 主从复制实现

原理:通过快照文件(类似mysql的二进制可执行文件),当master有更新时,从服务器slave会实时请求得到该快照文件,进行执行,如果网络问题?别担心过,会重试的。

fb351428b85b34d6d88b13cff5dcf25e.png

过程:

1:当一个从数据库启动时,会向主数据库发送sync命令,

2:主数据库接收到sync命令后会开始在后台保存快照(执行rdb操作),并将保存期间接收到的命令缓存起来

3:当快照完成后,redis会将快照文件和所有缓存的命令发送给从数据库。

4:从数据库收到后,会载入快照文件并执行收到的缓存的命令。

对于redis服务器来说,和mysql有很大不同,只要设置好主从服务器之后,主服务器master可读可写,从服务器slave仅可读,不像mysql那样需要分配用户和mycat插件来控制读写分离。

配置过程:

1、准备服务器,如上图中三台服务器(192.168.245.134,192.168.245.135,192.168.245.136),选择一台为主服务器master(这台服务器什么也不用做)

2、所以redis主从复制只需要配置从服务器slave就OK,修改redis.conf配置文件,放开以下两行的注释,添加如下内容。两台从服务器都要修改。

slaveof 192.168.245.134 6379

#主服务器的ip和端口号

# If the master is password protected (using the "requirepass" configuration

# directive below) it is possible to tell the slave to authenticate before

# starting the replication synchronization process, otherwise the master will

# refuse the slave request.

#

masterauth 123456

#主服务器的认证密码

3、测试

#进入master主服务器

192.168.245.134:6379> info

#回车后看到如下内容即代表成功

# Replication

role:master

connected_slaves:2 #两台从服务器

slave0:ip=192.168.245.135,port=6379,state=online,offset=127,lag=1 #一些描述信息

slave1:ip=192.168.245.136,port=6379,state=online,offset=127,lag=1 #一些描述信息

#进入任何一台服务器比如135,同样info以下,看到如下内容即代表成功。

# Replication

role:slave #角色从服务器

master_host:192.168.245.134 #主服务器ip

master_port:6379 #主服务端口

master_link_status:up #状态

master_last_io_seconds_ago:10

master_sync_in_progress:0

#主服务器

192.168.245.134:6379> set master "192.168.245.134"

OK

192.168.245.134:6379> get master

"192.168.245.134"

192.168.245.134:6379>

##可读可写是吧???????

#########刚刚设置的这条数据从服务器有吗??????############

192.168.245.135:6379> get master

"192.168.245.134"

192.168.245.135:6379> set slave "192.168.245.135"

(error) READONLY You can't write against a read only slave.

192.168.245.135:6379>

############哟呵有数据的,主从复制成功,主从间数据同步问题解决,而且不能写,读写分离也搞定了########

[root@localhost bin]# ./redis-cli -h 192.168.245.136 -p 6379 -a "123456"

192.168.245.136:6379> ping

PONG

192.168.245.136:6379> get master

"192.168.245.134"

192.168.245.136:6379> set slave "192.168.245.136"

(error) READONLY You can't write against a read only slave.

192.168.245.136:6379>

################另一台从服务器也一样######################

2.5.2 哨兵机制实现

原理:哨兵用于管理多个redis服务器,执行以下三个任务:

1、监控(monitoring):哨兵(sentinel)会不断检查你的master和slave是否运作正常

2、提醒(notification):当被监控的某个redis出现问题时,哨兵(sentinel)可以通过API向管理员或者其他应用程序发送通知

3、自动故障迁移(automatic failover):当一个master1不能正常工作时,哨兵会开始一次自动故障迁移操作,他将会失效master1的其中一个slave升级为新的master2,并让失效master1的其他slave的master1改为新的master2。当客户端试图连接失效的master1时,集群也会向客户端返回新的master2地址,使得集群可以使用新的master2代替失效的master1

哨兵是一个分布式系统,可以在一个架构中运行多个哨兵进程,这些进程使用流言协议(gossipprotocols)来接收关于master是否下线的消息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移以及选择哪个slave作为新的master。

每个哨兵会向其他哨兵(sentinel)、master、slave定时发送消息,来确认对方是否还活着,如果对方在指定的时间(可配置)内未响应,则暂时认为对方已挂(主观认为宕机,Subjective Down,sdown)

若哨兵群中的多数sentinel都报告某一个master没响应,系统认为该master彻底死亡(客观真正的宕机,Objective Down,oDwon),通过一定vote算法,从生下的slave节点中选择提升一台为master,然后自动修改相关配置

虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵(sentinel).

实现:

这里以上面三台服务器为基础,选择192.168.245.136这台服务器为哨兵(可以选择多台,此处仅一台为例)。

注意:如果主从复制时,主服务器没有配置masterauth 123456请加上,这个坑了我很久很久,导致哨兵时一直连不上,最后查看日志才搞定,记得先将这个加到主服务器的redis.conf中,然后重启一下

1、修改redis安装目录下的sentinel.conf

sentinel monitor mymaster 192.168.245.134 6379 1

# 主节点名称 主机ip 端口号 选举次数(就是说当有几台sentinel认为master挂了才是真的挂了,因为这里只有一个哨兵,所以为1)

sentinel down-after-milliseconds mymaster 30

#就是说多少ms后没有给老子响应,老子就觉得你挂了。,默认30s,这里设置为30ms,本地测试追求实时

sentinel config-epoch mymaster 1

#这个数字表示在发生主从复制的时候,比如master1向master2切换时,可以同时有多少个slave能对master2执行同步(也就是复制其实),越多越好?>如果太多了那么大家都去复制了,谁来响应客户端的请求?太少?太少的话,每个都要来一遍,怕是要到天黑哦,根据实际情况吧,这里只有三台所以

为设为1.

sentinel auth-pass mymaster 123456

#主服务器密码

2、启动哨兵:nohup ./redis-server ../etc/sentinel.conf --sentinel  2>1 1>nohup.log &

3、如何停止ps -aux | grep 端口号,kill -9 pid即可

4、测试?

#我们首先查看master(134)的info master

role:master

connected_slaves:2

slave0:ip=192.168.245.135,port=6379,state=online,offset=5349,lag=1

slave1:ip=192.168.245.136,port=6379,state=online,offset=5349,lag=0

#135的 slave

role:slave

master_host:192.168.245.134

master_port:6379

master_link_status:up

#136 的 slave

role:slave

master_host:192.168.245.134

master_port:6379

master_link_status:up

#我现在讲master停掉? master

#134

192.168.245.134:6379> shutdown

not connected>

#135 的info replication

192.168.245.135:6379> info replication

# Replication

role:slave

master_host:192.168.245.136

master_port:6379

master_link_status:up

#看到主服务器变为136,

#136?

192.168.245.136:6379> info replication

# Replication

role:master

connected_slaves:2

slave0:ip=192.168.245.135,port=6379,state=online,offset=739,lag=0

slave1:ip=192.168.245.134,port=6379,state=online,offset=739,lag=0

#基本上成功了,最后试试读写分离以及在测试一些其他的,这里不再展示

2.6 数据持久化

数据持久化:就是将内存中的数据保存到硬盘,redis支持AOF和RDB两种存储方式

2.6.1 RDB存储

RDB是指在一个时间点,如果达到所配置的数据修改量,就写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。(二进制文件方式)

有两种保存方式:1、(阻塞)主进程直接拍快照(snapshot),然后阻塞客户端请求写入IO磁盘。2、(非阻塞)当要写入磁盘时,新建(fork)一个子进程,子进程将当前数据库快照写入磁盘,而主进程继续处理客户端请求。

每次快照持久化都是将内存数据完整写入到磁盘一次,并不 是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。

优点:使用单独子进程进行持久化,主进程不会进行任何IO操作,保证了redis的高性能

缺点:RDB需要间隔一段时间进行持久化,而且必须达到相应修改数量,所以如果持久化之间发生故障,会造成数据丢失,常用于数据要求不严谨的时候。

配置:

#dbfilename:持久化数据存储在本地的文件

dbfilename dump.rdb

#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下启动的redis-cli,则数据会存储在当前src目录下

dir ./

##snapshot触发的时机,save

##如下距离上一次持久化已经900s了,如果有大于等于1个变更,才会snapshot

save 900 1

##对于此值的设置,需要谨慎,评估系统的变更操作密集程度

##可以通过“save “””来关闭snapshot功能

save 300 10 #表示间隔达到300s时如果更改了10次以上,就snapshot,如果你在10s时已经10次了,立马持久化

save 60 10000 #同理间隔达到60s时如果更改了10000次以上,就snapshot,如果你在10s时已经10000次了,立马持久化

##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等

stop-writes-on-bgsave-error yes

##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间

rdbcompression yes

这里我将save 300 10改为save 30 10进行测试一下(首先先停掉哨兵机制,不然宕机后他就重新选一台主的了):

改好后重启一下服务:

进行5次更改操作

192.168.245.136:6379> get name

"1"

192.168.245.136:6379> set name 1

OK

192.168.245.136:6379> set name 2

OK

192.168.245.136:6379> set name 3

OK

192.168.245.136:6379> set name 4

OK

192.168.245.136:6379> set name 5

OK

192.168.245.136:6379> get name

"5"

#立马kill掉redis进程,一定要kill如果主动关闭服务,他是会进行snapshot的

[root@localhost bin]# ps -aux | grep 6379

root 1572 0.1 0.9 140840 9640 ? Ssl 02:02 0:00 ./redis-server *:6379

root 1577 0.0 0.5 20160 5184 pts/0 S+ 02:02 0:00 ./redis-cli -h 192.168.245.136 -p 6379 -a 123456

root 1580 0.0 0.0 112676 984 pts/1 R+ 02:03 0:00 grep --color=auto 6379

[root@localhost bin]# kill -9 1572

#重启服务

[root@localhost bin]# ./redis-server ../etc/redis.conf

[root@localhost bin]# ./redis-cli -h 192.168.245.136 -p 6379 -a "123456"

192.168.245.136:6379> get name

"1"

192.168.245.136:6379>

#可以看到我最后的是“5”,而这里是“1”,数据丢失了##########################

#更改10次呢?,是成功进行持久化了的,这里不展示了,篇幅过大。

#而且如果你将dump.rdb文件删除后,达到snapshot条件时,会自动创建一个新的文件,持久化其实就是将该文件备份,下次将那些持久化后的文件再放过来不就达到数据恢复了吗????????????

2.6.2 AOF存储

以日志文件方式存储,其实就是将你“操作+数据”指令格式化后追加到操作日志文件的尾部,必须append(已经写入到文件或者即将写入),才会进行数据的实际变更。“日志文件”保存了历史所有的操作过程;当 server 需要数据恢复时,可以直接 replay 此日志文件,即可还原所有的操作过程。内容是字符串,容易阅读和解析。

缺点:AOF 文件比 RDB 文件大,且恢复速度慢。

只会记录“变更操作”(例如:set/del 等),如果 server 中持续的大量变更操作,将会导致 AOF 文件非常的庞大,意味着 server 失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条 AOF 记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为 AOF 持久化模式还伴生了“AOF rewrite”。

因为最多丢失最后一次写入文件的数据,所以很好修复,直接手工更改文件或者重新来一次即可。

修改redis.conf文件:

##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能

##只有在“yes”下,aof重写/文件同步等特性才会生效

appendonly yes

##指定aof文件名称

appendfilename appendonly.aof

##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec每秒

appendfsync everysec

##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”

no-appendfsync-on-rewrite no

##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”

auto-aof-rewrite-min-size 64mb

##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。

##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后

##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。

auto-aof-rewrite-percentage 100

重启服务后,根据你启动redis所在目录下出现appendonly.aof文件。

执行以下操作:

192.168.245.136:6379> set name 124

OK

192.168.245.136:6379> set name 145

OK

192.168.245.136:6379> set age 56

OK

192.168.245.136:6379> del age

(integer) 1

192.168.245.136:6379> get name

"145"

查看aof文件内容:

[root@localhost bin]# cat appendonly.aof

*2

$6

SELECT

$1

0

*3

$3

set

$4

name

$3

124

*3

$3

set

$4

。。。

查询的是不会出现在里面,而且这个文件是动态的。。看起来挺好的,就是频繁的更改造成文件过大,到时候恢复起来有点太慢了,有人说那么RDB中将时间改快点要求改小点?大哥,人家是全量复制,那岂不是时间都花去复制了,还处理什么请求?这个虽然慢,可是是追加方式啊,将就了。

2.6.3 redis宕机后,值会失效吗?

不会,redis默认开启RDB存储,如果是直接关闭服务,那么会自动备份,如果是kill或者断电如果没达到RDB配置的要求则不会持久化,而且这个虽然是非阻塞的,但是毕竟全量复制啊,保证了redis的性能,但是CPU可受不了啊。因此实际情况中,最好采用AOP方式,实时而且快,但是就是容易造成文件过大,恢复困难。

2.7 redis事务

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

multi 开启事务 exec提交事务。

序号

命令及描述

1

2

3

4

5

2.8 发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

a1c9af69d21e45517f8e29c8e7f0e079.png

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

9ee02ef89519303e89776053988f7b78.png

例子:

1、创建订阅频道名为 redisChatSimple

192.168.245.136:6379> subscribe redsiChatSample

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "redsiChatSample"

2、重新开个客户端,同一频道发布消息

192.168.245.136:6379> publish redsiChatSample "gogog"

(integer) 1

192.168.245.136:6379> publish redsiChatSample "gogog22"

(integer) 1

192.168.245.136:6379>

3、客户端显示如下信息:

192.168.245.136:6379> subscribe redsiChatSample

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "redsiChatSample"

3) (integer) 1

1) "message"

2) "redsiChatSample"

3) "gogog"

1) "message"

2) "redsiChatSample"

3) "gogog22"

厉害了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值