AskMe項(xiàng)目 Redis學(xué)習(xí) 贊踩實(shí)現(xiàn)

什么是Redis

Key-Value型的數(shù)據(jù)庫(kù)窟哺,和Mysql的二維表不一樣泻轰,性能很好,數(shù)據(jù)存在內(nèi)存中且轨,支持通用數(shù)據(jù)結(jié)構(gòu)浮声,如隊(duì)列,集合旋奢,哈希隊(duì)列等

  1. 官網(wǎng)
  2. github安裝地址
  3. 官網(wǎng)命令
  4. 書籍推薦:《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)));
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辆床,隨后出現(xiàn)的幾起案子佳晶,更是在濱河造成了極大的恐慌,老刑警劉巖讼载,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轿秧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咨堤,警方通過查閱死者的電腦和手機(jī)菇篡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來一喘,“玉大人驱还,你說我怎么就攤上這事⊥箍耍” “怎么了议蟆?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萎战。 經(jīng)常有香客問我咐容,道長(zhǎng),這世上最難降的妖魔是什么撞鹉? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任疟丙,我火速辦了婚禮颖侄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘享郊。我一直安慰自己览祖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布炊琉。 她就那樣靜靜地躺著展蒂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苔咪。 梳的紋絲不亂的頭發(fā)上锰悼,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音团赏,去河邊找鬼箕般。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舔清,可吹牛的內(nèi)容都是我干的丝里。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼体谒,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼杯聚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抒痒,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤幌绍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后故响,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傀广,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年彩届,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了主儡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惨缆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丰捷,到底是詐尸還是另有隱情坯墨,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布病往,位于F島的核電站捣染,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏停巷。R本人自食惡果不足惜耍攘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一榕栏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蕾各,春花似錦扒磁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吝羞,卻和暖如春兰伤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钧排。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工敦腔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恨溜。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓符衔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親筒捺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柏腻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)系吭,斷路器五嫂,智...
    卡卡羅2017閱讀 134,707評(píng)論 18 139
  • NOSQL類型簡(jiǎn)介鍵值對(duì):會(huì)使用到一個(gè)哈希表,表中有一個(gè)特定的鍵和一個(gè)指針指向特定的數(shù)據(jù)肯尺,如redis沃缘,volde...
    MicoCube閱讀 4,000評(píng)論 2 27
  • “××的父親去世了,昨晚的事则吟』蓖危”一早到辦公室,看到師兄發(fā)來的消息氓仲,我大吃一驚水慨,“怎么會(huì)?”我還以為他是在騙我敬扛,可想...
    SHE林閱讀 173評(píng)論 0 0
  • 當(dāng)有人與你發(fā)出不合諧的音符的時(shí)候晰洒;當(dāng)有人與你不在一個(gè)頻道欣賞節(jié)目的時(shí)候;當(dāng)有人不能一路與你一起看風(fēng)景的時(shí)候啥箭,不能也...
    lucky9125閱讀 481評(píng)論 0 0
  • 來到麗江.悠閑安靜.
    時(shí)光流轉(zhuǎn)閱讀 156評(píng)論 0 0