项目Redis 应用实例

Redis 目前应用相当广泛,由于是内存存储,性能很好,所以也在很多业务场景下都有其适用性,前段时间经常有同事问到使用Redis 的细节问题,如该使用它的哪种类型来解决某种场景下的某些问题,本文总结整理后,并给出实际的使用实例。

首先Redis 是开源的,ANSI C语言编写,key-value 的存储系统,内存存储数据,也可以通过配置根据策略去持久化数据。 

包含五种数据结构:

 

一、String 字符串

      最基础的数据存储类型,并且是二进制安全,也就是说该类型可以接受任何格式数据,图像,文字等,应用场景主要适用于热数据的缓存;其主要操作有,get set 等;

      下边是一个常用的模式,当有数据的改动,需要同时同步到redis和db中,为了不存储太多不常用的数据,可以在key增加一个过期时间,当要获取数据时可以直接从redis中获取数据,如果已经过期,可以再从db中获取,来保证数据的有效性,这种模式在一定程度上很有效的减少对db磁盘的频繁访问,提高性能。

 

def update_info(info):
      save_info_to_db(info)
      save_info_to_redis(info)

def get_info(id):
      res = get_info_from_redis(id)
      if not res:
            return get_info_from_db(id)

 

二、Hash -字典

      Redis hash 是一个string 类型的 key -value 的映射表,特别适用于存储对象,如果没有该类型。我们常做的做法是把 对象的属性和值dump成json串来存储,但是要是获取某个属性值,或者是要修改某个属性值,只能是先get, 然后 json load,修改后还要json dump 再保存,既繁琐,又效率低下,而使用Redis hash 会很便捷高效,如下图,可以很方便的设置 user:info:1110 这个对象的各个属性和值,并且可以单独update 属性值;

      

 

三、List - 链表

       Redis 使用双端列表实现List,常见的应用是消息队列,可以使用*PUSH操作往队列中加入消息,工作的进程可以使用POP操作从队列中获取消息,理解Redis List 首先要把它想成是一个列表,列表的左端(Left) 也就是列表的前段,右端(Right)也就是列表的后端,所有L开头的操作,都是在列表的左端,也就是头部进行操作,所有R开头的操作,都是在列表的右端,也就是尾部进行操作,那我们就不难理解,RPUSH 和 LPUSH了,分别是从列表的左边和右边插入数据。LPOP和RPOP是从两端移除并获取数据。BLPOP和BRPOP 是阻塞式的POP。在工作进程较为常用,没有任务就一直阻塞,有任务就获取出来执行。 还有一些LLEN LINDEX也较为常用。详细命令可以参考 http://redis.readthedocs.io/

 

四、Set - 集合

       特点:就是一堆不重复的数据的组合,并且Redis 提供了对集合求交集,差集,并集的操作。基于这两个特点,就可以应用于很多业务场景,

       (1)由于其天生具有去重的功能,所以很多要求唯一性的记录就可以使用set 类型,比如系统要记录今天所登录的账号列表,就可以使用Set,每次登录的时候放入到今天的key中;

       (2)接着上边的例子,如果想要知道连续三天内都登录的账号列表,那么使用刚才三天的set 取交集就可以轻松的搞定;

 

五、Sorted Set - 有序集合

       特点:在Set 的基础上增加 权重参数 score,集合中的元素会自动按照score进行排序,常见的应用,比如获取业务中的TOP N 数据,可以使用该数据结构高效的获取。

        sorted set 是比较有意思而且很使用的一种数据类型,就在前两天体验到了它的力量。这里分享给大家:

        背景:系统中要做数据的异步celery统计。一个站点有很多漏洞,每个漏洞变化后就要触发一次站点统计任务,当然漏洞变化的地方很多。所以把触发统计任务抽成一个接口供各模块来调用。但是问题来了。很多情况下,一个站点的多个漏洞会在一段时间内都改变,所以接口会在较短的时间内接受到多次同一个站点的统计任务。

        思路:把站点id 和 当时的timestap 放入 sorted set 中, 后台进程把sorted set 中timestamp 小于 某个值得获取到,下发。思想主要是避免了一个站点下多个漏洞状态更新,导致的多个统计任务执行,通过延迟下发,比较时间来避免这种多次的下发任务。

        下图是业务中的celery 任务情况,在使用sorted set 方法优化前,任务量和增加速度比较大。优化后观察,在15个worker下,基本上可以做到消息的实时处理。这就是sorted set 的一个应用。其实在业务中做数据TOP N的场景,使用sorted set 更方便。

 

                                                            图二:7点左右的任务量



  

                                                   图三:8点左右的任务量

 

 



  图四:Redis Sorted Set 控制下发

总结:Redis 这五种类型的数据,可以应用在我们业务的不同场景中,帮助我们提高性能,而不仅仅是缓存和消息队列~, 当然如果不清楚现有的使用方式是否合理时,可以通过INFO MONITOR SLOWLOG 来排查和发现一些潜在问题;

 

       

 

在 Java 项目使用 Redis,可以通过多种方式实现,其中最常见的是使用 Jedis 或 Spring 提供的 RedisTemplate。以下是一个使用 Jedis 的完整示例,展示如何连接 Redis 服务器并执行基本的字符串操作和集合操作。 ### 使用 Jedis 连接 Redis 并操作字符串 Jedis 是 Redis 的 Java 客户端实现,可以通过它直接 Redis 服务器进行交互。首先需要添加 Jedis 的 Maven 依赖: ```xml <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.0.1</version> </dependency> ``` 接下来是一个完整的 Java 示例代码: ```java package com.redistest; import redis.clients.jedis.Jedis; public class RedisStringExample { public static void main(String[] args) { // 创建 Jedis 实例,连接到 Redis 服务器 Jedis jedis = new Jedis("192.168.222.101", 6379); // 测试连接是否成功 System.out.println("Redis 服务是否启动: " + jedis.ping()); // 设置字符串值 jedis.set("zking", "获取到 zking 字符值"); jedis.set("baidu", "获取到 baidu 字符值"); // 获取并打印存储的字符串 System.out.println("Redis 存储的字符串为: " + jedis.get("zking")); // 关闭连接 jedis.close(); } } ``` ### 使用 Jedis 操作有序集合(Sorted Set) 除了字符串操作,Redis 还支持有序集合(Sorted Set),可以使用 `ZADD`、`ZCOUNT` 和 `ZREM` 等命令进行操作: ```java package com.redistest; import redis.clients.jedis.Jedis; import java.util.HashMap; import java.util.Map; public class RedisSortedSetExample { private static Jedis jedis = new Jedis("192.168.222.101", 6379); public static void main(String[] args) { System.out.println("Redis 服务是否启动: " + jedis.ping()); // 添加有序集合成员 Map<String, Double> scoreMap = new HashMap<>(); scoreMap.put("wurui", 5.0); scoreMap.put("bob", 3.5); scoreMap.put("jack", 6.0); Long addResult = jedis.zadd("score", scoreMap); System.out.println("成功添加的成员数量: " + addResult); // 查询指定分数范围内的成员数量 Long countResult = jedis.zcount("score", 2, 4); System.out.println("分数在 2 到 4 之间的成员数量: " + countResult); // 移除有序集合中的成员 Long removeResult = jedis.zrem("score", "tom"); System.out.println("成功移除的成员数量: " + removeResult); // 关闭连接 jedis.close(); } } ``` ### 使用 RedisTemplate(Spring 项目) 如果你使用的是 Spring 框架,可以通过 `RedisTemplate` 来操作 Redis。以下是一个 Spring 配置和使用的示例: #### 添加 Spring Data Redis 依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` #### 配置 RedisTemplate: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` #### 使用 RedisTemplate 操作数据: ```java @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } public void delete(String key) { redisTemplate.delete(key); } } ``` 以上代码展示了如何在 Java 项目使用 Redis,包括使用 Jedis 进行字符串和有序集合操作,以及在 Spring 项目使用 RedisTemplate。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值