假如你是一个java用户,请定义一个用户信息结构体,然后使用fastjson对用户信息对象进行序列化,然后将序列化的对象用jedis存入redis中。
接着用jedis将刚刚存入的用户信息从redis中取出,再经过fastjson反序列化后输出到控制台上!
- 先导入环境依赖。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
- 定义一个User类。
public class User {
private String name;
private Integer age;
private String sex;
//以下省略构造函数,getset方法,以及toString方法
}
- 在建立连接redis的jedis环境⭐
public class JedisConfig{
state{
JedisPoolConfig config=new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(50);
config.setMaxWaitMillis(3000);
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
JedisShardInfo jedisShardInfo = new JedisShardInfo("120.55.36.148", 6379);
jedisShardInfo.setPassword("123456");
List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
list.add(jedisShardInfo);
pool = new ShardedJedisPool(config,list);
}
}
- 最后在该类中创建一个main方法实现业务。⭐
public static void main(String[] args) {
User user = new User();
user.setName("chenhang");
user.setAge(1);
user.setSex("man");
//序列化后存入redis
String s = JSON.toJSONString(user);
ShardedJedis jedis = pool.getResource();
jedis.set(user.getName(),s);
//反序列化
String user2 = jedis.get(user.getName());
User user1 = JSON.parseObject(user2, User.class);
System.out.println(user1.toString());
}
Redis下载和安装(linux)
# 联网情况下,执行如下命令进行下载
wget http://download.redis.io/releases/redis-6.0.10.tar.gz
# 一般都在usr下创建一个目录,方便管理
mkdir /usr/local/src/redis
# 切换到下载的目录,进行解压缩
tar -zxvf redis-4.0.2.tar.gz
# 将解压缩的redis移到到/usr/local/src/redis
mv redis-6.0.10 /usr/local/src/redis
# 进入文件夹内,进行编译并安装
make
make install
# 启动redis
redis-server
# 连接redis
redis-cli
SpringBoot整合Redis⭐
- 配置Redis的redis.conf
## 确保客户端可以访问到redis
bind 0.0.0.0
protected-mode no
daemonize yes
- SpringBoot中关于redis的配置
# redis配置
Spring:
redis:
host: Redis所在的ip地址
port: 端口号
database: 选择的数据库
- 具体操作如下:
@SpringBootTest
class Boot06RedisApplicationTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@Test
// 操作stringRedisTemplate字符串
void test1() {
//对于key、value都是String时,可以使用StringRedisTemplate
stringRedisTemplate.opsForValue().set("age", "32");
stringRedisTemplate.opsForValue().set("name", "李哥");
stringRedisTemplate.opsForList().leftPushAll("lists", "java", "python", "golang", "c++");
stringRedisTemplate.opsForHash().put("mainKey", "secondKey", "value");
stringRedisTemplate.opsForSet().add("city", "beijing", "xian", "shanghai");
stringRedisTemplate.opsForZSet().add("score", "lige", 100);
}
@Test
// 操作redisTemplate字符串
void test2() {
// 将key和hashKey的序列化方式设置位String,防止乱码,默认是JdkSerializationRedisSerializer
// 对于key、value存在对象时,可以使用RedisTemplate
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.opsForValue().set("user", new User(1, "lige", "陕西省"));
// 其余操作都类似于StringRedisTemplate
redisTemplate.opsForValue().set("age", "32");
redisTemplate.opsForList().leftPushAll("lists", "java", "python", "golang", "c++");
redisTemplate.opsForHash().put("mainKey", "secondKey", "value");
redisTemplate.opsForSet().add("city", "beijing", "xian", "shanghai");
redisTemplate.opsForZSet().add("score", "lige", 100);
}
@Test
// 对同一个key多次操作时,可以使用boundXxxOps绑定一个key
void test3() {
BoundValueOperations name = redisTemplate.boundValueOps("name");
name.set("changed lige");
name.append("zhenshuai");
}
}
实战应用
- 利用mybatis自身本地缓存结合redis实现分布式缓存
mybatis中应用级缓存(二级缓存) SqlSession级别缓存 所有会话共享 - 开启二级缓存
- xxxMapper.xml中加入标签
- cache标签底层默认使用org.apache.ibatis.cache.impl.PerpetualCache
- 将缓存的type属性更改自定义RedisCache
- 通过mybatis默认cache源码可知,可以使用自定义cache类实现Cache接口,并对其方法进行实现
自定义Cache类:
@SuppressWarnings("all")
public class RedisCache implements Cache {
private RedisTemplate redisTemplate;
// id:对应mapper的namespace="com.atlige.boot.mapper.UserMapper"
private final String id;
public RedisCache(String id){
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
// 使用redis里的hash类型作为缓存存储模型,key -- id, hashkey--当前方法key, value -- value
getRedisTemplate(redisTemplate).opsForHash().put(id.toString(), getKeyToMD5(key.toString()), value);
}
@Override
public Object getObject(Object key) {
// 根据key从redis的hash类型中获取数据
return getRedisTemplate(redisTemplate).opsForHash().get(id.toString(), getKeyToMD5(key.toString()));
}
/**
* 根据指定的key删除缓存
* @param key
* @return
*/
@Override
public Object removeObject(Object key) {
return null;
}
/**
* 清空缓存
*/
@Override
public void clear() {
// 清空namespace
getRedisTemplate(redisTemplate).delete(id.toString());
}
/**
* 计算缓存数量
* @return 缓存数量
*/
@Override
public int getSize() {
// 获取hash中的key、value的数量
return getRedisTemplate(redisTemplate).opsForHash().size(id.toString()).intValue();
}
public RedisTemplate getRedisTemplate(RedisTemplate redisTemplate){
if (redisTemplate == null){
redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
}
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
private String getKeyToMD5(String key){
return DigestUtils.md5DigestAsHex(key.getBytes());
}
}
注意点:
- 自定义的RedisCache不是由spring的beanFactory实例化的,而所以不能使用自动注入 @Autowired
- 编写一个可以获取beanFactory的工具类ApplicationContextUtils来获取
/**
* @author Jeremy Li
* @data 2021/1/22 - 22:39
* 用来获取springboot创建好的工厂
*/
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
//保留下来的工厂
@Autowired
private static ApplicationContext applicationContext;
// 将创建好的工厂以参数的形式传递给这个类
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtils.applicationContext = applicationContext;
}
// 提供在工厂中获取对象的方法
public static <T> T getBean(String beanName, Class<T> requiredType){
return (T) applicationContext.getBean(beanName);
}
}
Redis主从复制架构
主从复制架构仅仅用来解决数据的冗余备份,从节点仅仅用来同步数据:
### master 7001
bind 0.0.0.0
port:7001
daemonize yes
protected-mode no
### slave1 7002
bind 0.0.0.0
port:7002
daemonize yes
protected-mode no
replicaof 192.168.152.128 7001
### slave2 7003
bind 0.0.0.0
port:7003
daemonize yes
protected-mode no
replicaof 192.168.152.128 7001
Redis哨兵机制
Sentinel系统 在被监视的主服务器进行下线状态时,自动将从服务器升级为新的主服务器。
- 创建一个sentinel文件夹并创建一个sentinel.conf
sentinel monitor [主从架构名称:mymaster] [主服务器的ip:192.168.152.128] [端口号:7003] [设置哨兵的数量:1]
- 使用redis/bin/下的redis-sentinel 加载配置文件并启动哨兵即可
Redis集群
相关的linux命令:
# 对每一个redis.conf进行修改
bind 0.0.0.0
port xxxx
daemonize yes
pidfile redis_xxxx.pid
logfile redis_xxxx.log
appendonly yes
cluster-enabled yes
cluster-config-file nodes-xxxx.conf
cluster-node-timeout 5000
cluster-slave-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes
# 构建集群
redis-cli --cluster create 192.168.152.128:8000 192.168.152.128:8001 192.168.152.128:8002 192.168.152.128:8003 192.168.152.128:8004 192.168.152.128:8005 --cluster-replicas 1
# 查看集群状态
redis-cli --cluster check 192.168.152.128:8001
Redis分布式Session管理
利用spring提供的session管理解决方案,将一个应用session交给redis存储,整个应用中所有的session的请求都会去redis中获取相应的session数据
- 引入依赖
<!--springboot-redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring-data-redis session管理-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
- 编写配置类
@Configuration
@EnableRedisHttpSession // 将整个应用中使用session的数据全部交给redis处理
public class RedisSessionManager {
}
- 测试
@Controller
@RequestMapping("test")
public class TestController {
@RequestMapping("test")
public void test(HttpServletRequest request, HttpServletResponse response) throws IOException {
List<String> list = (List<String>) request.getSession().getAttribute("list");
if (list == null){
list = new ArrayList<>();
// request.getSession().setAttribute("list", list);
}
list.add("xxxx");
request.getSession().setAttribute("list", list); // 每次session变化都要同步session
response.getWriter().write("size: " + list.size() + "\n");
response.getWriter().write("sessionId: " + request.getSession().getId());
}
@RequestMapping("logout")
public void testLogout(HttpServletRequest request){
request.getSession().invalidate();
}
}