一、哪儿用了redis?为什么要用?
哪儿用了:app启动后的轮播广告
为什么用:mysql是硬盘,顶不住高并发;redis是内存;
二、什么是redis?
redis是c语言开发的高性能的k-v形式的数据库,数据存储在内存中,诞生于意大利
三、redis安装和启动
1、安装
安装c语言环境
yum install gcc-c++
上传并解压
cd /usr/upload
tar -zxvf redis-3.0.0.tar.gz
编译并安装
cd /usr/local/redis-3.0.0
make
make install PREFIX=/usr/local/redis
2.启动和关闭
拷贝并修改配置文件
cp /usr/upload/redis-3.0.7/redis.conf /usr/local/redis/bin
vim /usr/local/redis/bin/redis.conf
daemonize yes #改为yes
启动
./redis-server redis.conf
关闭
./redis-cli shutdown
./redis-cli -h 127.0.0.1 -p 6379 shutdown #指定端口
查看状态
ps -ef | grep redis
四、redis的多数据库实例
1、redis实例中提供了下标是0-15的16个数据库,不能修改下标,可通过select切换
2、清空数据库的命令:
flushdb:清空当前数据库的数据
flushall:清空所有数据库的数据
五、持久化
1、RDB:默认(数据)
策略:
save 900 1 #修改1条数据,900秒持久化一次
save 300 10
save 60 10000优点:不影响性能 缺点:不能保证数据的完整性
2、AOF:(命令)
策略:
# appendfsync always 服务器每写入一个命令,就调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。
appendfsync everysec #服务器每一秒调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。
# appendfsync no #服务器不主动调用 fsync 函数,由操作系统决定何时将缓冲区里面的命令写入到硬盘。缺点:影响性能 优点:保证数据的完整性
六、主从复制
1、过程
a、从往主发送sync命令
b、主往从发送rdb文件
c、主往从发送写命令 2、配置步骤
主:无需配置
从 ,修改配置文件:slaveof 主ip 主port
实验:
1.往主写数据,观察从是否同步
2.关闭主,往从写数据(主死了从只能读)
七、redis的五种数据类型
1.String(字符串)
string 是 redis 最基本的类型,一个 key 对应一个 value。string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。string 类型的值最大能存储 512MB。
Hash(哈希)
Redis hash 是一个键值(key=>value)对集合
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
Set(集合)
Redis的Set是string类型的无序集合
zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。
赋值 取值 删除 特点
string set k v get k del k string
hash hset k k-v hget k k hdel k k map
list lpush/rpush k v... lrange k 0 -1 lrem k 2 v list
set sadd k v... smembers k srem k v set
zset zadd k 1 v... zrange k 0 -1 withscores zrem k v sort set
八、redis集群
1、redis集群是多少台?
投票容错超过半数:3台 高可用:3台
2、为什么集群中有一个节点挂了,则整个集群都挂类?
redis集群中有16384个槽分给了3个节点,存取数据时:crc16(key)%16384=[0~16383]
3、搭建步骤
安装ruby环境
#切换目录
cd /usr/upload
#安装ruby
yum install ruby
yum install rubygems
gem install redis-3.0.0.gem
#查看脚本
cd /usr/upload/redis-3.0.0/src
ll *.rb
拷贝6个节点,并启动
要拷贝干净的redis,持久化文件删除掉,dump.rdb和appendonly.aof
cd /usr/local/redis/bin
cd /usr/local/redis/bin
rm -f dump.rdb
rm -f appendonly.aof
拷贝6个节点
cd /usr/local
#创建文件夹放redis
mkdir redis-cluster
cp -r redis redis-cluster/redis-7001
#重复上面拷贝个命令,修改名称
...
目录结构
依次修改redis配置文件,这里用的是7001-7006
vim /usr/local/redis-cluster/redis-7001/bin/redis.conf
#修改配置文件中的端口号
port 7001
#集群打开
cluster-enable yes
创建启动脚本
cd /usr/local/redis-cluster/
vim start-all.sh
#启动脚本内容编辑
cd /usr/local/redis-cluster/redis-7001/bin
./redis-server redis.conf
cd /usr/local/redis-cluster/redis-7002/bin
./redis-server redis.conf
cd /usr/local/redis-cluster/redis-7003/bin
./redis-server redis.conf
cd /usr/local/redis-cluster/redis-7004/bin
./redis-server redis.conf
cd /usr/local/redis-cluster/redis-7005/bin
./redis-server redis.conf
cd /usr/local/redis-cluster/redis-7006/bin
./redis-server redis.conf
创建关闭脚本
vim shutdown-all.sh
#关闭脚本内容编辑
cd /usr/local/redis-cluster/redis-7001/bin/
./redis-cli -p 7001 shutdown
cd /usr/local/redis-cluster/redis-7002/bin/
./redis-cli -p 7002 shutdown
cd /usr/local/redis-cluster/redis-7003/bin/
./redis-cli -p 7003 shutdown
cd /usr/local/redis-cluster/redis-7004/bin/
./redis-cli -p 7004 shutdown
cd /usr/local/redis-cluster/redis-7005/bin/
./redis-cli -p 7005 shutdown
cd /usr/local/redis-cluster/redis-7006/bin/
./redis-cli -p 7006 shutdown
启动脚本
./start-all.sh
查看redis运行状态
ps -ef | grep redis
启动成功
使用ruby脚本创建redis集群(记得修改ip地址)
#切换找到脚本所在目录
cd /usr/upload/redis-3.0.0/src
#运行命令启动集群
./redis-trib.rb create --replicas 1 192.168.226.205:7001 192.168.226.205:7002 192.168.226.205:7003 192.168.226.205:7004 192.168.226.205:7005 192.168.226.205:7006
测试
进去redis-7001
cd /usr/local/redis-cluster/redis-7001/bin/
./redis-server redis.conf
./redis-cli -c -p 7001
#查看集群详情
cluster nodes
执行关闭脚本
cd /usr/local/redis-cluster/
./shutdown-all.sh
九、测试
加入依赖
<!-- Spring Data Redis的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件
spring:
redis:
cluster:
nodes:
- 192.168.226.205:7001
- 192.168.226.205:7002
- 192.168.226.205:7003
- 192.168.226.205:7004
- 192.168.226.205:7005
- 192.168.226.205:7006
jedis:
pool:
max-active: 20 #连接池最大连接数
max-idle: 10 #连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
启动类
package com.powershop
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpingDataApp {
public static void main(String[] args) {
SpringApplication.run(SpingDataApp.class, args);
}
}
配置类
package com.powershop.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
//设置通用序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
实体类
package com.powershop.pojo;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
RedisClient工具类
package com.powershop.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisClient {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key,long time){
try {
if(time>0){
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long ttl(String key){
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public Boolean exists(String key){
return redisTemplate.hasKey(key);
}
//============================String=============================
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key){
return key==null?null:redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key,Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
public Boolean del(String key){
return redisTemplate.delete(key);
}
/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta){
if(delta<0){
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta){
if(delta<0){
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().decrement(key, -delta);
}
//================================hash=================================
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key,String item){
return redisTemplate.opsForHash().get(key, item);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key,String item,Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item){
redisTemplate.opsForHash().delete(key,item);
}
//============================set=============================
/**
* 根据key获取Set中的所有值
* @param key 键
* @return
*/
public Set<Object> smembers(String key){
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将数据放入set缓存
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sadd(String key, Object...values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long srem(String key, Object ...values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* 获取list缓存的内容
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lrange(String key, long start, long end){
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean rpush(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lpush(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lrem(String key,long count,Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
测试
@SpringBootTest(classes = SpingDataApp.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class RedisTest {
@Test
public void testSetPojo4(){
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(100);
redisClient.set("user",user);
}
@Test
public void testGetPojo4(){
User user = (User) redisClient.get("user");
System.out.println(user);
}
}