目录
一、Redis简介
Redis 是key-value数据库,支持主从同步,数据存在内存,性能卓越。
AOF 和 RDB备份机制。
五种核心的数据类型:
String
Hash
List
Set
Zset
二、Redis使用
public static void print(int index, Object obj) {
System.out.println(String.format("%d,%s", index, obj.toString()));
}
public static void main(String[] argv){
Jedis jedis = new Jedis();
//remove all keys from the current database
jedis.flushAll();
// get,set
jedis.set("hello", "world");
print(1, jedis.get("hello"));
jedis.rename("hello", "newhello");
print(1, jedis.get("newhello"));
//setex 设置过期时间 15秒
jedis.setex("hello2", 15, "world");
// 数值操作
jedis.set("pv", "100");
jedis.incr("pv");
jedis.decrBy("pv", 5);
print(2, jedis.get("pv"));
print(3, jedis.keys("*"));
// 列表操作, 最近来访, 粉丝列表,消息队列
String listName = "list";
jedis.del(listName);
for (int i = 0; i < 10; ++i) {
jedis.lpush(listName, "a" + String.valueOf(i));
}
print(4, jedis.lrange(listName, 0, 12)); // 最近来访10个id
print(5, jedis.llen(listName));
print(6, jedis.lpop(listName));
print(7, jedis.llen(listName));
print(8, jedis.lrange(listName, 2, 6)); // 最近来访10个id
print(9, jedis.lindex(listName, 3));
print(10, jedis.linsert(listName, BinaryClient.LIST_POSITION.AFTER, "a4", "xx"));
print(10, jedis.linsert(listName, BinaryClient.LIST_POSITION.BEFORE, "a4", "bb"));
print(11, jedis.lrange(listName, 0, 12));
// hash, 可变字段
String userKey = "userxx";
jedis.hset(userKey, "name", "jim");
jedis.hset(userKey, "age", "12");
jedis.hset(userKey, "phone", "18666666666");
print(12, jedis.hget(userKey, "name"));
print(13, jedis.hgetAll(userKey));
jedis.hdel(userKey, "phone");
print(14, jedis.hgetAll(userKey));
print(15, jedis.hexists(userKey, "email"));
print(16, jedis.hexists(userKey, "age"));
print(17, jedis.hkeys(userKey));
print(18, jedis.hvals(userKey));
jedis.hsetnx(userKey, "school", "zju");
jedis.hsetnx(userKey, "name", "yxy");
print(19, jedis.hgetAll(userKey));
// 集合,点赞用户群, 共同好友
String likeKey1 = "newsLike1";
String likeKey2 = "newsLike2";
for (int i = 0; i < 10; ++i) {
jedis.sadd(likeKey1, String.valueOf(i));
jedis.sadd(likeKey2, String.valueOf(i * 2));
}
print(20, jedis.smembers(likeKey1));
print(21, jedis.smembers(likeKey2));
print(22, jedis.sunion(likeKey1, likeKey2));
print(23, jedis.sdiff(likeKey1, likeKey2));
print(24, jedis.sinter(likeKey1, likeKey2));
print(25, jedis.sismember(likeKey1, "12"));
print(26, jedis.sismember(likeKey2, "12"));
jedis.srem(likeKey1, "5");
print(27, jedis.smembers(likeKey1));
// 从1移动到2
jedis.smove(likeKey2, likeKey1, "14");
print(28, jedis.smembers(likeKey1));
print(29, jedis.scard(likeKey1));
// 排序集合,有限队列,排行榜
String rankKey = "rankKey";
jedis.zadd(rankKey, 15, "Jim");
jedis.zadd(rankKey, 60, "Ben");
jedis.zadd(rankKey, 90, "Lee");
jedis.zadd(rankKey, 75, "Lucy");
jedis.zadd(rankKey, 80, "Mei");
print(30, jedis.zcard(rankKey));
print(31, jedis.zcount(rankKey, 61, 100));
print(32, jedis.zscore(rankKey, "Lucy"));
jedis.zincrby(rankKey, 2, "Lucy");
print(33, jedis.zscore(rankKey, "Lucy"));
jedis.zincrby(rankKey, 2, "Luc");
print(34, jedis.zscore(rankKey, "Luc"));
print(35, jedis.zcount(rankKey, 0, 100));
// 1-3 名
print(36, jedis.zrange(rankKey, 1, 3));
print(36, jedis.zrevrange(rankKey, 1, 3));
for (Tuple tuple : jedis.zrangeByScoreWithScores(rankKey, "60", "100")) {
print(37, tuple.getElement() + ":" + String.valueOf(tuple.getScore()));
}
//Ben的排名
print(38, jedis.zrank(rankKey, "Ben"));
print(39, jedis.zrevrank(rankKey, "Ben"));
//Jedis Pool
JedisPool pool = new JedisPool();
for (int i = 0; i < 100; ++i) {
Jedis j = pool.getResource();
j.get("a");
j.close();
}
}
Jedis Pool 线程连接池默认是8条线程。
//JedisAdapter.java
//在对象JedisAdapter对象初始化以后,执行afterPropertiesSet中的内容,将pool初始化
@Override
public void afterPropertiesSet() throws Exception {
//jedis = new Jedis("localhost");
pool = new JedisPool("localhost", 6379);
}
private Jedis getJedis(){
return pool.getResource();
}
public String get(String key) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.get(key);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return null;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public void set(String key, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set(key, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public long sadd(String key, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.sadd(key, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return 0;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public long srem(String key, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.srem(key, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return 0;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
//判断自己是否在集合范围内
public boolean sismember(String key, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.sismember(key, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return false;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public long scard(String key) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.scard(key);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return 0;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public void setex(String key, String value) {
// 验证码, 防机器注册,记录上次注册时间,有效期3天
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.setex(key, 10, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public long lpush(String key, String value) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.lpush(key, value);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return 0;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public List<String> brpop(int timeout, String key) {
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.brpop(timeout, key);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return null;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
三、踩赞功能
//LikeService
/**
* 如果喜欢返回1,如果不喜欢返回 -1, 否则返回0
* @param userId
* @param entityType
* @param entityId
* @return
*/
public int getLikeStatus(int userId, int entityType, int entityId) {
String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
if(jedisAdapter.sismember(likeKey, String.valueOf(userId))) {
return 1;
}
String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
return jedisAdapter.sismember(disLikeKey, String.valueOf(userId)) ? -1 : 0;
}
public long like(int userId, int entityType, int entityId) {
// 在喜欢集合里增加
String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
jedisAdapter.sadd(likeKey, String.valueOf(userId));
// 从反对里删除
String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
jedisAdapter.srem(disLikeKey, String.valueOf(userId));
return jedisAdapter.scard(likeKey);
}
public long disLike(int userId, int entityType, int entityId) {
// 在反对集合里增加
String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
jedisAdapter.sadd(disLikeKey, String.valueOf(userId));
// 从喜欢里删除
String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
jedisAdapter.srem(likeKey, String.valueOf(userId));
return jedisAdapter.scard(likeKey);
}
//LikeController
@RequestMapping(path = {"/like"}, method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String like(@Param("newId") int newsId) {
long likeCount = likeService.like(hostHolder.getUser().getId(), EntityType.ENTITY_NEWS, newsId);
// 更新喜欢数
News news = newsService.getById(newsId);
newsService.updateLikeCount(newsId, (int) likeCount);
eventProducer.fireEvent(new EventModel(EventType.LIKE)
.setActorId(hostHolder.getUser().getId()).setEntityId(newsId)
.setEntityType(EntityType.ENTITY_NEWS).setEntityOwnerId(news.getUserId()));
return ToutiaoUtil.getJSONString(0, String.valueOf(likeCount));
}
@RequestMapping(path = {"/dislike"}, method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String dislike(@Param("newId") int newsId) {
long likeCount = likeService.disLike(hostHolder.getUser().getId(), EntityType.ENTITY_NEWS, newsId);
// 更新喜欢数
newsService.updateLikeCount(newsId, (int) likeCount);
return ToutiaoUtil.getJSONString(0, String.valueOf(likeCount));
}
//HomeController
private List<ViewObject> getNews(int userId, int offset, int limit) {
List<News> newsList = newsService.getLatestNews(userId, offset, limit);
int localUserId = hostHolder.getUser() != null ? hostHolder.getUser().getId() : 0;
List<ViewObject> vos = new ArrayList<>();
for (News news : newsList) {
ViewObject vo = new ViewObject();
vo.set("news", news);
vo.set("user", userService.getUser(news.getUserId()));
if (localUserId != 0) {
vo.set("like", likeService.getLikeStatus(localUserId, EntityType.ENTITY_NEWS, news.getId()));
} else {
vo.set("like", 0);
}
vos.add(vo);
}
return vos;
}
@RequestMapping(path = {"/", "/index"}, method = {RequestMethod.GET, RequestMethod.POST})
public String index(Model model,
@RequestParam(value = "pop", defaultValue = "0") int pop) {
model.addAttribute("vos", getNews(0, 0, 10));
if (hostHolder.getUser() != null) {
pop = 0;
}
model.addAttribute("pop", pop);
return "home";
}