Redis高级特性

本文涉及到的命令和数据类型请参见: Redis数据类型和基本操作

命令

  • keys * (可模糊匹配)
> set name mawenxia
OK
> set age 18
OK
> keys *
1) "age"
2) "name"
> keys n*  //模糊匹配
1) "name"
  • exists 判断key是否存在
> exists name
(integer) 1
  • 设置过期时间expire,查看过期时间ttl
> expire name 3600
(integer) 1
> ttl name
(integer) 3598
  • 取消过期时间persist
> persist name
(integer) 1
  • select 选择数据库。一个redis实例,数据库为0到15 一共16个,默认进入的是0数据库。可根据业务逻辑规则,或系统分类进行划分,存储在不同的库中
>SELECT 1
OK
>127.0.0.1:6379[1]> keys *    //这边多了一个[1]
(empty list or set)         //会发现之前的name和age都不在这里
  • move 移动数据到其他库中
127.0.0.1:6379[1]> set sex nan    //在库[1]中存入sex
OK
127.0.0.1:6379[1]> keys *
1) "sex"
127.0.0.1:6379[1]> move sex 0   //移动sex到库[0]中
(integer) 1
127.0.0.1:6379[1]> select 0         //切换到[0]数据库
OK
127.0.0.1:6379> get sex             //获取sex
"nan"                               //数据库[0]中已存在该数据
  • randomkey 随机返回数据库中的一个key 使用场景:抽奖。
  • rename 重命名key
  • echo 打印命令
  • dbsize 查看数据库key的数量
  • info 数据库信息查看 (CPU、内存、主从、集群、Client等信息) 。可用于监控平台
  • config get * 查看配置信息。可用于监控平台
  • flushdb 清空当前数据库 flushall 清空所有数据库

位操作

  • bitset
  • bitcount 计算二进制位中所有1的数量
  • bitop and/or destkey [key1,key2] 按位与按位或操作
  • 位操作在实时统计记录用户活跃量、点击量等应用中能提供高效的应用
  • 基于这个应用,在本公司实际项目中可统计每个实验室每天发生的阳性样本数。以各实验室id为key,366个二进制字节位表示每一天。只要某一天有阳性。就以天为offset把当前位的0改为1。最后可以用bitcount key offset1 offset2统计其他对比指标随意时间段内的阳性数。并且可以用bitop操作来快速对比各实验室间情况。

安全

由于redis速度极快,一个外部用户一秒内可以进行15万次的密码尝试,这意味着需要设定一个非常强大的密码来防止暴力破解,但是再复杂的密码,在大量的尝试下还是会被hit。建议加入计数器,超过数量之后,不允许再登录,锁定一段时间。

  • 密码设置

    vi redis.conf 找得到 requirepass *** 设置密码
    设置密码之后。需要先使用 auth *** 登录

事务

  • 使用multi 打开事务。执行完所有数据操作后,使用 exec 执行生效。
> multi
OK
set p1 1
QUEUED
> set p2 2
QUEUED
> set p3 3
QUEUED
> exec
1) OK
2) OK
3) OK
> keys p*
1) "p1"
2) "p3"
3) "p2"
  • 使用discard 取消事务
> multi
OK
> set p4 4
QUEUED
> set p5 5
QUEUED
> discard
OK
127.0.0.1:6379> keys p*
1) "p1"
2) "p3"
3) "p2"
  • 注意。目前redis还不能保证操作的原子性,可能部分回滚失败,比如事务中间出现报错的时候。
> get name
"mawenxia"
> get age
"19"
> multi    //开启事务
OK
> incr age    //年龄+1
QUEUED
> incr name    //名字+1
QUEUED
> exec      //执行
1) (integer) 20    //年龄+1成功
2) (error) ERR value is not an integer or out of range  //名字+1报错
> get age
"20"    //年龄+1成功。说明事务的回滚失败

Redis JavaAPI

  • 单实例下的redis是单线程的。
  • 单节点java操作redis一般使用Jedis
  • 在redis cluster 集群模式下,需要使用sharedJedis
/**
 * ShardJedis的测试类
 */
public class ShardJedisTest {

    private ShardedJedisPool sharedPool;

    @Before
    public void initJedis(){
        //Jedis池配置
        JedisPoolConfig config =new JedisPoolConfig();
        config.setTestOnBorrow(true);
        String hostA = "127.0.0.1";
        int portA = 6381;
        String hostB = "127.0.0.1";
        int portB = 6382;
        List<JedisShardInfo> jdsInfoList =new ArrayList<JedisShardInfo>(2);
        JedisShardInfo infoA = new JedisShardInfo(hostA, portA);
        JedisShardInfo infoB = new JedisShardInfo(hostB, portB);
        jdsInfoList.add(infoA);
        jdsInfoList.add(infoB);
        sharedPool =new ShardedJedisPool(config, jdsInfoList);
    }

    @Test
    public void testSetKV() throws InterruptedException {
        try {
            for (int i=0;i<50;i++){
                String key = "test"+i;
                ShardedJedis jedisClient = sharedPool.getResource();
                System.out.println(key+":"+jedisClient.getShard(key).getClient().getHost()+":"+jedisClient.getShard(key).getClient().getPort());
                System.out.println(jedisClient.set(key,Math.random()+""));
                jedisClient.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

}
  • 其他操作数据的API和命令行的操作基本一致,可参考Redis的基本命令来查找JedisAPI。
  • Jedis事务操作
//开启事务
Transaction tx = jedis.multi(); 
//执行操作1.2.3...
act1...
act2...
act3...
//提交。并接收操作结果
List<Object> resList = tx.exec();
  • Jedis Pool 使用连接池提高性能.操作结束必须返还连接
SharedJedis sj = pool.getResource();
...各类操作
//操作结束后返还连接
pool.returnResourceObject(sj);

Redis复杂查询技巧

比如做一个类似 select * from user where age = 18 and sex='m'的操作

  • 关键是设计一个合理的存储结构。存储结构如下。说明:把Set当做查询的条件存储,只存放数据的id。然后根据id取全部数据
数据类型 key (field) data
Hash id {"name":"zhangsan","age",18,"sex":"m"}...
Set userage18 key1,key2,key3...
Set usersexm key1,key2...
  • Hash类型的中存储全部user数据。set 类型的“userage18”中存储所有年龄为18的用户的id。同理,“usersexm”存储性别为"m"的用户id

  • 查询时,只要查询Set中符合条件的id,然后根据id取出需要的user数据即可

  • Set集合有"sinter"取交集,“sunion”取并集命令。来取出符合"age=18 and sex=m" 或 "age=18 or and sex=m" 的用户id

    数据结构
    sinter sunion 查询到用户key
  • 最后根据key来获取用户信息。

  • 这么做的好处:如果直接取出全部user数据在代码中判断符合条件的数据,很可能因为数据量过大,导致内存溢出。

分布式系统中的应用

  • setnx 可作为分布式锁使用。对指定的key,线程获取锁时进行setnx 如果能设置成功,即获得锁。操作结束删除。如果未结束。其他线程setnx将失败。
  • incr incrby 可作为各系统的主键生成器,既保证了主键的唯一性,还保证了主键的连续性,利于数据的合并及查找。
  • list push 和pop 可作为消息队列使用
  • zset实现延迟队列 业务场景:订单需要在未支付的30分钟后失效/72小时后设置默认评论等,如果轮询查库,数据量大了会拖死数据库。利用zset的score排序特性,以下单时间作为score,key来区分不同类型的延迟队列,value为mq消息体。这样每种类型的延迟队列只需要有一个任务来查询最小的score跟当前时间做对比判断是否超过时间,如果超过就取出value,发送mq消息,让对应的服务来消费,做对应的业务(订单失效/设置默认评论)。

Redis底层存储结构为 字节数组 故存储和取出时,注意要使用相同的字符集,否则将出现乱码。使用strlen 命令计算字符串长度时,也要特别注意,它计算的是字节数组的长度,并不是字符串长度,比如一个中文字,可能占用多个字节,故长度是会大于1的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容

  • NOSQL类型简介键值对:会使用到一个哈希表,表中有一个特定的键和一个指针指向特定的数据,如redis,volde...
    MicoCube阅读 3,963评论 2 27
  • 本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概...
    kelgon阅读 61,134评论 23 626
  • 【昨日感悟】 要郑重,对待人和事都要郑重。 对人,即使是对两三岁的孩子,在交流时也要把对方看成是一个什么都知道的“...
    爱游泳的Danny阅读 204评论 0 1
  • 松香适量,药店里就有卖。把松香磨成粉,泡到白酒里,白酒要没过肿胀的部位,把手指放到白酒里泡一会,然后把酒里的松香涂...
    谢氏养生堂阅读 238评论 0 1
  • 1.弗洛伊德认为,人天生有性本能,而快感中心的不同,导致了一个人的人格发展,也即性心理发展,有五个阶段:口欲期、肛...
    Joycty阅读 355评论 0 0