Redis使用总结
在项目开发过程中,笔主使用Redis也有一段时间了。在一些特性的场景,Redis能帮助我们解决一些问题。因此,总结一下分享给大家。
1.使用Redis实现分布式锁
- 使用Boolean setIfAbsent(K key, Vvalue)
/**
* Redis访问工具类
*/
@Component
public class RedisDao {
private static Logger logger = LoggerFactory.getLogger(RedisDao.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Resource(name="stringRedisTemplate")
private ValueOperations<String, String> valOpsStr;
/**
* 如果key不存在,就存储一个key-value,相当于SETNX命令
* @param key 键
* @param value 值,可以为空
* @return
*/
public boolean setIfObsent (String key, String value) {
return valOpsObj.setIfAbsent(key, value);
}
}
- 使用Boolean setNX(byte[] key, byte[] value)
@Component
public class RedisDao {
private static Logger logger = LoggerFactory.getLogger(RedisDao.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 设置一个锁
* @param key
* @param value
* @return
*/
public boolean setNX(String key, String value) {
RedisConnection connection = null;
boolean flag = false;
try {
//获取一个连接
connection = stringRedisTemplate.getConnectionFactory().getConnection();
connection.setNX(key.getBytes(), value.getBytes());
connection.expire(key.getBytes(), 120);
logger.info("设置redis锁成功");
flag = true;
} catch (Exception e) {
connection.del(key.getBytes());
logger.error("设置redis锁失败,原因:{}", e);
}
return flag;
}
}
2.分布式场景下使用Redis生成有序递增序列
笔主在开发过程中有个需求,要求主键的格式为“xxx+有序递增的数字”,xxx是一个特定的字符串常量。这时,借助Mysql的主键自增功能显然不能满足需求。这时,可以借助Long increment(K key, long delta)生成有序递增的数字,然后拼接出主键。
@Component
public class RedisDao {
private static Logger logger = LoggerFactory.getLogger(RedisDao.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Resource(name="stringRedisTemplate")
private ValueOperations<String, String> valOpsStr;
/**
* 为指定的key对应的value增加delta
* @param key 键
* @param delta 增量
* @return
*/
public Long increment(String key, long delta){
return valOpsStr.increment(key, delta);
}
}
3.使用 bitmap 实现用户上线次数统计
4.使用Redis的List结构实现分布式队列
5.使用Redis的Set结构实现集合间的并集、交集、差集
例如:两个不同的用户共同关注了哪些主播
6.使用Redis的ZSet结构实现排行榜统计
例如:某个主播的粉丝贡献排行榜,假设主播id为001,这里定义该主播的粉丝贡献排行榜的key为fans_contribution_rank_001。
/**
* Redis访问工具类
*/
@Component
public class RedisDao {
private static Logger logger = LoggerFactory.getLogger(RedisDao.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 添加zset记录
* @param key 键
* @param value 值
* @param score 分数
* @return
*/
public boolean zAdd (String key, String value, double score) {
return zSetOpsStr.add(key, value, score);
}
/**
* 返回按照分数从高到低排序的zset集合
* @param key 键
* @return
*/
public Set<TypedTuple<String>> reverseRangeByScoreWithScores (String key) {
return zSetOpsStr.reverseRangeWithScores(key, 0, -1);
}
}
添加打赏记录和查询的测试代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo1ApplicationTests2 {
private static Logger logger = LoggerFactory.getLogger(Demo1ApplicationTests2.class);
@Autowired
private TestService testService;
@Autowired
private RedisDao redisDao;
@Test
public void contextLoads() {
//主播的粉丝贡献排行榜key
String key = "fans_contribution_rank_001";
//添加用户给主播的打赏记录,参数分别为key、用户id、打赏的道具数
redisDao.zAdd(key, "100001", 100);
redisDao.zAdd(key, "100002", 20);
redisDao.zAdd(key, "100003", 50);
redisDao.zAdd(key, "100004", 210);
redisDao.zAdd(key, "100005", 360);
redisDao.zAdd(key, "100006", 180);
redisDao.zAdd(key, "100007", 270);
//查询主播的粉丝贡献排行榜key
Set<TypedTuple<String>> tuples = redisDao.reverseRangeByScoreWithScores(key);
System.out.println();
for (TypedTuple<String> arg :tuples) {
logger.info("values:{} , score:{}", arg.getValue(), arg.getScore());
}
}
}
测试结果如下:
2018-12-03 17:29:31.841 - values:100005 , score:360.0
2018-12-03 17:29:31.842 - values:100007 , score:270.0
2018-12-03 17:29:31.842 - values:100004 , score:210.0
2018-12-03 17:29:31.842 - values:100006 , score:180.0
2018-12-03 17:29:31.842 - values:100001 , score:100.0
2018-12-03 17:29:31.842 - values:100003 , score:50.0
2018-12-03 17:29:31.842 - values:100002 , score:20.0
版权声明:本文为zhaoheng314原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。