缓存机制
为了提告数据库的查询能力,引入了缓存服务器,用户连续查询相同的数据时可以直接从缓存中取出.
缓存机制介绍
使用缓存机制就是为了降低用户访问物理设备的频次,从缓存服务器中获取数据,而不是服务器中,提高整体速度,提升用户体验.
如何实现缓存机制
1. 缓存使用的数据结构 Key=Value 且 Key必须唯一
2. 应该使用什么语言开发 C语言
3. 缓存的运行环境 内存中
4. 内存数据断电即擦除如何保证数据安全 实现持久化(写入磁盘中)
5. 内存数据如何优化 LRU算法/LFU算法
Redis介绍
*Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库,缓存,消息中间件,他支持多种类型的数据结构,例:字符串(String),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets) *与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability).
速度快:
tomcat: 150-220/秒
nginx: 3-5万/秒
redis: 写 8.6万/秒 读 11.2万/秒 ~ 平均10万次/秒
安装Redis
1.在虚拟机指定位置上传Redis
2.解压Redis
tar -xvf redis.tar.gz
3.编译Redis
进入redis安装目录 make
4.安装Redis
需进入安装目录:make install
5.修改Redis配置文件(redis.conf)
vim redis.conf
1: 修改IP绑定.将Redis自带的IP绑定注释
2. 取消保护模式
3. 开启开机后台启动
Redis常规命令
复制redis-conf到安装目录下 即有server的目录下
1. 启动命令 redis-server redis-conf(没开启后台运行效果)
2. 检索redis服务 ps -ef | grep redis
3.进入redis客户端 redis-cli -p 6379
4.关闭redis
方式1:rediscli -p 6379 shutdown
方拾2: ps -ef | grep redis查看进程kill杀死进程
Redis入门
1.添加jar包
<!--spring整合redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
测试API
动态获取Redis对象(Jedis)
1.创建redis.properyies配置文件
#配置单台的Redis
redis.host=192.168.126.129
redis.port=6379
2.创建配置类RedisConfig并动态赋值
此处的
@Bean是将对象交给sping容器管理@Configuration表示这是个配置类
@PropertySource指明配置文件来源
@Configuration //表示配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
return new Jedis(host,port);
}
}
3.创建测试类并注入自行配置的Redis对象
错误检查:
1.Linux防火墙
2.Redis三项配置
3.重启Redis
@SpringBootTest //需要依赖Spring容器,从容器中获取对象
public class TestRedis {
@Autowired
private Jedis jedis;
}
String类型测试
测试一
向Redis中存数据
@Test
public void test01() {
//1.向Redis中存数据
jedis.set("1", "憨批曲佳磊憨批齐亚硕");
//2.从Redis中取值
String value = jedis.get("1");
System.out.println(value);
}
测试二
API:
exists 检查Redis中是否存在某个值
expire 设定Key超时自动销毁时间
ttl 获取剩余生存时间
persist 撤销删除操作
@Test
public void test02() {
//1.判断Redis中是否存在某个key
if (jedis.exists("1")) {
//2.如果存在则设定超时时间
jedis.expire("1", 100);
//3.线程暂停2秒
try {
Thread.sleep(2000);
//4.获取key的剩余生存时间
Long time = jedis.ttl("1");
System.out.println("生命倒计时" + time);
//5.撤销删除操作
jedis.persist("1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试三
redis的set操作会将之前的value覆盖
API : setnx 如果值存在则不执行赋值
操作之前检查Redis中是否有改数据
@Test
public void test03() {
jedis.flushAll();//清空redis缓存
jedis.setnx("boos", "马化腾");
jedis.setnx("boos", "马云");
System.out.println(jedis.get("boos"));
}
测试四
保证原子性如何操作(妖魔同时成功,妖魔同时失败)
API:setex 保证原子性操作并添加超时时间
@Test
public void test04() {
Jedis jedis = new Jedis("192.168.126.129", 6379);
jedis.setex("aaa", 20, "xxxx");//满足原子性需求
}
测试五
同时添加超时时间并且满足原子性要求
API:SetParams设置参数 set传入参数即可
private static final String XX = “xx”; 只有key存在时才能赋值
private static final String NX = “nx”; 只有key不存在时才能赋值
private static final String PX = “px”; 毫秒
private static final String EX = “ex”; 秒
@Test
public void test05() {
SetParams setParams = new SetParams();
setParams.nx().ex(20);
jedis.set("AAA", "w", setParams);
String s = jedis.get("AAA");
System.out.println(s);
}
Hash类型测试
可以用散列类型保存对象和属性值
@Test
public void testHash() {
Jedis jedis = new Jedis("192.168.126.129", 6379);
jedis.hset("person", "name", "tomcat");
jedis.hset("person", "age", "100");
Map<String, String> person = jedis.hgetAll("person");
System.out.println(person);
}
Lsit类型测试
List集合当做队列使用也可以当做栈使用
队列:存入数据的方向和获取数据的方向相反
栈:存入数据的方向和获取数据的方向相同
API:
lpush 从队列的左边入队一个或多个元素
rpush 从队列的右边入队一个或多个元素
lpop 从队列的左端出队一个元素
rpop 从队列的右端出队一个元素
lpushx 当队列存在时从队列的左侧入队一个元素
rpushx 当队列存在时从队列的右侧入队一个元素
@Test
public void testList() {
Jedis jedis = new Jedis("192.168.126.129", 6379);
jedis.lpush("list", "1", "2", "3", "4", "5");
String value = jedis.rpop("list");
System.out.println(value);
System.out.println(jedis.rpop("list"));
}
Redis事务控制
API:
multi 标记一个事务开始
exec 执行所有multi之后发的命令
discard 丢弃所有multi之后发的命令
Transaction transaction = jedis.multi(); 事务对象
transaction.exec(); 提交事务
transaction.discard();回滚事务
@Test
public void testMulti() {
Transaction transaction = jedis.multi();
try {
transaction.set("AAA", "XXX");
transaction.set("BBB", "XXX");
transaction.exec(); //提交事务
}catch (Exception exception){
exception.printStackTrace();
transaction.discard();//回滚事务
}
}