redisは点賛機能を実現する

3498 ワード

Mysql
ユーザーの「いいね」レコードをMysqlに書き込む
  • 文章がほめられた回数を記録する
  • ユーザーはそれらの文章
  • を称賛した.
    欠点
    人気のある文章には多くのユーザーがいいねをしたり、短時間でたくさんいいねをされたりして、データベースの読み書きのプレッシャーが大きい.
    redisストレージ、一括消去データベース
    redisはデータの格納が速く、多種のデータ構造をサポートし、incr方法をサポートする.
    メリット
  • 高性能
  • データベース読み書き圧力を緩和
  • 欠点
  • 開発複雑
  • はデータの安全性を保証することができなくて、redisが切る時データを失うことができて、同時に直ちにredisの中のデータを同期しないで、redisメモリが置換する時に
  • を淘汰されるかもしれません
    具体的な実装
    Mysql 、ユーザーは文章表をほめた.
    Redis
    public void saveLiked2Redis(String likedUserId, String likedPostId) {
            String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
            redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.LIKE.getCode());
        }
    
        public void unlikeFromRedis(String likedUserId, String likedPostId) {
            String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
            redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.UNLIKE.getCode());
        }
    
        public void deleteLikedFromRedis(String likedUserId, String likedPostId) {
            String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
            redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
        }
    
        public void incrementLikedCount(String likedUserId) {
           redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, 1);
        }
    
        public void decrementLikedCount(String likedUserId) {
           redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1);
        }
    
        public List getLikedDataFromRedis() {
            Cursor> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);
            List list = new ArrayList<>();
            while (cursor.hasNext()){
                Map.Entry entry = cursor.next();
                String key = (String) entry.getKey();
    
                String[] split = key.split("::");
                String likedUserId = split[0];
                String likedPostId = split[1];
                Integer value = (Integer) entry.getValue();
    
                UserLike userLike = new UserLike(likedUserId, likedPostId, value);
                list.add(userLike);
    
                redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
            }
    
            return list;
        }
    
        public List getLikedCountFromRedis() {
            Cursor> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);
            List list = new ArrayList<>();
            while (cursor.hasNext()){
                Map.Entry map = cursor.next();
                String key = (String)map.getKey();
                LikedCountDTO dto = new LikedCountDTO(key, (Integer) map.getValue());
                list.add(dto);
    redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key);
            }
            return list;
        }

    hashscanメソッドを使用して、単一hashkeyのすべてのデータを取得します.
  • scanコマンドの時間的複雑さもO(N)であるが,スレッドをブロックすることなく分割的に行われる.
  • scanコマンドはlimitパラメータを提供し、結果を返すたびに最大エントリ数を制御できます.
  • scanコマンドはインクリメンタルループであり、呼び出すたびに要素の一部だけが返されます.だからKEYS命令の穴はありません.
  • scanコマンドは、0からループを開始し、0までループを終了するカーソルを返します.

  • keyでのfieldが多すぎる場合、keyを時間またはゾーンモードで分割することも考えられる