点讃モジュール設計-Redisキャッシュ+タイミングライトデータベース高性能点讃機能を実現
38559 ワード
ソースアドレス:github.com/cachecats/c…
いいねはシステム全体の小さなモジュールとして、コードは
本稿ではSpringCloudに基づいて,ユーザが「いいね」を発し,「いいね」を取り消した後,まずRedisに格納し,2時間おきにRedisからいいねデータを読み出してデータベースに書き込み,永続化して格納する.
いいね機能は多くのシステムにありますが、機能が小さいのを見ないで、よく考えなければならないことが多いです.
いいね、いいねを取り消すのは高頻度の操作で、毎回データベースを読み書きすると、大量の操作がデータベースの性能に影響するので、キャッシュが必要です.
どのくらいRedisから一度データを取ってデータベースに保存するかは、プロジェクトの実際の状況によって決まりますが、私は一時的に2時間設定しました.
プロジェクトのニーズは、誰が「いいね」をクリックしたのかを確認する必要があるので、「いいね」をクリックした人や「いいね」をクリックした人を保存するには、簡単にカウントすることはできません.
文章は4つの部分に分けて紹介します. Redisキャッシュ設計及び実現 データベース設計 データベース操作 オープンタイミングタスク永続化データベース へ格納
一、Redisキャッシュの設計と実現
1.1 Redis設置及び運転
Redisのインストールは、関連するチュートリアルを参照してください.
DockerをインストールしてRedisを実行すると言います
Redisがインストールされている場合は、コマンドラインを開き、Redisを起動するコマンドを入力します.
1.2 RedisとSpringBootプロジェクトの統合は を導入する.起動クラスに注釈 を追加する. Redis構成クラス を記述する.
これでRedisのSpringBootプロジェクトでの構成が完了し、快適に使用できます.
1.3 Redisのデータ構造タイプ
Redisは、String(文字列)、List(リスト)、Set(集合)、Hash(ハッシュ)、Zset(整列集合)の5つの異なるデータ構造タイプとの間のキーのマッピングを格納することができる.
この5つのデータ構造タイプについて簡単に説明します.
構造タイプ
構造ストレージの値
構造の読み書き能力
String
文字列、整数または浮動小数点数
文字列または文字列の一部全体に対して操作を実行します.オブジェクトと浮動小数点数の自己増加(increment)または自己減少(decrement)
List
チェーンテーブルの各ノードに文字列が含まれているチェーンテーブル
チェーンテーブルの両端から要素をプッシュまたはポップアップします.オフセット量に基づいてチェーンテーブルをトリミングする(trim);単一または複数の要素を読み込みます.値に基づいて要素を検索または削除
Set
文字列を含む無秩序コレクタ(unorderedcollection)であり、含まれる各文字列はユニークで異なる
単一の要素を追加、取得、削除します.エレメントがコレクションに存在するかどうかを確認します.交差、並列、差分セットを計算します.コレクションからランダムに要素を取得する
Hash
キー値ペアを含む無秩序分散リスト
単一のキー値ペアを追加、取得、削除します.すべてのキー値ペアを取得
Zset
文字列メンバー(member)と浮動小数点数スコア(score)の間の秩序マッピング、要素の配列順序はスコアのサイズによって決定されます
単一の要素を追加、取得、削除します.要素は、スコア範囲(range)またはメンバーに基づいて取得されます.
1.4点賛データのRedisにおける格納フォーマット
Redisでは2種類のデータが格納されています.1つは、「いいね」をクリックした人、「いいねをクリックした人」、「いいねをクリックした人」、「いいねをクリックした人」、「いいねをクリックした人」の状態を記録したデータで、もう1つはユーザーごとに何回「いいね」をクリックしたかを簡単
「いいね」と「いいね」を記録する必要があり、「いいね」の状態(いいね、いいねの取り消し)もあるため、Redisのすべての「いいね」データを一定時間間隔で取り出し、次の「Redisデータフォーマット」の
点赞人のidは
したがって、ユーザが「いいね」をクリックすると、格納されたキーは
いいねをキャンセルします.保存されているキーは
データを取るときにキーを
ビジュアル化ツールRDMで見たのは、このようなものです.
1.5操作Redis
Redisの各種データフォーマットの操作方法はこの文章を見ることができて、書くのがとても良いです.
具体的な操作方法を
RedisService.java
実装クラスRedisServiceImpl.java
使用するツールクラスと列挙クラス
RedisKeyUtilsは、一定のルールに基づいてkeyを生成するために使用されます.
LikedStatusEnumユーザーの称賛状態の列挙クラス
二、データベース設計
データベース・テーブルには、少なくとも3つのフィールドが含まれます.プライマリキーidを加えて、作成時間、修正時間でいいです.
テーブル文
対応するオブジェクト
三、データベース操作
操作データベースもインタフェースにカプセル化
LikedService
LikedServiceImpl実装クラス
データベースの操作はこれだけで、主に削除して調べます.
四、オープンタイミングタスクの永続化データベースへの保存
タイミングタスク依存 を追加プロファイル作成 実行タスクを記述するクラスは、 から継承される.
タイミングタスクで
以上が点賛機能の設計と実現であり、不足点は皆さんによろしくお願いします.
より良い実装案があれば、コメントエリアでの交流を歓迎します.
コードはオープンソースプロジェクト
coderiver中国語名河コードは、プログラマーとデザイナーにプロジェクト協力を提供するプラットフォームです.フロントエンド、バックエンド、モバイル開発者、デザイナー、プロダクトマネージャにかかわらず、プラットフォーム上でプロジェクトを公開し、同じパートナーと協力してプロジェクトを完了することができます.
coderiver河コードはプログラマー宿屋に似ているが、主な目的は各細分化分野の人材間の技術交流を便利にし、共同で成長し、多くの人が協力してプロジェクトを完成することである.金銭取引には触れない.
PC端末(Vue、React)、モバイルH 5(Vue、React)、ReactNativeのハイブリッド開発、Androidオリジナル、微信ウィジェット、javaバックエンドを含むフルプラットフォーム型フルスタックプロジェクトを計画しており、注目を集めたい.
プロジェクトアドレス:github.com/cachecats/c…
あなたの励ましは私の前進の最大の動力で、いいねを歓迎して、小さい星を送ることを歓迎します✨ ~
いいねはシステム全体の小さなモジュールとして、コードは
user-service
ユーザーサービスの下にあります.本稿ではSpringCloudに基づいて,ユーザが「いいね」を発し,「いいね」を取り消した後,まずRedisに格納し,2時間おきにRedisからいいねデータを読み出してデータベースに書き込み,永続化して格納する.
いいね機能は多くのシステムにありますが、機能が小さいのを見ないで、よく考えなければならないことが多いです.
いいね、いいねを取り消すのは高頻度の操作で、毎回データベースを読み書きすると、大量の操作がデータベースの性能に影響するので、キャッシュが必要です.
どのくらいRedisから一度データを取ってデータベースに保存するかは、プロジェクトの実際の状況によって決まりますが、私は一時的に2時間設定しました.
プロジェクトのニーズは、誰が「いいね」をクリックしたのかを確認する必要があるので、「いいね」をクリックした人や「いいね」をクリックした人を保存するには、簡単にカウントすることはできません.
文章は4つの部分に分けて紹介します.
一、Redisキャッシュの設計と実現
1.1 Redis設置及び運転
Redisのインストールは、関連するチュートリアルを参照してください.
DockerをインストールしてRedisを実行すると言います
docker run -d -p 6379:6379 redis:4.0.8
Redisがインストールされている場合は、コマンドラインを開き、Redisを起動するコマンドを入力します.
redis-server
1.2 RedisとSpringBootプロジェクトの統合
pom.xml
に依存
org.springframework.boot
spring-boot-starter-data-redis
@EnableCaching
@SpringBootApplication
@EnableDiscoveryClient
@EnableSwagger2
@EnableFeignClients(basePackages = "com.solo.coderiver.project.client")
@EnableCaching
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
RedisConfig
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import java.net.UnknownHostException;
@Configuration
public class RedisConfig {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate redisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
Jackson2JsonRedisSerializer
これでRedisのSpringBootプロジェクトでの構成が完了し、快適に使用できます.
1.3 Redisのデータ構造タイプ
Redisは、String(文字列)、List(リスト)、Set(集合)、Hash(ハッシュ)、Zset(整列集合)の5つの異なるデータ構造タイプとの間のキーのマッピングを格納することができる.
この5つのデータ構造タイプについて簡単に説明します.
構造タイプ
構造ストレージの値
構造の読み書き能力
String
文字列、整数または浮動小数点数
文字列または文字列の一部全体に対して操作を実行します.オブジェクトと浮動小数点数の自己増加(increment)または自己減少(decrement)
List
チェーンテーブルの各ノードに文字列が含まれているチェーンテーブル
チェーンテーブルの両端から要素をプッシュまたはポップアップします.オフセット量に基づいてチェーンテーブルをトリミングする(trim);単一または複数の要素を読み込みます.値に基づいて要素を検索または削除
Set
文字列を含む無秩序コレクタ(unorderedcollection)であり、含まれる各文字列はユニークで異なる
単一の要素を追加、取得、削除します.エレメントがコレクションに存在するかどうかを確認します.交差、並列、差分セットを計算します.コレクションからランダムに要素を取得する
Hash
キー値ペアを含む無秩序分散リスト
単一のキー値ペアを追加、取得、削除します.すべてのキー値ペアを取得
Zset
文字列メンバー(member)と浮動小数点数スコア(score)の間の秩序マッピング、要素の配列順序はスコアのサイズによって決定されます
単一の要素を追加、取得、削除します.要素は、スコア範囲(range)またはメンバーに基づいて取得されます.
1.4点賛データのRedisにおける格納フォーマット
Redisでは2種類のデータが格納されています.1つは、「いいね」をクリックした人、「いいねをクリックした人」、「いいねをクリックした人」、「いいねをクリックした人」、「いいねをクリックした人」の状態を記録したデータで、もう1つはユーザーごとに何回「いいね」をクリックしたかを簡単
「いいね」と「いいね」を記録する必要があり、「いいね」の状態(いいね、いいねの取り消し)もあるため、Redisのすべての「いいね」データを一定時間間隔で取り出し、次の「Redisデータフォーマット」の
Hash
が最適であることを分析した.Hash
のデータはすべて1つのキーに存在するため、このキーを通じてすべての点賛データを簡単に取り出すことができます.このキーの中のデータはキー値のペアの形式に保存することもでき、いいね人、いいね人、いいね状態を保存するのに便利です.点赞人のidは
likedPostId
,点赞人のidはlikedUserId
,点赞时状态は1,キャンセル点赞状态は0とする.点賛人idと被点賛人idをキーとし、2つのidの間を::
で区切り、点賛状態を値とする.したがって、ユーザが「いいね」をクリックすると、格納されたキーは
likedUserId::likedPostId
であり、対応する値は1である.いいねをキャンセルします.保存されているキーは
likedUserId::likedPostId
で、対応する値は0です.データを取るときにキーを
::
で切ると2つのidが得られ、便利です.ビジュアル化ツールRDMで見たのは、このようなものです.
1.5操作Redis
Redisの各種データフォーマットの操作方法はこの文章を見ることができて、書くのがとても良いです.
具体的な操作方法を
RedisService
インタフェースにカプセル化RedisService.java
import com.solo.coderiver.user.dataobject.UserLike;
import com.solo.coderiver.user.dto.LikedCountDTO;
import java.util.List;
public interface RedisService {
/**
* 。 1
* @param likedUserId
* @param likedPostId
*/
void saveLiked2Redis(String likedUserId, String likedPostId);
/**
* 。 0
* @param likedUserId
* @param likedPostId
*/
void unlikeFromRedis(String likedUserId, String likedPostId);
/**
* Redis
* @param likedUserId
* @param likedPostId
*/
void deleteLikedFromRedis(String likedUserId, String likedPostId);
/**
* 1
* @param likedUserId
*/
void incrementLikedCount(String likedUserId);
/**
* 1
* @param likedUserId
*/
void decrementLikedCount(String likedUserId);
/**
* Redis
* @return
*/
List getLikedDataFromRedis() ;
/**
* Redis
* @return
*/
List getLikedCountFromRedis() ;
}
実装クラスRedisServiceImpl.java
import com.solo.coderiver.user.dataobject.UserLike;
import com.solo.coderiver.user.dto.LikedCountDTO;
import com.solo.coderiver.user.enums.LikedStatusEnum;
import com.solo.coderiver.user.service.LikedService;
import com.solo.coderiver.user.service.RedisService;
import com.solo.coderiver.user.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class RedisServiceImpl implements RedisService {
@Autowired
RedisTemplate redisTemplate;
@Autowired
LikedService likedService;
@Override
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());
}
@Override
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());
}
@Override
public void deleteLikedFromRedis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
}
@Override
public void incrementLikedCount(String likedUserId) {
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, 1);
}
@Override
public void decrementLikedCount(String likedUserId) {
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1);
}
@Override
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();
// likedUserId,likedPostId
String[] split = key.split("::");
String likedUserId = split[0];
String likedPostId = split[1];
Integer value = (Integer) entry.getValue();
// UserLike
UserLike userLike = new UserLike(likedUserId, likedPostId, value);
list.add(userLike);
// list Redis
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
}
return list;
}
@Override
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();
// LikedCountDT
String key = (String)map.getKey();
LikedCountDTO dto = new LikedCountDTO(key, (Integer) map.getValue());
list.add(dto);
// Redis
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key);
}
return list;
}
}
使用するツールクラスと列挙クラス
RedisKeyUtilsは、一定のルールに基づいてkeyを生成するために使用されます.
public class RedisKeyUtils {
// key
public static final String MAP_KEY_USER_LIKED = "MAP_USER_LIKED";
// key
public static final String MAP_KEY_USER_LIKED_COUNT = "MAP_USER_LIKED_COUNT";
/**
* id id key。 222222::333333
* @param likedUserId id
* @param likedPostId id
* @return
*/
public static String getLikedKey(String likedUserId, String likedPostId){
StringBuilder builder = new StringBuilder();
builder.append(likedUserId);
builder.append("::");
builder.append(likedPostId);
return builder.toString();
}
}
LikedStatusEnumユーザーの称賛状態の列挙クラス
package com.solo.coderiver.user.enums;
import lombok.Getter;
/**
*
*/
@Getter
public enum LikedStatusEnum {
LIKE(1, " "),
UNLIKE(0, " / "),
;
private Integer code;
private String msg;
LikedStatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
二、データベース設計
データベース・テーブルには、少なくとも3つのフィールドが含まれます.プライマリキーidを加えて、作成時間、修正時間でいいです.
テーブル文
create table `user_like`(
`id` int not null auto_increment,
`liked_user_id` varchar(32) not null comment ' id',
`liked_post_id` varchar(32) not null comment ' id',
`status` tinyint(1) default '1' comment ' ,0 ,1 ',
`create_time` timestamp not null default current_timestamp comment ' ',
`update_time` timestamp not null default current_timestamp on update current_timestamp comment ' ',
primary key(`id`),
INDEX `liked_user_id`(`liked_user_id`),
INDEX `liked_post_id`(`liked_post_id`)
) comment ' ';
対応するオブジェクト
UserLike
import com.solo.coderiver.user.enums.LikedStatusEnum;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
*
*/
@Entity
@Data
public class UserLike {
// id
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// id
private String likedUserId;
// id
private String likedPostId;
// .
private Integer status = LikedStatusEnum.UNLIKE.getCode();
public UserLike() {
}
public UserLike(String likedUserId, String likedPostId, Integer status) {
this.likedUserId = likedUserId;
this.likedPostId = likedPostId;
this.status = status;
}
}
三、データベース操作
操作データベースもインタフェースにカプセル化
LikedService
import com.solo.coderiver.user.dataobject.UserLike;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface LikedService {
/**
*
* @param userLike
* @return
*/
UserLike save(UserLike userLike);
/**
*
* @param list
*/
List saveAll(List list) ;
/**
* id ( )
* @param likedUserId id
* @param pageable
* @return
*/
Page getLikedListByLikedUserId(String likedUserId, Pageable pageable) ;
/**
* id ( )
* @param likedPostId
* @param pageable
* @return
*/
Page getLikedListByLikedPostId(String likedPostId, Pageable pageable) ;
/**
* id
* @param likedUserId
* @param likedPostId
* @return
*/
UserLike getByLikedUserIdAndLikedPostId(String likedUserId, String likedPostId);
/**
* Redis
*/
void transLikedFromRedis2DB();
/**
* Redis
*/
void transLikedCountFromRedis2DB();
}
LikedServiceImpl実装クラス
import com.solo.coderiver.user.dataobject.UserInfo;
import com.solo.coderiver.user.dataobject.UserLike;
import com.solo.coderiver.user.dto.LikedCountDTO;
import com.solo.coderiver.user.enums.LikedStatusEnum;
import com.solo.coderiver.user.repository.UserLikeRepository;
import com.solo.coderiver.user.service.LikedService;
import com.solo.coderiver.user.service.RedisService;
import com.solo.coderiver.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Slf4j
public class LikedServiceImpl implements LikedService {
@Autowired
UserLikeRepository likeRepository;
@Autowired
RedisService redisService;
@Autowired
UserService userService;
@Override
@Transactional
public UserLike save(UserLike userLike) {
return likeRepository.save(userLike);
}
@Override
@Transactional
public List saveAll(List list) {
return likeRepository.saveAll(list);
}
@Override
public Page getLikedListByLikedUserId(String likedUserId, Pageable pageable) {
return likeRepository.findByLikedUserIdAndStatus(likedUserId, LikedStatusEnum.LIKE.getCode(), pageable);
}
@Override
public Page getLikedListByLikedPostId(String likedPostId, Pageable pageable) {
return likeRepository.findByLikedPostIdAndStatus(likedPostId, LikedStatusEnum.LIKE.getCode(), pageable);
}
@Override
public UserLike getByLikedUserIdAndLikedPostId(String likedUserId, String likedPostId) {
return likeRepository.findByLikedUserIdAndLikedPostId(likedUserId, likedPostId);
}
@Override
@Transactional
public void transLikedFromRedis2DB() {
List list = redisService.getLikedDataFromRedis();
for (UserLike like : list) {
UserLike ul = getByLikedUserIdAndLikedPostId(like.getLikedUserId(), like.getLikedPostId());
if (ul == null){
// ,
save(like);
}else{
// ,
ul.setStatus(like.getStatus());
save(ul);
}
}
}
@Override
@Transactional
public void transLikedCountFromRedis2DB() {
List list = redisService.getLikedCountFromRedis();
for (LikedCountDTO dto : list) {
UserInfo user = userService.findById(dto.getId());
// ,
if (user != null){
Integer likeNum = user.getLikeNum() + dto.getCount();
user.setLikeNum(likeNum);
//
userService.updateInfo(user);
}
}
}
}
データベースの操作はこれだけで、主に削除して調べます.
四、オープンタイミングタスクの永続化データベースへの保存
タイミングタスク
Quartz
は強力で、それを使用します.Quartz
使用手順:
org.springframework.boot
spring-boot-starter-quartz
package com.solo.coderiver.user.config;
import com.solo.coderiver.user.task.LikeTask;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
private static final String LIKE_TASK_IDENTITY = "LikeTaskQuartz";
@Bean
public JobDetail quartzDetail(){
return JobBuilder.newJob(LikeTask.class).withIdentity(LIKE_TASK_IDENTITY).storeDurably().build();
}
@Bean
public Trigger quartzTrigger(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
// .withIntervalInSeconds(10) //
.withIntervalInHours(2) //
.repeatForever();
return TriggerBuilder.newTrigger().forJob(quartzDetail())
.withIdentity(LIKE_TASK_IDENTITY)
.withSchedule(scheduleBuilder)
.build();
}
}
QuartzJobBean
package com.solo.coderiver.user.task;
import com.solo.coderiver.user.service.LikedService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
*/
@Slf4j
public class LikeTask extends QuartzJobBean {
@Autowired
LikedService likedService;
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("LikeTask-------- {}", sdf.format(new Date()));
// Redis
likedService.transLikedFromRedis2DB();
likedService.transLikedCountFromRedis2DB();
}
}
タイミングタスクで
LikedService
カプセル化メソッドを直接呼び出してデータ同期を完了する.以上が点賛機能の設計と実現であり、不足点は皆さんによろしくお願いします.
より良い実装案があれば、コメントエリアでの交流を歓迎します.
コードはオープンソースプロジェクト
CodeRiver
から出て、全プラットフォーム型全スタック精品オープンソースプロジェクトの構築に力を入れている.coderiver中国語名河コードは、プログラマーとデザイナーにプロジェクト協力を提供するプラットフォームです.フロントエンド、バックエンド、モバイル開発者、デザイナー、プロダクトマネージャにかかわらず、プラットフォーム上でプロジェクトを公開し、同じパートナーと協力してプロジェクトを完了することができます.
coderiver河コードはプログラマー宿屋に似ているが、主な目的は各細分化分野の人材間の技術交流を便利にし、共同で成長し、多くの人が協力してプロジェクトを完成することである.金銭取引には触れない.
PC端末(Vue、React)、モバイルH 5(Vue、React)、ReactNativeのハイブリッド開発、Androidオリジナル、微信ウィジェット、javaバックエンドを含むフルプラットフォーム型フルスタックプロジェクトを計画しており、注目を集めたい.
プロジェクトアドレス:github.com/cachecats/c…
あなたの励ましは私の前進の最大の動力で、いいねを歓迎して、小さい星を送ることを歓迎します✨ ~