Redis初学(二)

166 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

Hash是什么

redis的hash数据结构,其实就是string的升级版,它把string数据结构的key,value 中的value类型升级位hash(和Java的hash结构一样的结构) HashMap<String,HashMap<String,String>>();

每个hash的存储大小:可以存储2的(32-1)方的键值对(40多亿)

Redis存储Java对象常用String,那为什么还要hash来存储呢?

Redis存储Java对象,一般是String或Hash两种,什么时候用String?什么时候用Hash呢?

String的存储通常用在频繁操作,它的存储格式是json,即把java对象转换为json,然后存入redis.

Hash的存储场景应用在频繁写操作,即,当对象的某个属性频繁修改时,不适用string+json的数据结构,因为不灵活,每次修改都需要把整个对象转换为json存储。如果采用hash,就可以针对某个属性单独修改,不用序列号去修改整个对象。例如,商品的库存、价格、关注数、评价数经常变动时,就使用存储hash结果。 例如:购物车

常用命令

HSET key field value

将哈希表key中的字段field的值设为value。

HGET key field

获取存储在哈希表中指定字段的值

hset product:100 name iphone11
hget product:100 name

HMSET key field1 value1 [field2 value2]

同时将多个 field-value (域-值)对设置到哈希表 key 中。

HMGET key field1 [field2 field3 ...]

获取所有给定字段的值

hmset product:100 price 5000 detail "I love xiaomi"
hmget produc:100 name price datail

HKEYS key

获取指定hash中所有field值

hkeys product:100

HVALS key

获取指定hash中所有value值

hvals product:100

HGETALL key

获取指定hash中所有field、value值

hgetall product:100

HLEN key

获取指定hash中元素的个数

hlen product:100

HINCRBY key field data(整形)

给指定field 对应的value值加上data数组

HINCRBYFLOAT key field data(浮点数)

给指定 field 对应的 value 值加上 data 数值

hincrby product:100 price 100
hgetall product:100

HEXISTS key field

检查指定的field是否存在

hexists product:100 name

HDEL key field1 [field2 fiedl3 ...]

删除一个或多个哈希表字段

hdel product:100 name
hgetall product:100

案例:Springboot+redis+hash存储商品数据

入门Hash

  1. 加入依赖包
  2. 创建商品的redis处理数据
//参数:Product obj
//TODO 先进db
//创建商品,先把数据添加到数据库,再存入redis
//key:"前缀"+商品id
//批量put操作,puttAll 等于 hmset命令
this.redisTemplate.opsForHash().putAll(key,map);
//根据key获取数据 hget key field命令
Object name=this.redisTemplate.opsForHash().get(key,"name");
log.info("name={}",name);

商品涨价

//参数:int id,int price

String key="product:"+id;
//商品价格涨价 increment等于  hincrby命令
this.redisTemplate.opsForHash().increment(key,"price",price);
Object price2=this.redisTemplate.opsForHash().get(key,"price");
log.info("price={}",price2);

购物车功能

前提要求:用户已经登录的情况下

购物车涉及高并发,会出现数据一致性问题。这块后期讲。

一、购物车场景分析

步骤1:先登录你的京东账号,清空以前购物车,然后添加一件商品A,保证你的购物车只有一件商品A。

步骤2:退出登录,购物车添加商品B,然后关闭游览器再打开。(请问:购物车的商品B是否存在?)存在

步骤3:再次登录你的京东账号,(请问:你的购物车有几件商品)

二、图解分析(欠着)

三、redis实现 往购物车加入2件商品 采用hash数据结果,key=cart:user:用户id

hset cart:user:1000 101 1
hset cart:user:1000 102 1
hgetall cart:user:1000

修改购物车的数据,为某件商品添加数量

hincrby cart:user:1000 101 1
hincrby cart:user:1000 102 10
hgetall cart:user:1000

统计购物车有多少件商品

hlen cart:user:1000

删除购物车某件商品

hdel cart:user:1000 102
hgetall cart:user:1000

四、Java代码

步骤1:登录状态下添加商品到购物车

①、添加购物车

@PostMapping(value = "/addCart")
    public void addCart(@RequestBody Cart obj) {
        String key = CART_KEY + obj.getUserId();
        Boolean hasKey = redisTemplate.opsForHash().getOperations().hasKey(key);
        //存在
        if(hasKey){
            this.redisTemplate.opsForHash().put(key, obj.getProductId().toString(), obj.getAmount());
        }else{
            this.redisTemplate.opsForHash().put(key, obj.getProductId().toString(), obj.getAmount());
            this.redisTemplate.expire(key,90, TimeUnit.DAYS);
        }
    }


②修改购物车的数量

@PostMapping(value = "/updateCart")
    public void updateCart(@RequestBody Cart obj) {
        String key = CART_KEY + obj.getUserId();
        this.redisTemplate.opsForHash().put(key, obj.getProductId().toString(), obj.getAmount());
    }

③删除购物车

@PostMapping(value = "/delCart")
    public void delCart(Long userId, Long productId) {
        String key = CART_KEY + userId;
        this.redisTemplate.opsForHash().delete(key, productId.toString());
    }

④查询购物车

@PostMapping(value = "/findAll")
    public CartPage findAll(Long userId) {
        String key = CART_KEY + userId;
        CartPage cartPage = new CartPage();
        //查购物车的总数
        long size = this.redisTemplate.opsForHash().size(key);
        cartPage.setCount((int) size);

        //查询购物车的所有商品
        //entries=hgetall命令
        Map<String, Integer> map = this.redisTemplate.opsForHash().entries(key);
        List<Cart> cartList = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            Cart cart = new Cart();
            cart.setUserId(userId);
            cart.setProductId(Long.parseLong(entry.getKey()));
            cart.setAmount(entry.getValue());
            cartList.add(cart);
        }
        cartPage.setCartList(cartList);
        return cartPage;
    }

后续写 cookie+redis 实现不登录的前提下 实现加入数据。

淘宝短链接 如何设计 有什么好处 什么算法实现的?

《短链接转换器》的原理:

  1. 长链接转换为短链接 实现原理:长链接转换为短链接加密串key,然后存储于redis的hash结构中。
  2. 重定向到原始的url 实现原理:通过加密串key到redis找出原始url,然后重定向出去