- 4、Redis新增的数据类型
- 4.1 Bitmaps
- 4.1.1 基本命令
- 4.1.2 实例
- 4.1.3 Bitmaps和set的对比
- 4.2 HyperLogLog
- 4.2.1 基本命令
- 4.2.2 实例
- 4.3 Geospatial
- 4.3.1 基本命令
- 4.3.2 实例
- 5、Jedis *** 作redis
- 5.1 Jedis-String
- 5.2 Jedis-List
- 5.3 Jedis-Set
- 5.4 Jedis-Hash
- 5.5 Jedis-Zset
- 6、Springboot整合Redis
- 1、pom依赖
- 2、配置config
- 3、测试redisTemplate
- 4、配置RedisUtil类,对redisTemplate进行封装
接上文:Redis入门-----五种基本数据类型
4、Redis新增的数据类型 4.1 BitmapsRedis提供了Bitmaps这个“数据类型”可以实现对二进制位的 *** 作:
-
Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行 *** 作。
-
Bitmaps单独提供了一套命令, 所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BcWJWK5T-1639188520085)(C:UsersBanditDesktopnotenote.assetsimage-20211210100111428.png)]
setbit4.1.2 实例#设置Bitmaps中某个偏移量的值(0或1) getbit #获取Bitmaps中某个偏移量的值 bitcount [start end] #统计字符串从start字节到end字节比特值为1的数量 bitop and(or/not/xor) [key…] #bitop是一个复合 *** 作,它可以做多个Bitmaps的and(交集) 、 or(并集)not(非) xor(异或) *** 作并将结果保存在destkey中。
①每个独立用户是否访问过网站存放在Bitmaps中, 将访问的用户记做1, 没有访问的用户记做0, 用偏移量作为用户的id。
设置键的第offset个位的值(从0算起) , 假设现在有20个用户,userid=1,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pLqr7e4g-1639188520086)(C:UsersBanditDesktopnotenote.assetsimage-20211210101006955.png)]
unique:users:20201106代表2020-11-06这天的独立访问用户的Bitmaps
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZHlIq4T-1639188520087)(C:UsersBanditDesktopnotenote.assetsimage-20211210100953625.png)]
注意:很多应用的用户id以一个指定数字(例如10000) 开头, 直接将用户id和Bitmaps的偏移量对应势必会造成一定的浪费, 通常的做法是每次做setbit *** 作时将用户id减去这个指定数字。
在第一次初始化Bitmaps时, 假如偏移量非常大, 那么整个初始化过程执行会比较慢, 可能会造成Redis的阻塞。
②获取id=8的用户是否在2020-11-06这天访问过, 返回0说明没有访问过:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BCVKXU5r-1639188520087)(C:UsersBanditDesktopnotenote.assetsimage-20211210103515062.png)]
③计算2022-11-06这天的独立访问用户数量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJOBzruh-1639188520088)(C:UsersBanditDesktopnotenote.assetsimage-20211210103603953.png)]
④bitop复合 *** 作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d9lKKmPr-1639188520089)(C:UsersBanditDesktopnotenote.assetsimage-20211210103922744.png)]
4.1.3 Bitmaps和set的对比1、假设网站有1亿用户, 每天独立访问的用户有5千万, 如果每天用集合类型和Bitmaps分别存储活跃用户可以得到表
set和Bitmaps存储一天活跃用户对比
set和Bitmaps存储独立用户空间对比
2、 假如该网站每天的独立访问用户很少, 例如只有10万(大量的僵尸用户) , 那么两者的对比如下表所示, 很显然, 这时候使用Bitmaps就不太合适了, 因为基本上大部分位都是0。
set和Bitmaps存储一天活跃用户对比(独立用户比较少)
处理基数问题:求集合中不重复元素个数的问题称为基数问题。
解决基数问题有很多种方案:
(1)数据存储在MySQL表中,使用distinct count计算不重复个数
(2)使用Redis提供的hash、set、bitmaps等数据结构来处理
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。
HyperLogLog是降低精度来平衡存储空间的
优点:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
4.2.1 基本命令pfadd4.2.2 实例< element> [element ...] #添加指定元素到 HyperLogLog 中 pfcount [key ...] #计算HLL的近似基数,可以计算多个HLL pfmerge [sourcekey ...] #将一个或多个HLL合并后的结果存储在另一个HLL中
①将所有元素添加到指定HyperLogLog数据结构中时:
- 如果执行命令后HLL估计的近似基数发生变化,则返回1
- 否则返回0。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNgIbMhQ-1639188520090)(C:UsersBanditDesktopnotenote.assetsimage-20211210132522089.png)]
②用HLL存储每天的UV,计算一周的UV可以使用7天的UV合并计算即可(计算每一个合并返回)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLbynL8l-1639188520091)(C:UsersBanditDesktopnotenote.assetsimage-20211210132622048.png)]
③每月活跃用户可以使用每天的活跃用户来合并计算可得(计算每一个合并到最后一个返回最后一个)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FkXjGAsX-1639188520091)(C:UsersBanditDesktopnotenote.assetsimage-20211210132638752.png)]
4.3 GeospatialGEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见 *** 作。
4.3.1 基本命令#添加地理位置(经度,纬度,名称),无法添加南北极, geoadd4.3.2 实例[longitude latitude member...] #获得指定地区的坐标值 geopos [member...] #获取两个位置之间的直线距离 geodist [m|km|ft|mi ] #以给定的经纬度为中心,找出某一半径内的元素 georadius < longitude> radius m|km|ft|mi
①添加:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HstpxlDU-1639188520092)(C:UsersBanditDesktopnotenote.assetsimage-20211210144147174.png)]
②获取:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yqpfzj5Y-1639188520093)(C:UsersBanditDesktopnotenote.assetsimage-20211210144200925.png)]
③计算直线距离:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zfgIwMJy-1639188520094)(C:UsersBanditDesktopnotenote.assetsimage-20211210144217375.png)]
④找出半径内元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u5KgtyiS-1639188520094)(C:UsersBanditDesktopnotenote.assetsimage-20211210144244613.png)]
5、Jedis *** 作redis
需要导入的包:
redis.clients jedis3.7.0
基本用法:
private static final String host = "xx.xx.xx.xx"; private static final String password = "xxxxxx"; public void jedisDemo(){ Jedis jedisConnection = new Jedis(host,6379);//建立连接 jedisConnection.auth(password); //密码验证 //.... jedisConnection.close(); //用完后要关闭连接 }
以下 *** 作均可在第③节基本 *** 作找到对应,仅演示部分
5.1 Jedis-String@Test public void jedisString(){ Jedis jedisConnection = new Jedis(host,6379); jedisConnection.auth(password); jedisConnection.flushDB(); //set jedisConnection.set("k1", "v1"); System.out.println(jedisConnection.get("k1")); //append jedisConnection.append("k1","v2"); System.out.println(jedisConnection.get("k1")); //mset jedisConnection.mset("k11","v11","k22","v22","k33","v33"); System.out.println(jedisConnection.keys("*")); //mget List5.2 Jedis-Listmget = jedisConnection.mget("k11", "k22", "k33", "k1"); System.out.println(mget); jedisConnection.close(); }
@Test public void jedisList(){ Jedis jedisConnection = new Jedis(host,6379); jedisConnection.auth(password); jedisConnection.flushDB(); jedisConnection.lpush("k1","1","2","3","4","5"); System.out.println(jedisConnection.lrange("k1",0,-1)); jedisConnection.rpush("k2","1","2","3","4","5"); System.out.println(jedisConnection.lrange("k2",0,-1)); jedisConnection.rpoplpush("k1","k2"); System.out.println(jedisConnection.lrange("k1",0,-1)); System.out.println(jedisConnection.lrange("k2",0,-1)); jedisConnection.linsert("k2", ListPosition.AFTER,"1","插入"); System.out.println(jedisConnection.lrange("k2",0,-1)); jedisConnection.close(); }5.3 Jedis-Set
@Test public void jedisSet(){ Jedis jedisConnection = new Jedis(host,6379); jedisConnection.auth(password); jedisConnection.flushDB(); jedisConnection.sadd("k1","s1","s2","s3","s4","s5"); jedisConnection.sadd("k2","s2","s6","s10","s3"); System.out.println("k1:"+jedisConnection.smembers("k1")); System.out.println("k1随机两个数:"+jedisConnection.srandmember("k1", 2)); System.out.println("交集"+jedisConnection.sinter("k1", "k2")); System.out.println("并集"+jedisConnection.sunion("k1", "k2")); System.out.println("差集"+jedisConnection.sdiff("k1", "k2")); jedisConnection.smove("k1","k2","s5"); System.out.println("k1:"+jedisConnection.smembers("k1")); System.out.println("k2:"+jedisConnection.smembers("k2")); jedisConnection.close(); }5.4 Jedis-Hash
@Test public void jedisHash(){ Jedis jedisConnection = new Jedis(host,6379); jedisConnection.auth(password); jedisConnection.flushDB(); HashMap5.5 Jedis-Zsetmap = new HashMap<>(); map.put("name","zhangbing"); map.put("age","20"); jedisConnection.hset("user1",map); jedisConnection.hset("user2","name","wangwu"); jedisConnection.hset("user2","age","17"); System.out.println(jedisConnection.hget("user1", "age")); System.out.println(jedisConnection.hvals("user2")); jedisConnection.close(); }
@Test public void jedisZSet(){ Jedis jedisConnection = new Jedis(host,6379); jedisConnection.auth(password); jedisConnection.flushDB(); HashMap6、Springboot整合Redis 1、pom依赖map = new HashMap<>(); map.put("java", 100.0); map.put("redis",200.0); map.put("mysql",300.0); jedisConnection.zadd("zkey1",map); System.out.println(jedisConnection.zrange("zkey1", 0, -1)); System.out.println(jedisConnection.zrangeWithScores("zkey1", 0, -1)); System.out.println(jedisConnection.zrangeByScore("zkey1", 1.0, 200.0)); System.out.println(jedisConnection.zrank("zkey1", "java")); jedisConnection.zincrby("zkey1",500,"java"); System.out.println(jedisConnection.zrank("zkey1", "java")); jedisConnection.close(); }
2、配置configorg.springframework.boot spring-boot-starter-data-redis2.5.4 redis.clients jedis
通过springboot-autoconfigre包里面找到RedisAutoConfigration。仿造他的来配redisTemplate
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iuSYlwkE-1639188520095)(C:UsersBanditDesktopnotenote.assetsimage-20211211092721841.png)]
@EnableCaching @Configuration public class RedisConfig extends CachingConfigurerSupport { @Bean @Primary public RedisTemplate3、测试redisTemplateredisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate<>(); RedisSerializer 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);过期,用下方这条语句替代 om.activateDefaultTyping(LaissezFaireSubTypevalidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 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 redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypevalidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 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; } }
- 需要将redisTemplate注入进来
- redisTemplate.opsFor[XXX]---->就是对redis各种数据类型 *** 作的封装
@SpringBootTest class MyspringbootApplicationTests { @Autowired RedisTemplateredisTemplate; @Test void contextLoads() { Department department = new Department(1, "A部门"); redisTemplate.opsForValue().set("k1","v1"); redisTemplate.opsForList().rightPush("departKey",department); System.out.println(redisTemplate.opsForValue().get("k1")); System.out.println(redisTemplate.opsForList().range("departKey", 0, -1)); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m7e2Yo0C-1639188520096)(C:UsersBanditDesktopnotenote.assetsimage-20211211092959802.png)]
4、配置RedisUtil类,对redisTemplate进行封装@Component public final class RedisUtil { @Autowired private RedisTemplateredisTemplate; // =============================common============================ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete((Collection ) CollectionUtils.arrayToList(key)); } } } // ============================String============================= public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } // ================================Map================================= public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } public Map
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)