sql:关系型数据库 NoSql:非关系型数据库
Redis可以把数据持久化,缓存到硬盘里,这样假如Redis宕机了,只需要重启Redis,可以从硬盘中恢复数据。
在以前的老项目中使用到的jvm内置缓存框架,假如有多个服务器做集群的情况下,每一个jvm缓存,都会缓存一份,有一个缓存数据进行修改了,那么其他的缓存的数据也要跟着修改。而Redis的分布式管理,所有的服务器的数据都会放入Redis,保证了两台服务器的同步性。所以这也是为什么Redis支持分布式共享。
安装linux环境:: 安装Linux教程
随后打开vm ware,你已经启动了一台Linux下的虚拟机
yum install -y gcc tcl
安装完毕后,将下载好的redis安装包拖拽到/usr/local/src目录下:
tar -zxvf redis-7.0.5.tar.gz
cd redis-7.0.5/
make && make install
redis-cli:是redis提供的命令行客户端
redis-server:是redis的服务端启动脚本
redis-sentinel:是redis的哨兵启动脚本
redis-server
那么前台启动完成了不过你不可以做任何操作。因此我们生产环境一般都是后台启动的!
cd /usr/local/src/redis-7.0.5/
cp redis.conf redis.conf.bck
vi redis.conf
这里我们把redis服务器密码设置成了123321,这个记住,后面要用到!
接下来就可以进行后台启动了:
redis-server redis.conf
此时已经运行完配置文件,但是并没有真正的启动Redis!!想要查看是否运行成功可以使用:
ps -ef | grep redis
当看到redis-server就说明redis-server被加载了,但是还未启动!
使用kill命令杀死后台进程
kill -9 7668
vi /etc/systemd/system/redis.service
修改为
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-7.0.5/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
#启动redis
systemctl start redis
#停止redis
systemctl stop redis
#重启redis
systemctl restart redis
# 查看redis状态
systemctl status redis
#开机自启redis
systemctl enable redis
1.进入到bin目录
cd /usr/local/bin/
2.使用命令行客户端redis-cli [option] [command]
redis-cli -h 192.168.239.128 -p 6379
3.使用AUTH设置密码,与-a选项等价
#这里的密码与redis.conf文件里的requirepass 密码对应
AUTH 123321
下载地址 RedisDesktopManager
下载好了之后,连接虚拟机的IP,密码是redis服务器的密码。(与前面设置的redis.conf文件里的requirepass 密码对应:123321)
随后就能看到16个redis的库。这些库的名称不能修改。
ps:如果连不上,说明Redis服务未开启,可以使用systemctl命令启动服务:
systemctl start redis
如果还是连不上,就关闭linux下的防火墙:
systemctl stop firewalld.service
String:将对象序列化为json字符串后存储,值是字符串。
Hash:值是哈希表,也称散列表。
List:值是list集合,与java中的LinkedList相似,是一个双向链表结构,可正向检索也可反向检索,List是有序的。
Set:Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征。
TTL的值为-1时代表永久有效,-2代表过期。
redis的key是主键且唯一的,为了区分不同类型下的同名key,redis推出了层级存储key的方式:
set ProjectName:product:1 '{"id":1,"name":"RedmiK50 Pro","price":"9999"}'
Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。
SortedSet具备下列特性:
可排序。 元素不重复查询速度快。因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可
jedis是服务于Redis的java客户端
使用jedis需要的步骤如下:
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>4.3.0version>
dependency>
@SpringBootTest
class JedisApplicationTests {
private Jedis jedis;
@BeforeEach
void setup() {
//建立连接
jedis = new Jedis("192.168.239.128", 6379);
//设置密码
jedis.auth("123321");
jedis.select(1);
}
@AfterEach
void close(){
if (jedis!=null){
jedis.close();
}
}
}
@Test
void test(){
String rs = jedis.set("name", "kxy");
System.out.println(rs);
String s = jedis.get("name");
System.out.println(s);
}
由于jedis是线程不安全的,频繁销毁和创建jedis对象会造成性能损耗,因此使用jedis连接池来代替jedis:
public class JedisConnectFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);
poolConfig.setMaxIdle(8);
poolConfig.setMaxIdle(0);
jedisPool = new JedisPool(poolConfig, "192.168.239.128", 6379, 1000, "123321");
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
那么配置好了连接池,就可以从连接池中获取jedis对象了:
void setup() {
//建立连接
jedis = JedisConnectFactory.getJedis();
//设置密码
jedis.auth("123321");
jedis.select(1);
}
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
dependency>
spring:
redis:
host: 192.168.239.128
port: 6379
password: 123321
lettuce:
pool:
max-active: 8 # 最大连接
max-idle: 8 # 最大空闲连接
min-idle: 0 #
max-wait: 100 # 等待连接时间
@SpringBootTest
class RedisApplicationTests {
@Resource
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("name","lisi");
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);
}
}
由于RedisTemplate 默认的序列化方式是jdk 序列化,这样就会导致我们存储key或value的最终显示在客户端上会出现地址,这是我们不期望的。
因此我们需要写一个配置类去修改redisTemplate的序列化方式:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//创建RedisTemplate对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
redisTemplate.setKeySerializer(serializer);
redisTemplate.setHashKeySerializer(serializer);
// 设置Value的序列化
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashValueSerializer(serializer);
//返回
return redisTemplate;
}
}
通用版:
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
由于Json的序列化方式,在反序列化的的前提是确定class类型,因此会把class字节码对象存入到Json对象中,而class字节码对象会带来额外的内存开销。
为了解决这个问题,我们通常不会用json的序列化器,而是使用String序列化器:只能存储String类型的key和value。当存储的是一个java对象时,则需要程序员手动的完成对象的序列化和反序列化。
而正好spring提供了一个StringRedisTemplate类,它的序列化方式默认就是String方式。
以下是分别是存储普通的字符串的key和value以及一个java对象序列化成json对象存储到redis的示例
@SpringBootTest
class RedisStringTests {
@Autowired
private StringRedisTemplate redisTemplate;
@Test
void testString() {
//写入数据存入redis
redisTemplate.opsForValue().set("name1","zs1");
//取数据
Object name1 = redisTemplate.opsForValue().get("name1");
System.out.println(name1);
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
User user = new User("zhangsan", 21);
//手动序列化:将java对象转成json字符串
String json = mapper.writeValueAsString(user);
//数据存入redis
redisTemplate.opsForValue().set("user:200",json);
//获取数据
String jsonUser = redisTemplate.opsForValue().get("user:200");
//手动反序列化:
User user1 = mapper.readValue(jsonUser, User.class);//参数1:要反序列化的json对象。参数2:要反序列化成的类型
System.out.println("user1="+user1);
}
}