什么是Redis
Key-Value型的數(shù)據(jù)庫(kù)窟哺,和Mysql的二維表不一樣泻轰,性能很好,數(shù)據(jù)存在內(nèi)存中且轨,支持通用數(shù)據(jù)結(jié)構(gòu)浮声,如隊(duì)列,集合旋奢,哈希隊(duì)列等
- 官網(wǎng)
- github安裝地址
- 官網(wǎng)命令
- 書籍推薦:《Redis設(shè)計(jì)與實(shí)現(xiàn)》
基本命令
- set key value key為你想添加的鍵值泳挥,value為你想添加的鍵值對(duì)應(yīng)的值,value可以為任何類型的數(shù)據(jù)結(jié)構(gòu)
- get key找到key對(duì)應(yīng)的value值
- select num選擇一個(gè)數(shù)據(jù)庫(kù)(默認(rèn)為16個(gè)數(shù)據(jù)庫(kù)至朗,select 9表示選擇第9個(gè)數(shù)據(jù)庫(kù))
- keys 正則表達(dá)式 找到滿足正則表達(dá)式的所有鍵值
Redis config
- 打開安裝文件夾中的redis.windows.conf羡洁,以下幾行表示900秒中有一個(gè)key值發(fā)生變化,就會(huì)進(jìn)行一次備份爽丹,300秒中有10個(gè)key值發(fā)生變化,就會(huì)進(jìn)行一次備份辛蚊,最后一行同理粤蝎。因?yàn)镽edis是內(nèi)存型的數(shù)據(jù)庫(kù),所以需要一個(gè)機(jī)制來讓改變的數(shù)據(jù)同步到文件中
save 900 1
save 300 10
save 60 10000
- 兩種存儲(chǔ)方式
RDB:某一時(shí)刻數(shù)據(jù)庫(kù)當(dāng)前狀態(tài)袋马,把最終結(jié)果保存起來初澎,適合修改次數(shù)比較多的情況
AOF:不記最終結(jié)果,記錄所有執(zhí)行的命令(通過再執(zhí)行一遍命令虑凛,來得到數(shù)據(jù)庫(kù)當(dāng)前狀態(tài))碑宴,可以避免丟失數(shù)據(jù)
使用Jedis連接Redis
github地址
安裝方法
1. 項(xiàng)目中添加依賴(在pom.xml中添加)
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2. 代碼中使用方法
Jedis jd=new Jedis("redis://localhost:6379/6");
//連接第6個(gè)數(shù)據(jù)庫(kù)(安裝時(shí)默認(rèn)端口為6379)
jd.flushDB(); //將該數(shù)據(jù)庫(kù)中的數(shù)據(jù)清除,flushAll是將所有數(shù)據(jù)都清除
jd.set("hello","fsa"); //添加key value對(duì)
print(1,jd.get("hello")); //jd.get獲取key值對(duì)應(yīng)的value
3.List的使用
雙向列表桑谍,適用于最新列表延柠,關(guān)注列表
String name="list";
jd.del(name);
jd.lpushx(name,"ifexists");//如果name這個(gè)key存在才Push
print(0,jd.lrange(name,0,jd.llen(name)));//lrange得到下標(biāo)從start到end的name中元素list
for(int i=0;i<10;i++)
{
jd.lpush(name,"a"+String.valueOf(i),"b"+String.valueOf(i));
//從左邊壓入,相當(dāng)于棧锣披,先進(jìn)來的下標(biāo)大
}
for(int i=11;i<20;i++)
jd.rpush(name,"a"+String.valueOf(i));
//從右邊壓入贞间,相當(dāng)于隊(duì)列贿条,先進(jìn)來的下標(biāo)小
print(1,jd.lrange(name,0,jd.llen(name)));//llen獲取列表長(zhǎng)度
print(2,jd.lindex(name,6));//獲取下標(biāo)為6的元素
jd.linsert(name, BinaryClient.LIST_POSITION.AFTER,"a8","hello");
jd.linsert(name, BinaryClient.LIST_POSITION.AFTER,"a8","hello");
//在“a8”元素后面插入兩個(gè)hello,執(zhí)行了兩次
jd.linsert(name, BinaryClient.LIST_POSITION.BEFORE,"a8","you");
//在“a8”元素前面插入一個(gè)you
print(5,jd.lpop(name));//pop掉第一個(gè)元素增热,并返回第一個(gè)元素
jd.lrem(name,2,"hello");//刪除兩個(gè)hello
jd.lset(name,0,"me");//把下標(biāo)為0的設(shè)為me
jd.ltrim(name,0,9);//裁剪整以,只留下下標(biāo)0-9的元素
4.Hash的使用
String hset="hset";
jd.hset(hset,"name","ERIKA");//在hset中設(shè)置key-value對(duì),name對(duì)應(yīng)為ERIKA
jd.hset(hset,"age","21");
jd.hset(hset,"school","fdu");
print(1,jd.hgetAll(hset));//得到所有hset中的key-value對(duì)峻仇,結(jié)果類似dict
print(2,jd.hget(hset,"name"));//得到hset中name這個(gè)key對(duì)應(yīng)的value
print(3,jd.hexists(hset,"family"));//判斷hset中是否有family這個(gè)key,返回boolean
print(5,jd.hkeys(hset));//得到hset所有的keys的集合
print(6,jd.hlen(hset));//返回hset的長(zhǎng)度
print(7,jd.hdel(hset,"school"));//刪除hset的school這個(gè)key的鍵值對(duì)
jd.hsetnx(hset,"name","hello");//如果不存在就添加公黑,存在則不再修改,可以防止篡改
jd.hsetnx(hset,"school","fduu");
5.Set的使用
String name="set";
String name2="set2";
for(int i=0;i<10;i++)
{
jd.sadd(name,String.valueOf(i));//在集合name中添加值
jd.sadd(name2,String.valueOf(i*i));
}
print(1,jd.scard(name));//返回name的長(zhǎng)度
jd.srem(name,"4");//刪除4這個(gè)元素
print(2,jd.smembers(name));//返回name中所有元素的集合
jd.smove(name2,name,"16");//把name2中的16移到name中摄咆,name2中刪除凡蚜,name中添加
print(5,jd.sismember(name,"9"));//判斷9是否為name集合中的元素
print(7,jd.sunion(name,name2));//求并
print(8,jd.sinter(name,name2));//求交
print(9,jd.sdiff(name2,name));//求不同的元素
6.Sorted List的使用
String name="sortedlist";
jd.zadd(name,100,"Erika");//有序列表中添加名字和score的對(duì)應(yīng)值
jd.zadd(name,80,"Lily");
jd.zadd(name,60,"Ben");
jd.zadd(name,40,"Jim");
print(1,jd.zcard(name));//返回list長(zhǎng)度
print(2,jd.zcount(name,60,100));//計(jì)算score為60-100的人數(shù)
print(3,jd.zrange(name,0,2));//返回score從小到大第0-2名的名字
print(4,jd.zrangeByScore(name,60,100));//成績(jī)從小到大60-100分的名字
print(5,jd.zrevrangeByScore(name,100,80));//成績(jī)從大到小60-100分的名字
print(6,jd.zscore(name,"Erika"));//返回名叫Erika的成績(jī)
jd.zincrby(name,5,"Lily");//給Lily的成績(jī)加5分
print(7,jd.zrevrange(name,0,jd.zcard(name)));//輸出所有成績(jī)從大到小排序的人名
for(Tuple tuple:jd.zrevrangeByScoreWithScores(name,100,60))
{
print(8,tuple.getElement()+":"+String.valueOf(tuple.getScore()));
//輸出 名字:成績(jī)
}
print(9,jd.zrank(name,"Lily"));//得到Lily從小到大的排名
print(10,jd.zrevrank(name,"Lily"));//得到Lily從大到小的排名
String s="zset";
jd.zadd(s,1,"a");
jd.zadd(s,1,"g");
jd.zadd(s,1,"b");
jd.zadd(s,1,"d");
print(11,jd.zlexcount(s,"-","+"));//計(jì)算從負(fù)無窮到正無窮的個(gè)數(shù)
print(12,jd.zlexcount(s,"[b","[c"));//計(jì)算從b-c(左右都包)的個(gè)數(shù),按照字典序豆同,lex只有在score一樣時(shí)有效
print(13,jd.zlexcount(s,"(b","[g"));//左不包右包
jd.zremrangeByLex(s,"(b","[g");//刪除這個(gè)區(qū)間內(nèi)的所有元素
7.鏈接池的使用
默認(rèn)8個(gè)線程可以連接番刊,從池中取出連接后如果不close掉線程8個(gè)之后的進(jìn)不來,所以用好一定要關(guān)掉
JedisPool pool=new JedisPool();
for(int i=0;i<10;i++)
{
Jedis j=pool.getResource();
print(i,j.keys("*"));
print(i,j.get("pv"));
j.close();
}
使用這種方式影锈,默認(rèn)getresource是第0號(hào)數(shù)據(jù)庫(kù),使用下面的方法可以設(shè)定為第6號(hào)數(shù)據(jù)庫(kù)
JedisPool pool=new JedisPool("redis://localhost:6379/6");
8.Json序列化實(shí)現(xiàn)對(duì)象的緩存和取出
User user=new User();
user.setPassword("1");
user.setHeadUrl("fd.png");
user.setSalt("fdsa");
user.setName("hello");
user.setId(10);
//轉(zhuǎn)換成Json字符串
jd.set("user1",JSONObject.toJSONString(user));
//取出時(shí)使用parseObject來將json字符串回到class
User user2= JSON.parseObject(jd.get("user1"),User.class);
print(10,user2.getName());
集合實(shí)現(xiàn)贊踩功能
1.建立JedisService來實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接和具體操作的接口(其他功能又需要使用Redis數(shù)據(jù)庫(kù)時(shí)芹务,可以重復(fù)使用)
@Service
public class JedisService implements InitializingBean{
private static final Logger logger= LoggerFactory.getLogger(JedisService.class) ;
private JedisPool pool;
public long addkeyvalue(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.sadd(key,value);
}
catch (Exception e)
{
logger.error("redis添加失敗"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
public long delvalue(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.srem(key,value);
}
catch (Exception e)
{
logger.error("刪除失敗"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
public boolean ismember(String key,String value)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.sismember(key,value);
}
catch (Exception e)
{
logger.error("獲取是否為成員失敗"+e);
}
finally {
if(j!=null)
j.close();
}
return false;
}
public long getcount(String key)
{
Jedis j=null;
try
{
j=pool.getResource();
return j.scard(key);
}
catch(Exception e)
{
logger.error("獲取總數(shù)失敗"+e);
}
finally {
if(j!=null)
j.close();
}
return 0;
}
@Override
public void afterPropertiesSet() throws Exception {
pool=new JedisPool("redis://localhost:6379/6");
}
}
2. 建立LikeService來實(shí)現(xiàn)實(shí)際Like or DisLike的數(shù)據(jù)更新(多個(gè)頁(yè)面位置需要實(shí)現(xiàn)贊踩功能時(shí)可以重復(fù)使用)
@Service
public class LikeService {
@Autowired
JedisService j;
public long addLike(int entity_type,int entity_id,int user_id)
{
String key= new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.addkeyvalue(key,String.valueOf(user_id));
}
public long addDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
return j.addkeyvalue(key,String.valueOf(user_id));
}
public int isLikeorDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
if(j.ismember(key,String.valueOf(user_id)))
return 1;
key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
if(j.ismember(key,String.valueOf(user_id)))
return 2;
return 0;
}
public long getCountLike(int entity_type,int entity_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.getcount(key);
}
public long dellike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getLikeKey(entity_type,entity_id);
return j.delvalue(key,String.valueOf(user_id));
}
public long delDislike(int entity_type,int entity_id,int user_id)
{
String key=new RedisKeyUtil().getDislikeKey(entity_type,entity_id);
return j.delvalue(key,String.valueOf(user_id));
}
}
3. 建立RedisKeyUtil工具,來根據(jù)實(shí)際的功能和ID等參數(shù)鸭廷,實(shí)現(xiàn)生成Keys的功能枣抱,以防止出現(xiàn)Key值重復(fù)而導(dǎo)致覆蓋的問題
public class RedisKeyUtil {
private int entity_type;
private int entity_id;
public String getLikeKey(int entype,int id)
{
return "Like-"+String.valueOf(entype)+"-"+String.valueOf(id);
}
public String getDislikeKey(int entype,int id)
{
return "Dislike-"+String.valueOf(entype)+"-"+String.valueOf(id);
}
}
4.Controller中添加相關(guān)路徑和方法
@Controller
public class LikeController {
@Autowired
HostHolder host;
@Autowired
LikeService like;
@RequestMapping(path={"/like"},method={RequestMethod.POST})
@ResponseBody
public String likeit(@RequestParam("commentId")int entity_id)
{
User user=host.getuser();
if(user==null)
return WendaUtil.generatejson(999);
if(like.isLikeorDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId())==2)
{
like.delDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
}
like.addLike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
return WendaUtil.generatejson(0,String.valueOf(like.getCountLike(EntityType.ENTITY_COMMENT,entity_id)));
}
@RequestMapping(path={"/dislike"},method={RequestMethod.POST})
@ResponseBody
public String dislikeit(@RequestParam("commentId")int entity_id)
{
User user=host.getuser();
if(user==null)
return WendaUtil.generatejson(999);
if(like.isLikeorDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId())==1)
{
like.dellike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
}
like.addDislike(EntityType.ENTITY_COMMENT,entity_id,user.getId());
return WendaUtil.generatejson(0,String.valueOf(like.getCountLike(EntityType.ENTITY_COMMENT,entity_id)));
}
}