Redis学习笔记(中)

Redis学习笔记(上)

学习视频【狂神说Java】Redis最新超详细版教程通俗易懂
即使再小的帆也能远航

目录

Hyperloglog

什么是基数?

基数(cardinal number)在数学上,是集合论中刻画任意集合大小的一个概念。两个能够建立元素间一一对应的集合称为互相对等集合。例如3个人的集合和3匹马的集合可以建立一一对应,是两个对等的集合。

简介

Redis在2.8.9版本更新了Hyperloglog数据结构
Redis Hyperloglog是做基数统计的算法

有点:占用的内存是固定的,2^64不同的元素的技术,只需要费12kb的内存,如果要从内存角度考虑,Hyperloglog是首选,大概有0.81的错误率

网页的UV(Unique Visitor,独立访客数)–> 一个人访问网站多次,任然算作一个人

传统方式:使用set集合保存用户的ID,然后就可以统计set集合中元素的数量作为判断标准
这种方法如果保存大量的用户ID,会十分耗内存,我们的目的是计数而不是记录用户ID

命令

pdadd key element [element]:向Hyperloglog中加入element
pfcount key:返回Hyperloglog的个数
pfmerge destkey sourcekey [sourcekey ...]:将多个名为sourcekey的HyperLogLog合并为一个名为destkey的HyperLogLog

测试

pi:0>pfadd mykey a b c d e f
"1"
pi:0>pfcount mykey
"6"
pi:0>pfadd mykey2 a b c d e f g h i j
"1"
pi:0>pfmerge hy mykey mykey2
"OK"
pi:0>pfcount hy
"10"

如果允许容错,就使用这个
如果不允许容错,就使用set

Bitmap

位存储

统计用户信息,活跃|不活跃,登录|未登录,打卡|未打卡 => 这种两个状态的都可以使用Bitmap存储
Bitmaps,位图,一种数据结构,都是操作二进制来进行记录,就只有0和1两个状态
例如:365天 -> 365位,1B = 8bit,46个字节左右就可以存储一个人一年的打卡情况

命令

setbit key offset value:设置名为key的Bitmap在第offset位的值为value
getbit key offset:获取名为key的Bitmap在第offset位的值
bitcount key [start end]:获取Bitmap的中值为1的位数

测试

pi:0>setbit sign 0 0
"0"
pi:0>setbit sign 1 1
"0"
pi:0>setbit sign 2 1
"0"
pi:0>setbit sign 3 0
"0"
pi:0>setbit sign 4 0
"0"
pi:0>setbit sign 5 1
"0"
pi:0>setbit sign 6 1
"0"
pi:0>getbit sign 5
"1"
pi:0>getbit sign 4
"0"
pi:0>bitcount sign
"4"

参考官网:http://www.redis.cn/topics/data-types-intro.html#bitmaps

事务

要不同时成功,要不同时失败 -> 原子性

Redis单条命令是保证原子性,但Redis的事务不保证原子性,Redis的事务没有隔离级别的概念,所以命令在事务中,没有直接执行,只有发起执行命令才会执行

Redis事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务的执行过程中,会按顺序执行。
一致性,顺序性,排他性

Redis的事务:

  • 开启事务(multi)
  • 命令入队(。。。)
  • 执行事务(exec)

正常执行事务

pi:0>multi
"OK"
pi:0>set k1 v1
"QUEUED"
pi:0>set k2 v2
"QUEUED"
pi:0>get k2
"QUEUED"
pi:0>set k3 v3
"QUEUED"
pi:0>exec
 1)  "OK"
 2)  "OK"
 3)  "v2"
 4)  "OK"

放弃事务

pi:0>multi
"OK"
pi:0>set k1 v1 k2 v2 k3 v3
"QUEUED"
pi:0>discard
"OK"
pi:0>get k1
null

编译型异常

命令错误,事务中的所有命令都不会执行

pi:0>multi
"OK"
pi:0>set k1 v1 k2 v2 k3 v3
"QUEUED"
pi:0>getset k4
"ERR wrong number of arguments for 'getset' command"
pi:0>set k5 v5
"QUEUED"
pi:0>exec
"EXECABORT Transaction discarded because of previous errors."
pi:0>get k1
null

运行时异常

如果事务队列中存在存在语法性异常,那么执行命令的时候,其他命令是可以正常执行的,错误命令会抛出异常

pi:0>set k1 v1
"OK"
pi:0>multi
"OK"
pi:0>incr k1
"QUEUED"
pi:0>set k2 v2
"QUEUED"
pi:0>exec
 1)  "ERR value is not an integer or out of range"
 2)  "OK"
pi:0>get k1
"v1"
pi:0>get k2
"v2"

监控(watch)【面试常问】

乐观锁

  • 很悲观
  • 认为什么时候都会出问题
  • 无论做什么都加锁

悲观锁

  • 很乐观
  • 认为什么时候都不会出现问题
  • 所以不会上锁
  • 更新数据的时候判断一下在此期间是否有人修改过数据

watch key [key ...]:监视key

正常执行成功

pi:0>set money 100
"OK"
pi:0>set out 0
"OK"
pi:0>watch money
"OK"
pi:0>multi
"OK"
pi:0>decrby money 20
"QUEUED"
pi:0>incrby out 20
"QUEUED"
pi:0>exec
 1)  "80"
 2)  "20"

失败

测试多线程修改值,使用watch可以当作Redis的乐观锁操作

# 线程一
pi:0>set money 100
"OK"
pi:0>set out 0
"OK"
pi:0>watch money
"OK"
pi:0>multi
"OK"
pi:0>decrby money 10
"QUEUED"
pi:0>incrby out 10
"QUEUED"
pi:0>exec
(nil)
pi:0>
# 线程二
pi:0>get money
"100"
pi:0>incrby money 100
"200"

如果修改失败,获取最新值再次执行即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ashTnm5C-1594539903502)(741848070B614E4599C7DCE234DDEF44)]

Jedis

使用Java操作客户端

什么是Jedis

Jedis是Redis官方推荐的操作Redis的jar包,那么一定要对Jedis十分的熟悉

使用

  1. 导入对应的jar包依赖(创建的Springboot项目,不需要version)
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  1. 编码测试
  • 连接数据库
  • 操作命令
  • 断开连接
@Test
void Test01() {
	//1. new一个对象
	Jedis jedis = new Jedis(new HostAndPort("192.168.0.105", 6379));
	//Jedis的所有的方法就是Redis的命令
	String ping = jedis.ping();
	System.out.println(ping);
	jedis.close();
}

常用API

Redis-key

@Test
void TestKey() {
	Jedis jedis = new Jedis(new HostAndPort("192.168.0.105", 6379));
	System.out.println("清空数据:" + jedis.flushDB());
	System.out.println("判断某个键是否存在" + jedis.exists("username"));
	System.out.println("新增键值对" + jedis.set("username", "Esion"));
	System.out.println("新增键值对" + jedis.set("password", "123456"));
	System.out.println("系统中所有的键值对:" + jedis.keys("*"));
	System.out.println("删除键password:" + jedis.del("password"));
	System.out.println("判断password是否存在:" + jedis.exists("password"));
	System.out.println("判断键username的值的类型:" + jedis.type("username"));
	System.out.println("随机返回key空间中的一个:" + jedis.randomKey());
	System.out.println("重命名key:" + jedis.rename("username", "nickname"));
	System.out.println("取出改后的nickname:" + jedis.get("nickname"));
	System.out.println("按索引查询:" + jedis.select(0));
	System.out.println("删除当前数据库中所有的key:" + jedis.flushDB());
	System.out.println("返回当前数据库中key的数目:" + jedis.dbSize());
	System.out.println("删除所有数据库中所有的key:" + jedis.flushAll());
}

//结果
/*
清空数据:OK
判断某个键是否存在false
新增键值对OK
新增键值对OK
系统中所有的键值对:[password, username]
删除键password:1
判断password是否存在:false
判断键username的值的类型:string
随机返回key空间中的一个:username
重命名key:OK
取出改后的nickname:Esion
按索引查询:OK
删除当前数据库中所有的key:OK
返回当前数据库中key的数目:0
删除所有数据库中所有的key:OK
*/

String

@Test
void TestString() {
	Jedis jedis = new Jedis(new HostAndPort("192.168.0.105", 6379));
	jedis.flushAll();
	System.out.println("======增加数据======");
	System.out.println(jedis.set("key1", "value1"));
	System.out.println(jedis.set("key2", "value2"));
	System.out.println(jedis.set("key3", "value3"));
	System.out.println("删除键key2:" + jedis.del("key2"));
	System.out.println("获取键key2:" + jedis.get("key2"));
	System.out.println("修改key1的值:" + jedis.set("key2", "newvalue2"));
	System.out.println("获取key1的值:" + jedis.get("key1"));
	System.out.println("在key3后面加入值" + jedis.append("key3", "_new"));
	System.out.println("获取key3的值:" + jedis.get("key3"));
	System.out.println("增加多个键值对:" + jedis.mset("key4", "value4", "key5", "value5"));
	System.out.println("获取多个键值对" + jedis.mget("key1", "key2", "key3"));
	System.out.println("删除多个键值对:" + jedis.del("key1", "key2"));
	System.out.println("======新增键值对防止覆盖旧的值======");
	System.out.println(jedis.setnx("key01", "value01"));
	System.out.println(jedis.setnx("key02", "value02"));
	System.out.println(jedis.setnx("key02", "new_value02"));
	System.out.println(jedis.get("key01"));
	System.out.println(jedis.get("key02"));
	System.out.println("======新增键值对并设置有效时间======");
	System.out.println(jedis.setex("key001", 3, "value001"));
	System.out.println(jedis.get("key001"));
	try {
		Thread.sleep(3);
	} catch (Exception e) {
		// TODO: handle exception
	}
	System.out.println(jedis.get("key001"));
	System.out.println("获取key02中的子串:" + jedis.getrange("key02", 2, 3));
	
}
// console
/*
======增加数据======
OK
OK
OK
删除键key2:1
获取键key2:null
修改key1的值:OK
获取key1的值:value1
在key3后面加入值10
获取key3的值:value3_new
增加多个键值对:OK
获取多个键值对[value1, newvalue2, value3_new]
删除多个键值对:2
======新增键值对防止覆盖旧的值======
1
1
0
value01
value02
======新增键值对并设置有效时间======
OK
value001
value001
获取key02中的子串:lu
*/

List

@Test
void TestList() {
	Jedis jedis = new Jedis(new HostAndPort("192.168.0.105", 6379));
	jedis.flushAll();
	System.out.println("======添加一个List======");
	System.out.println(jedis.lpush("list", "value1", "value2", "value3"));
	System.out.println(jedis.lpush("list", "value2"));
	System.out.println(jedis.lpush("list", "value4"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("list0-2的元素:" + jedis.lrange("list", 0, 2));
	System.out.println("============");
	System.out.println("删除列表指定的值,第二个参数为删除的个数(有重复时),后add进去的值会被先删掉,类似于出栈");
	System.out.println("删除指定元素个数:" + jedis.lrem("list", 1, "value2"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("删除下标0-3之外的元素:" + jedis.ltrim("list", 0, 3));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("list列表出栈,左端:" + jedis.lpop("list"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("list添加元素,从列表的右端,与lpush对应:" + jedis.rpush("list", "value5"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("list列表出栈,右端:" + jedis.rpop("list"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("修改list指定下标为1的内容:" + jedis.lset("list", 1, "newvalue2"));
	System.out.println("list的内容:" + jedis.lrange("list", 0, -1));
	System.out.println("============");
	System.out.println("list的长度:" + jedis.llen("list"));
	System.out.println("获取list指定下标为2的内容:" + jedis.lindex("list", 2));
	System.out.println("============");
	jedis.lpush("sort", "3", "1", "4", "5", "2", "6");
	System.out.println("sort排序前:" + jedis.lrange("sort", 0, -1));
	System.out.println(jedis.sort("sort"));
	System.out.println("sort排序后:" + jedis.lrange("sort", 0, -1));
}
// 结果
/*
======添加一个List======
3
4
5
list的内容:[value4, value2, value3, value2, value1]
list0-2的元素:[value4, value2, value3]
============
删除列表指定的值,第二个参数为删除的个数(有重复时),后add进去的值会被先删掉,类似于出栈
删除指定元素个数:1
list的内容:[value4, value3, value2, value1]
删除下标0-3之外的元素:OK
list的内容:[value4, value3, value2, value1]
list列表出栈,左端:value4
list的内容:[value3, value2, value1]
list添加元素,从列表的右端,与lpush对应:4
list的内容:[value3, value2, value1, value5]
list列表出栈,右端:value5
list的内容:[value3, value2, value1]
修改list指定下标为1的内容:OK
list的内容:[value3, newvalue2, value1]
============
list的长度:3
获取list指定下标为2的内容:value1
============
sort排序前:[6, 2, 5, 4, 1, 3]
[1, 2, 3, 4, 5, 6]
sort排序后:[6, 2, 5, 4, 1, 3]
*/

其他的一样,跳过(所有的API就是命令)

事务

@Test
void TestTransaction() {
	Jedis jedis = new Jedis(new HostAndPort("192.168.0.105", 6379));
	jedis.flushAll();
	//开启事务
	Transaction transaction = jedis.multi();
	JSONObject json = new JSONObject();
	json.set("name", "esion");
	json.set("age", 22);
	//jedis.watch("user:1");
	try {
		transaction.set("user:1", json.toString());
		transaction.set("user:2", json.toString());
		int i = 1 / 0;//这个地方会发生异常,事务执行失败
		transaction.exec();
	} catch(Exception e) {
		transaction.discard();
		System.err.println(e.getClass() + e.getMessage());
	} finally {
		System.out.println(jedis.get("user:1"));
		System.out.println(jedis.get("user:2"));
		jedis.close();
	}
}
// 结果
/*
class java.lang.ArithmeticException/ by zero
null
null
*/

SpringBoot整合

在SPringboot2.x之后,原来使用的Jedis被替换为lettuce

Jedis:底层采用的是直连,如果有多个线程操作是不安全的,如果想避免,就使用Jedis Pool
lettuce:底层使用netty,实例可以再过个线程中共享,不存在线程不安全的状况,可以减少线程数量

源码分析

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

	@Bean
	//如果Bean不存在则生效,所以我们可以自己定义一个redisTemplate来替换默认的redisTemplate
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		//默认的RedisTemplate,没有过多的设置,Redis对象都是需要序列化的
		//两个泛型类型都是Object,后面需要强制转换,我们洗完是String
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	//由于String类型是最长使用的,
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

}

使用

  1. 导入依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 配置
spring:
  redis:
    host: 192.168.0.105
    port: 6379
  1. 测试
@SpringBootTest
class RedisApplicationTests {
	
	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Test
	void contextLoads() {
		//redisTemplate操作不同的数据类型,API和命令是一样的
		//opsForCluster
		//opsForGeo
		//opsForHash
		//opsForHyperLogLog
		//opsForList
		//opsForStream
		//opsForValue -> 操作字符串
		//opsForZSet
		
		//处理基本的操作,常用的方法可以直接通过redisTemplate操作,比如事务和基本的增删改查
		
		redisTemplate.opsForValue().set("key", "value");
		System.out.println(redisTemplate.opsForValue().get("key"));
		
		//获取连接操作
		RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
		connection.flushAll();
		connection.flushDb();
	}

}

序列化配置

源码截取

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {

	private boolean enableTransactionSupport = false;
	private boolean exposeConnection = false;
	private boolean initialized = false;
	private boolean enableDefaultSerializer = true;
	private @Nullable RedisSerializer<?> defaultSerializer;
	private @Nullable ClassLoader classLoader;

    //配置序列化
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
	
	@Override
	public void afterPropertiesSet() {

		super.afterPropertiesSet();

		boolean defaultUsed = false;

		if (defaultSerializer == null) {

            //默认的序列化是JDK序列化,我们可能使用JSON来序列化
			defaultSerializer = new JdkSerializationRedisSerializer(
					classLoader != null ? classLoader : this.getClass().getClassLoader());
		}

		if (enableDefaultSerializer) {

			if (keySerializer == null) {
				keySerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (valueSerializer == null) {
				valueSerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (hashKeySerializer == null) {
				hashKeySerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (hashValueSerializer == null) {
				hashValueSerializer = defaultSerializer;
				defaultUsed = true;
			}
		}

		if (enableDefaultSerializer && defaultUsed) {
			Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
		}

		if (scriptExecutor == null) {
			this.scriptExecutor = new DefaultScriptExecutor<>(this);
		}

		initialized = true;
	}
	
}

如果没有实现序列化接口,汇报异常

@getter
@setter
@toString
public class User {

	private String username;
	private String password;
	
}
@Test
void TestObject() throws JsonProcessingException {
	User user = new User("admin", "admin");
	// 真实的开发都是使用JSON来保存对象
	String json = new ObjectMapper().writeValueAsString(user);
	redisTemplate.opsForValue().set("user", user);
	System.out.println(redisTemplate.opsForValue().get("user"));
}
/*
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.qsd.redis.po.User]
*/

如果实现序列化

// 在企业中,实体类都会实现序列化接口
public class User implements Serializable {

	private static final long serialVersionUID = -4869333122434031467L;
	private String username;
	private String password;
	
}
/*
User [username=admin, password=admin]
*/

自定义序列化

@Configuration
public class RedisConfig {
	
	//编写自定义RedisTemplate
	//写好的固定模板,在企业中可以直接使用
	@Bean(value = "redisTemplate")
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		//为了开发方便,一般采用<String, Object>
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		//一定要先设置,否则会报错
		template.setConnectionFactory(redisConnectionFactory);
		
		//配置具体的序列化方法
		//JSON的序列化
		Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		serializer.setObjectMapper(objectMapper);
		//String的序列化
		StringRedisSerializer serializer2 = new StringRedisSerializer();
		
		//key采用StringRedisSerializer序列化
		template.setKeySerializer(serializer2);
		//hash的key也采用StringRedisSerializer序列化
		template.setHashKeySerializer(serializer2);
		//value采用Jackson2JsonRedisSerializer序列化
		template.setValueSerializer(serializer);
		//hash的value采用Jackson2JsonRedisSerializer序列化
		template.setHashValueSerializer(serializer);
		template.afterPropertiesSet();
		
		return template;
	}

}

工具类编写

具体方式参考springboot redis 项目实战 完整篇

Redis的操作对于一个java程序员来说十分的简单,所以更应该学习Redis的原理和理解Redis的思想,还有数据类型的使用场景

redis.conf配置文件

配置文件参数说明

连接:Redis配置 - 菜鸟教程

# units are case insensitive so 1GB 1Gb 1gB are all the same.
# 对大小写不敏感
################################## INCLUDES ###################################
# include /path/to/local.conf
# include /path/to/other.conf
# 可以包含其他配置文件
################################## MODULES #####################################
################################## NETWORK #####################################
bind 127.0.0.1 192.168.0.105
# 绑定ip,注意,这个ip是你的网卡ip,通过ip判断允许那个网卡可以访问,如果想限制ip就只能防火墙
protected-mode yes
# 是否是受保护的模式,一般开起
port 6379
# 绑定端口号
################################# TLS/SSL #####################################
################################# GENERAL #####################################
daemonize yes
# 是否开启守护进程,默认no,前台运行,如果yes则后台运行
pidfile /var/run/redis_6379.pid
# 如果以后台方式运行,我们就需要制定一个pid文件
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)  生产环境使用
# warning (only very important / critical messages are logged)
loglevel notice
# 日志级别
logfile ""
# 生成的日志文件名
databases 16
# 数据库的数量,默认16个
always-show-logo yes
# 是否总是显示logo
################################ SNAPSHOTTING  ################################
# 快照,持久化,在规定的时间内执行了多少次操作,就会被持久化
# Redis是个内存数据库,如果不持久化,断电即失去
save 900 1
# 如果900秒内,至少有1个key被修改,就进行持久化
save 300 10
# 如果300秒内,至少有10个key被修改,就进行持久化
save 60 10000
# 如果60秒内,至少有10000个key被修改,就进行持久化
stop-writes-on-bgsave-error yes
# 持久化出错后是否继续工作,默认开启
rdbcompression yes
# 是否压缩rdb文件,需要消耗一些CPU资源
rdbchecksum yes
# 保存rdb文件时,进行检查校验
dbfilename dump.rdb
# rdb文件名
dir ./
# rdb文件保存位置
################################# REPLICATION #################################
# 复制,后面讲解主从复制再进行讲解
############################### KEYS TRACKING #################################
################################## SECURITY ###################################
# 安全相关
# requirepass foobared
# 默认不设置密码,一般不在配置文件中设置,可以使用命令设置:config set requirepass 123456
#####################################################################
pi@raspberrypi:/opt/redis $ bin/redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass 123456
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"
127.0.0.1:6379> exit
pi@raspberrypi:/opt/redis $ bin/redis-cli
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> ping
PONG
#####################################################################
# 限制 -> 了解
################################### CLIENTS ####################################
# maxclients 10000
# 设置最大连接客户端数量
############################## MEMORY MANAGEMENT ################################
# maxmemory <bytes>
# 配置最大的内存容量
# maxmemory-policy noeviction [连接]
# 内存到达最大值的处理策略
############################# LAZY FREEING ####################################
############################### THREADED I/O #################################
############################## APPEND ONLY MODE ###############################
# AOF配置
appendonly no
# 默认不开启aof模式,默认使用rdb持久化,因为在所有的情况下rdb够用了
appendfilename "appendonly.aof"
# aof文件名
# appendfsync always
# 每次修改都会同步
appendfsync everysec
# 每秒执行一次sync,可能会丢失这一秒的数据
# appendfsync no
# 不执行同步,这个时候操作系统自己同步数据,速度最快
# aof在aof时详解

连接:redis 设置过期Key 的 maxmemory-policy 六种方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值