set中的值是不能重复的。 sadd myset "hello" #添加一个值 smembers myset # 查看指定set值 sismember myset hello #判断某一个元素是否在set中 scard myset # 获取集合中的元素个数值 srem myset a1 #移除set指定元素 set是无序,不重复集合 srandmember myset #随机抽set元素 spop myset #随机删除set元素 smove sa sb a1 #将一个库里指定的值移动到另一个库里 微博、B站,共同关注!(并集) 数字集合类: • 差集 sdiff k1 k2 • 交集 sinter k1 k2 • 并集 sunion k1 k2 微博,A用户将所有关注的人放到一个set集合中!将他的粉丝也放到一个集合中 共同关注、共同爱好、二度好友(六度分割理论)
适合对象的存储,string 更加适合字符串存储。 map集合,key-<key,value>(集合) hset myhash filed1 kuang #存储 hget myhash filed1 #获取 hmset myhash filed1 f1 filed2 f2 #存储多个值 hmget myhash filed1 filed2 #获取多个值 hgetall myhash #获取所有的值 hdel myhash filed1 #删除hash指定的段 hlen myhash #获取hash表的字段数量 hexists myhash filed1 #指定值是否存在 hkeys myhash #获取所有的key hvals myhash #获取所有的值 hincrby myhash mynumber 1 #数量累加 hincrby myhash mynumber -1 #数量累减 hsetnx myhash fi4 ff #如果不存在则可以设置,存在不可设置 list
比set多了排序,存储班级成绩表,工资表等 普通消息,1 重要消息 2 权重判断 排行榜 范围查询 zset k1 score v1 #在set基础上增加了一个值 zadd salary 2500 xiaoming #添加值 zrangebyscore salary -inf +inf #从小到大排序,显示名称 zrevrange salary 0 -1 #从大到小排序,显示名称 zrangebyscore salary -inf +inf withscores #从小到大排序,显示值和名称 zrangebyscore salary -inf 2000 withscores #2000一下值升序 zrem salary liu #移除值 zrange salary 0 -1 #查看集合所有值 zcard salary #获取有序集合的个数 zcount salary 1 10000 #获取指定区间的指定数量
思考:朋友的定位,附近的人,打车的距离计算? 规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入! 有效的纬度从-85.05112878度到85.05112878度。 当坐标位置超出上述指定范围时,改命令会返回一个错误 ERR invalid longitude,latitude pair 31.230000,121.470000 添加数据: 值 纬度 经度 名称 geoadd china:city 116.40 39.90 beijing geoadd china:city 121.47 31.23 shanghai geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian geopos china:city beijing #获取指定城市的经度和纬度 geodist china:city beijing shanghai km #查看北京到上海直线距离m km 我附近的人?(获得所有人的地址,定位。)通过半径进行搜索 georadius china:city 110 30 500 km #获取指定经度纬度 500km以内数据 georadius china:city 110 30 500 km withdist #展示具体距离 georadius china:city 110 30 500 km withcoord #展示经度纬度 georadius china:city 110 30 500 km withcoord count 1 #显示指定数量数据 georadiusbymember china:city beijing 1000 km #找出指定位置周围的其他元素 geohash china:city beijing chongqi#将二维的字符串转换为一维的字符串 GEO底层就是zset!所以我们可以使用zset命令实现。 hyperloglog 简介: redis 2.8.9 就更新了 hyperloglog数据结构! 基数统计算法! 页面访问量, 一个人访问一个网站多次,但是还是算作一个人。 传统方式 set用户id,自动去重 如果保存大量用户id,则比较麻烦。我们的目的是记数,而不是保存用户id。 优点:占用的内存是固定的,2^ 64 不同的元素基数,只需要费12kb内存! 如果要从内存角度考虑,hyperloglog就是首选 0.81% 错误率,统计UV任务,可以忽略不计的! pfadd mykey a b c d e f g h i j #创建一组元素 pfcount mykey #查询一组元素数量 pfmerge mykey3 mykey myketto #合并两组元素生成新一组,去重,并集 如果允许容错,那么一定使用hyperloglog ! 如果不允许容错,就使用set或自己的数据类型即可。
位运算。 统计疫情感染人数: 0 00 0 1 0 1 0 统计用户信息,活跃人数,不活跃,登陆,未登录人数。 位图(数据结构)操作二进制位来进行记录,0 1 两个状态 setbit sign 0 0 # 周一打卡 setbit sign 1 0 # 周二打卡 getbit sign 4 #查看指定天数打卡情况 bitcount sign #显示打卡天数
原子性:mySql:ACID 要么全部成功,要么全部失败 Redis单条命令是保证原子性了,但Redis事务是不支持原子性的。 事务的本质:一组命令的集合! 悲观锁:很悲观,认为什么时候都会出问题,无论做什么都会加锁。 乐观锁:很乐观认为什么都不会出问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改数据 获取version ,更新时比较version 监视:watch 可以写乐观锁,本身就是乐观锁
是官网推荐java开发工具,使用Java操作Redis的一个中间键先说说jedis(底层)
<dependencies> <!--导入jedis包--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.2.0</version> </dependency> <!--fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> </dependencies>
2.编码测试
• 连接数据库
• 操作命令
• 断开连接 jedis.close();
public static void main(String[] args) { Jedis jedis = new Jedis("127.0.0.1",6379); //所有的命令就是之前所有指令,掌握指令很重要 System.out.println(jedis.ping());//测试连接 PONG JSONObject jsonObject = new JSONObject(); jsonObject.put("hello","www"); jsonObject.put("name","kkk"); jedis.flushDB(); Transaction multi = jedis.multi();//开启事务 String string = jsonObject.toJSONString(); try { multi.set("user1",string); multi.set("user2",string); int i = 1/0;//代码跑出异常事务,执行失败! multi.exec();//执行事务 } catch (Exception e) { multi.discard();//放弃事务 e.printStackTrace(); } finally { System.out.println(jedis.get("user1")); System.out.println(jedis.get("user2")); jedis.close(); } }
springboot操作数据:spring-data jpa jebc mongodb redis! springDate和SpringBoot也是齐名的项目! springboot 所有配置类都在 spring-boot-autoconfigure-2.5.3.jar 中 spring.factories 文件里
@Bean @ConditionalOnMissingBean(name = "redisTemplate")//我们可以自己定义一个redisTemplate来替换这个默认的 @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { //默认的RedisTemplate 没有过多配置,redis对象都是需要序列化的! //两个泛型都是object,object类型,后使用需要强制转换,<string,object> RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } //由于string类型是很常用的类型,所以就单独提出一个bean @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
spring.redis.host=127.0.0.1 spring.redis.port=6379
测试!
默认为jdk序列化!
首先redis存储需要进行序列化,使用jar包自带 redisTemple 默认使用的是jdk进行序列化代理,可充写redisTemple方法更换序列化模式,序列化后存储key为非其他格式拼接字符,正常存储
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { //为了开发方便一般直接使用 <String, Object> RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory); //Json序列化配置 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); //String 的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
所有的Redis操作,对于开发者来说,十分简单,更重要的是去理解redis的思想和每一种数据结构的用处和作用场景!
配置文件 unit单位对大小写不敏感 包含文件、就好比我们学的spring 、import 、include 导入文件 bind 绑定ip protected-mode yes #保护模式 port 6379 #端口设置 GENERAL #通用配置 daemonize yes #以守护进程的方式运行,默认是no pidfile /var/run/redis_6379.pid #如果以后台方式运行,我们就需要指向一个pid文件! 默认 notice #生产环境 logfile "" #日志的文件路径名 databases 16 #默认16个数据库 always-show-logo no #是否总是显示LOGO SNAPSHOTTING 快照 (持久化) 在规定的时间内,执行了多少操作,则会持久化一个文件,.rdb .aof 文件 redis是内存数据库,如果没有持久化,那么数据就会断电即失! 如果在3600秒内 至少有1个key进行了修改,我们就进行持久化操作 # save 3600 1 如果在300秒内 至少有100个key进行了修改,我们就进行持久化操作 # save 300 100 如果在60秒内 至少有10000个key进行了修改,我们就进行持久化操作 # save 60 10000 我们之后学习持久化,会定义这个测试! stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要工作 rdbcompression yes #是否压缩rdb文件,需要消耗cpu文件 rdbchecksum yes #保存rdb文件时,检查校验 dbfilename dump.rdb #rdb文件保存目录 REPLICATION 复制,~主从复制再扯 SECURITY 安全 默认无密码 CLIENTS 客户端 maxclients 10000 #最大客户端连接数量 maxmemory <bytes> #redis配置最大内存容量 maxmemory-policy noeviction #内存到达上线处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 2、allkeys-lru : 删除lru算法的key 3、volatile-random:随机删除即将过期key 4、allkeys-random:随机删除 5、volatile-ttl : 删除即将过期的 6、noeviction : 永不过期,返回错误 Redis持久化 Redis发布订阅 Redis主从复制(哨兵模式) Redis缓存穿透和雪崩