1 Redis入门
Redis优点:性能很好、支持的数据很完善、使用简单 Redis应用: 1.缓存:使用非常频繁的数据,可以放在内存上 2.排行榜:访问非常频繁的帖子,放在内存上 3.计数器:每访问一下帖子,浏览量+1,这个动作很频繁,用Redis实现 4.社交网络:点赞、点踩、关注,动作很频繁,这种数据存在数据库里也不好存,以键值对的方式存在内存里 5.消息队列:可以满足要求,但不是专门的
Redis主要学数据类型,会存数据类型就ok了,用各种命令
官网:https://redis.io/
下载win版:https://github.com/microsoftarchive/redis 管理员cmd
redis-cli
select 1
flushdb
set test:count 1
get test:count
incr test:count
decr test:count
hset test:user id 1
hget test:user id
lpush test:ids 101 102 103
llen test:ids
lindex test:ids 0
lrange test:ids 0 2
rpop test:ids
sadd test:teachers aaa bbb ccc ddd eee
scard test:teachers
spop test:teachers
smembers test:teachers
zadd test:students 10 aaa 20 bbb 30 ccc
zscore test:students ccc
zrank test:students ccc
zrange test:students 0 2
keys *
keys test*
type test:user
exists test:user
del test:user
expire test:students 10
2 Spring整合Redis
#RedisProperties
spring.redis.database=11
spring.redis.host=localhost
spring.redis.port=6379
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.json());
template.setHashKeySerializer(RedisSerializer.string());
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class RedisTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testStrings(){
String redisKey = "test:count";
redisTemplate.opsForValue().set(redisKey, 1);
System.out.println(redisTemplate.opsForValue().get(redisKey));
System.out.println(redisTemplate.opsForValue().increment(redisKey));
System.out.println(redisTemplate.opsForValue().decrement(redisKey));
}
@Test
public void testHash(){
String redisKey = "test:user";
redisTemplate.opsForHash().put(redisKey, "id", 1);
redisTemplate.opsForHash().put(redisKey,"username","zhangsan");
System.out.println(redisTemplate.opsForHash().get(redisKey, "id"));
System.out.println(redisTemplate.opsForHash().get(redisKey, "username"));
}
@Test
public void testLists(){
String redisKey = "test:ids";
redisTemplate.opsForList().leftPush(redisKey, 101);
redisTemplate.opsForList().leftPush(redisKey, 102);
redisTemplate.opsForList().leftPush(redisKey, 103);
System.out.println(redisTemplate.opsForList().size(redisKey));
System.out.println(redisTemplate.opsForList().index(redisKey, 0));
System.out.println(redisTemplate.opsForList().range(redisKey, 0, 2));
System.out.println(redisTemplate.opsForList().leftPop(redisKey));
System.out.println(redisTemplate.opsForList().leftPop(redisKey));
System.out.println(redisTemplate.opsForList().leftPop(redisKey));
}
@Test
public void testSets() {
String redisKey = "test:teachers";
redisTemplate.opsForSet().add(redisKey,"刘备","关羽","张飞");
System.out.println(redisTemplate.opsForSet().size(redisKey));
System.out.println(redisTemplate.opsForSet().pop(redisKey));
System.out.println(redisTemplate.opsForSet().members(redisKey));
}
@Test
public void testSortedSets() {
String redisKey = "test:students";
redisTemplate.opsForZSet().add(redisKey, "唐僧", 80);
redisTemplate.opsForZSet().add(redisKey, "悟空", 90);
redisTemplate.opsForZSet().add(redisKey, "八戒", 70);
System.out.println(redisTemplate.opsForZSet().zCard(redisKey));
System.out.println(redisTemplate.opsForZSet().score(redisKey,"八戒"));
System.out.println(redisTemplate.opsForZSet().rank(redisKey,"八戒"));
System.out.println(redisTemplate.opsForZSet().reverseRank(redisKey,"八戒"));
}
@Test
public void testKeys() {
redisTemplate.delete("test:user");
System.out.println(redisTemplate.hasKey("test:uesr"));
redisTemplate.expire("test:students", 10, TimeUnit.SECONDS);
}
@Test
public void testBoundOperations(){
String redisKey = "test:count";
BoundValueOperations operations = redisTemplate.boundValueOps(redisKey);
operations.increment();
System.out.println(operations.get());
}
@Test
public void testTransactional(){
Object obj = redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
String redisKey = "text:tx";
operations.multi();
operations.opsForSet().add(redisKey,"zhangsan");
operations.opsForSet().add(redisKey,"lisi");
System.out.println(operations.opsForSet().members(redisKey));
operations.opsForSet().add(redisKey,"wangwu");
System.out.println(operations.opsForSet().members(redisKey));
return operations.exec();
}
});
System.out.println(obj);
}
}
注意最后几行的事务:
查询一定要放在事务之外
redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
String redisKey = "text:tx";
operations.multi();
operations.opsForSet().add(redisKey,"zhangsan");
operations.opsForSet().add(redisKey,"lisi");
System.out.println(operations.opsForSet().members(redisKey));
operations.opsForSet().add(redisKey,"wangwu");
System.out.println(operations.opsForSet().members(redisKey));
return operations.exec();
}
});
3 点赞
点赞是个很频繁的动作,将点赞存到redis里提高性能。核心是对redis的使用
向Redis存数据、取数据,操作数据的过程中,是以key为关键的 为了让key反复复用,要写一个工具专门生成key
3.1 生成Key的工具RedisKeyUtil
public class RedisKeyUtil {
private static final String SPLIT = ":";
private static final String PREFIX_ENTITY_LIKE = "like:entity";
public static String getEntityLikeKey(int entityType,int entityId){
return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;
}
}
3.2 编写Service
@Service
public class LikeService {
@Autowired
private RedisTemplate redisTemplate;
public void like(int userId, int entityType, int entityId){
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);
if(isMember){
redisTemplate.opsForSet().remove(entityLikeKey, userId);
}else{
redisTemplate.opsForSet().add(entityLikeKey, userId);
}
}
public long findEntityLikeCount(int entityType, int entityId){
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().size(entityLikeKey);
}
public int findEntityLikeStatus(int userId, int entityType, int entityId){
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().isMember(entityLikeKey, userId)?1:0;
}
}
3.3 编写Controller
点赞:点的时候是异步请求,整个页面不刷新,点完之后改变状态就行了 用map封装返回的结果,返回JSON格式的字符串
@RequestMapping(path = "/like",method = RequestMethod.POST)
@ResponseBody
public String like(int entityType,int entityId){
User user = hostHolder.getUser();
likeService.like(user.getId(), entityType, entityId);
long likeCount = likeService.findEntityLikeCount(entityType, entityId);
int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);
Map<String, Object> map = new HashMap<>();
map.put("likeCount", likeCount);
map.put("likeStatus", likeStatus);
return CommunityUtil.getJSONString(0, null, map);
}
3.4 修改动态页面中对帖子点赞的显示
|