redis-cli(不使用镜像的时候) docker run -d --name w-redis redis redis-server docker exec -it w-redis redis-cli
shutdown //退出redis模式 docker stop 容器的ID //关闭容器
keys * 查看当前库所有key (匹配:keys *1) exists key 判断某个key是否存在 type key 查看你的key是什么类型 del key 删除指定的key数据 unlink key 根据value选择非阻塞删除(仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。) expire key 10 10秒钟:为给定的key设置过期时间 ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期 select 命令切换数据库(一共16个,0~15,默认的是0) dbsize 查看当前数据库的key的数量 flushdb 清空当前库 flushall 通杀全部库
内部实现是ArrayList
set <key><value> 添加键值对 get <key> 查询对应键值 append <key><value> 将给定的<value> 追加到原值的末尾 strlen <key> 获得值的长度 setnx <key><value> 只有在 key 不存在时 设置 key 的值 incr <key> 将 key 中储存的数字值增1 只能对数字值操作,如果为空,新增值为1 decr <key> 将 key 中储存的数字值减1 只能对数字值操作,如果为空,新增值为-1 incrby / decrby <key><步长> 将 key 中储存的数字值增减。自定义步长。 mset <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value对 mget <key1><key2><key3> ..... 同时获取一个或多个 value msetnx <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。 getrange <key><起始位置><结束位置> 获得值的范围,类似java中的substring,前包,后包 setrange <key><起始位置><value> 用 <value> 覆写<key>所储存的字符串值,从<起始位置>开始(索引从0开始)。 setex <key><过期时间><value> 设置键值的同时,设置过期时间,单位秒。 getset <key><value> 以新换旧,设置了新值同时获得旧值。
内部实现:List的数据结构为快速链表quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。
它将所有的元素紧挨着一起存储,分配的是一块连续的内存。
当数据量比较多的时候才会改成quicklist。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QwqOUGOP-1620812325959)(C:\Users\Acer\Pictures\Saved Pictures\redis1.png)]
lpush/rpush <key><value1><value2><value3> .... 从左边/右边插入一个或多个值。 lpop/rpop <key> 从左边/右边吐出一个值。值在键在,值光键亡。 rpoplpush <key1><key2>从<key1> 列表右边吐出一个值,插到<key2>列表左边。 lrange <key><start><stop> 按照索引下标获得元素(从左到右) lrange mylist 0 -1 0左边第一个,-1右边第一个,(0-1表示获取所有) lindex <key><index> 按照索引下标获得元素(从左到右) llen <key> 获得列表长度 linsert <key> before <value><newvalue> 在<value>的后面插入<newvalue>插入值 lrem <key><n><value> 从左边删除n个value(从左到右) lset<key><index><value> 将列表key下标为index的值替换成value
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的****复杂度都是O(1)****。
sadd <key><value1><value2> ..... 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略 smembers <key> 取出该集合的所有值。 sismember <key><value> 判断集合<key>是否为含有该<value>值,有1,没有0 scard<key> 返回该集合的元素个数。 srem <key><value1><value2> .... 删除集合中的某个元素。 spop <key> 随机从该集合中吐出一个值。 srandmember <key><n> 随机从该集合中取出n个值。不会从集合中删除 。 smove <source><destination>value 把集合中一个值从一个集合移动到另一个集合 sinter <key1><key2> 返回两个集合的交集元素。 sunion <key1><key2> 返回两个集合的并集元素。 sdiff <key1><key2> 返回两个集合的差集元素(key1中的,不包含key2中的)
内部实现:Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
hset <key><field><value> 给<key>集合中的 <field>键赋值<value> hget <key1><field> 从<key1>集合<field>取出 value hmset <key1><field1><value1><field2><value2>... 批量设置hash的值 hexists<key1><field> 查看哈希表 key 中,给定域 field 是否存在。 hkeys <key> 列出该hash集合的所有field hvals <key> 列出该hash集合的所有value hincrby <key><field><increment> 为哈希表 key 中的域 field 的值加上增量 1 -1 hsetnx <key><field><value> 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在 .
内部实现:(1)hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
(2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
zadd <key><score1><value1><score2><value2>… 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。 zrange <key><start><stop> [WITHSCORES] 返回有序集 key 中,下标在<start><stop>之间的元素,带WITHSCORES,可以让分数一起和值返回到结果集。 zrangebyscore key minmax [withscores] [limit offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。 zrevrangebyscore key maxmin [withscores] [limit offset count] 同上,改为从大到小排列。 zincrby <key><increment><value> 为元素的score加上增量 zrem <key><value> 删除该集合下,指定值的元素 zcount <key><min><max> 统计该集合,分数区间内的元素个数 zrank <key><value> 返回该值在集合中的排名,从0开始。
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
1、打开一个客户端订阅channel1 SUBSCRIBE channel1 2、打开另一个客户端,给channel1发布消息hello publish channel1 hello
Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。
Bitmaps单独提供了一套命令, 所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量.
setbit<key><offset><value> 设置Bitmaps中某个偏移量的值(0或1) getbit<key><offset> 获取Bitmaps中某个偏移量的值 bitcount<key>[start end] 统计字符串从start字节到end字节比特值为1的数量 bitop and(or/not/xor) <destkey> [key…] bitop是一个复合操作, 它可以做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中。
Bitmaps和Set对比,数据量大的话使用Bitmaps,比如1亿数据。
数据量小的话用Set比如一万数据。
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
pfadd <key>< element> [element ...] 添加指定元素到 HyperLogLog 中 pfcount<key> [key ...] 计算HLL的近似基数,可以计算多个HLL pfmerge<destkey><sourcekey> [sourcekey ...] 将一个或多个HLL合并后的结果存储在另一个HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得
Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。
geoadd<key><longitude><latitude><member> [longitude latitude member...] 添加地理位置(经度,纬度,名称) geopos <key><member> [member...] 获得指定地区的坐标值 geodist<key><member1><member2> [m|km|ft|mi ] 获取两个位置之间的直线距 georadius<key>< longitude><latitude>radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- spring2.X集成redis所需common-pool2--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.0</version> </dependency>
#Redis服务器地址 spring.redis.host=8.142.98.85 #Redis服务器连接端口 spring.redis.port=6379 #Redis数据库索引(默认为0) spring.redis.database= 0 #连接超时时间(毫秒) spring.redis.timeout=1800000 #连接池最大连接数(使用负值表示没有限制) spring.redis.lettuce.pool.max-active=20 #最大阻塞等待时间(负数表示没限制) spring.redis.lettuce.pool.max-wait=-1 #连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle=5 #连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle=0
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setConnectionFactory(factory); //key序列化方式 template.setKeySerializer(redisSerializer); //value序列化 template.setValueSerializer(jackson2JsonRedisSerializer); //value hashmap序列化 template.setHashValueSerializer(jackson2JsonRedisSerializer); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题),过期时间600秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } }
在引用的类中注入即可。 @Autowired private RedisTemplate redisTemplate;
从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。 组队的过程中可以通过discard来放弃组队
1、监控某个Key的值或多个
2、执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
1、取消 WATCH 命令对所有 key 的监视。 2、如果在执行 WATCH 命令之后,EXEC 命令或DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。
1、单独的隔离操作 事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 2、没有隔离级别的概念 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行 3、不保证原子性 事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
1、在虚拟机里面可以使用工具ab模拟高访问量和高并发的测试。 2、安装 yum install httpd-tools 3、遇见的三个问题和解决方案 1)连接Redis超时的问题:使用连接池 2)超卖的问题:使用乐观锁,把库存监视一下,然后把库存减一和添加用户按顺序加到事务里面,在执行。 3)库存遗留问题(乐观锁造成的):LUA脚本
1、将需要持久化的数据先写到一个临时文件,然后在放到持久化文件。 2、RDB的缺点是最后一次持久化后的数据可能丢失。
1、以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件。
如果两个都开启,默认使用AOF 官方推荐两个都启用。 如果对数据不敏感,可以选单独用RDB。 不建议单独用 AOF,因为可能会出现Bug。 如果只是做纯内存缓存,可以都不用
1、从机选择主机的时候用到:slaveof <ip><port> 例如:slaveof 127.0.0.1 6379 2、从机挂掉之后,需要重新连接到主机上面,执行第一步。 3、当主机活了之后,还是主机。
1、一个从机还可以有另外的从机。
1、主机挂掉之后,其他从机有当主机的机会。 可以使用 slaveof no one 将从机变成主机。 不过还需要手动,此方式不可以。下面使用哨兵 2、哨兵选举主机 启动哨兵监控主机,当主机死掉之后,会在从机里面选举出来一个新的主机。 不同与一主多仆,之前死掉的主机活了之后会变成从机。
master=》主机,Slave=》从机。 1、Slave启动成功连接到master后会发送一个sync命令 2、Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步 3、全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。 4、增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步 5、但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
1、cluster nodes 命令查看集群信息。 2、slots(插槽), Redis 集群包含 16384 个插槽。 3、集群状态下插入多个值,需要用到组的概念。例如:mset name{user} wxs age{user} 20,把它们放到USER组里
1、如果主节点下线?从节点能否自动升为主节点?注意:15秒超时 2、主节点恢复后,主从关系会如何?主节点回来变成从机 3、如果所有某一段插槽的主从节点都宕掉,redis服务是否还能继续? 如果某一段插槽的主从都挂掉,而cluster-require-full-coverage 为yes ,那么 ,整个集群都挂掉 如果某一段插槽的主从都挂掉,而cluster-require-full-coverage 为no ,那么,该插槽数据全都不能使 用,也无法存储。 4、redis.conf中的参数 cluster-require-full-coverage
客户访问大量空数据造成服务器压力属于缓存穿透,访问过期的热点key属于缓存击穿,大量key过期属于缓存雪崩。
现象: 1、应用服务器压力增加 2、redis命中率降低 3、一直查询数据库 原因: 1、redis中查找不到Key的值,请求就会访问数据源,而数据源也没有对应的值,最终会压垮数据源。 2、一般这种现象是黑客入侵(非法的url访问)。 解决: 1、对空值缓存:如果访问这个值不存在时,仍然把该值(BULL结果)缓存,设置过期时间短一点,不超过五分钟。 2、采用布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmaps中,一个一定不存在的数据会被 这个 bitmaps拦截掉,从而避免了对底层存储系统的查询压力。 3、实时监控:当发现Redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名 单限制服务。(或者可以报网警)
现象: 1、数据库访问量忽然增加 2、redis中没有大量的Key过期 3、redis正常运行 原因: 1、热点访问key过期。 解决: 1、预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长 2、适时调整:现场监控那些key数据热门,增加存活时间 3、使用锁:效率太低
现象: 1、数据库压力大,服务器崩溃 原因: 1、大量的key值过期。 解决: 1、将缓存失效时间分散开来:在原来失效时间上面加一个随机值,这样每一个缓存失效时间的重复率会降低,避免大量 key失效。 2、设置过期标志更新缓存:如果一个key触发了过期,会通知另外一个进程在后台去更新key的缓存。 3、构建多级缓存架构:使用多级缓存。(比较麻烦) 4、使用队列或者锁:效率低。
单限制服务。(或者可以报网警)
###### 缓存击穿 ```tex 现象: 1、数据库访问量忽然增加 2、redis中没有大量的Key过期 3、redis正常运行 原因: 1、热点访问key过期。 解决: 1、预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长 2、适时调整:现场监控那些key数据热门,增加存活时间 3、使用锁:效率太低
现象: 1、数据库压力大,服务器崩溃 原因: 1、大量的key值过期。 解决: 1、将缓存失效时间分散开来:在原来失效时间上面加一个随机值,这样每一个缓存失效时间的重复率会降低,避免大量 key失效。 2、设置过期标志更新缓存:如果一个key触发了过期,会通知另外一个进程在后台去更新key的缓存。 3、构建多级缓存架构:使用多级缓存。(比较麻烦) 4、使用队列或者锁:效率低。